Webhooks
Webhooks
Section titled “Webhooks”UniCraft provides webhook functionality for real-time notifications and event handling, allowing you to stay informed about important events and integrate with external systems.
Overview
Section titled “Overview”Webhooks allow you to receive real-time notifications when specific events occur in UniCraft:
- Request Events: Notifications when requests are completed or fail
- Cost Events: Alerts when spending limits are reached
- Provider Events: Notifications about provider status changes
- Error Events: Alerts when errors occur
- Custom Events: Notifications for custom-defined events
Setting Up Webhooks
Section titled “Setting Up Webhooks”1. Create a Webhook
Section titled “1. Create a Webhook”// Create a webhook via APIconst webhook = await fetch("https://api.unicraft.com/v1/webhooks", { method: "POST", headers: { Authorization: "Bearer your-unicraft-api-key", "Content-Type": "application/json", }, body: JSON.stringify({ name: "Production Alerts", url: "https://your-app.com/webhooks/unicraft", events: [ "request.completed", "request.failed", "cost.exceeded", "provider.unavailable", ], secret: "your-webhook-secret", enabled: true, }),});
const webhookData = await webhook.json();console.log("Webhook created:", webhookData);2. Via Dashboard
Section titled “2. Via Dashboard”- Log into your UniCraft dashboard
- Navigate to Settings → Webhooks
- Click Add Webhook
- Configure the webhook:
- Name: Descriptive name for the webhook
- URL: Your endpoint URL
- Events: Select events to monitor
- Secret: Optional secret for verification
- Enabled: Toggle webhook on/off
Webhook Events
Section titled “Webhook Events”1. Request Events
Section titled “1. Request Events”Request Completed
Section titled “Request Completed”{ "event": "request.completed", "timestamp": "2024-01-20T10:30:00Z", "data": { "request_id": "req_123456789", "model": "gpt-3.5-turbo", "provider": "openai", "cost": 0.000042, "response_time": 1250, "tokens": { "prompt": 50, "completion": 25, "total": 75 }, "user_id": "user_123", "project_id": "proj_456" }}Request Failed
Section titled “Request Failed”{ "event": "request.failed", "timestamp": "2024-01-20T10:30:00Z", "data": { "request_id": "req_123456789", "model": "gpt-4", "provider": "openai", "error": { "type": "rate_limit_exceeded", "message": "Rate limit exceeded", "code": "rate_limit_exceeded" }, "retry_count": 3, "user_id": "user_123", "project_id": "proj_456" }}2. Cost Events
Section titled “2. Cost Events”Cost Exceeded
Section titled “Cost Exceeded”{ "event": "cost.exceeded", "timestamp": "2024-01-20T10:30:00Z", "data": { "budget_id": "budget_123", "budget_name": "Monthly AI Budget", "current_cost": 1050.0, "limit": 1000.0, "excess": 50.0, "period": "monthly", "user_id": "user_123", "project_id": "proj_456" }}Daily Cost Alert
Section titled “Daily Cost Alert”{ "event": "cost.daily_alert", "timestamp": "2024-01-20T10:30:00Z", "data": { "date": "2024-01-20", "daily_cost": 85.0, "daily_limit": 100.0, "percentage": 85.0, "user_id": "user_123", "project_id": "proj_456" }}3. Provider Events
Section titled “3. Provider Events”Provider Unavailable
Section titled “Provider Unavailable”{ "event": "provider.unavailable", "timestamp": "2024-01-20T10:30:00Z", "data": { "provider": "openai", "status": "unavailable", "reason": "service_outage", "estimated_recovery": "2024-01-20T11:00:00Z", "affected_models": ["gpt-4", "gpt-3.5-turbo"] }}Provider Recovered
Section titled “Provider Recovered”{ "event": "provider.recovered", "timestamp": "2024-01-20T11:00:00Z", "data": { "provider": "openai", "status": "available", "downtime_duration": 1800, "affected_models": ["gpt-4", "gpt-3.5-turbo"] }}4. Error Events
Section titled “4. Error Events”High Error Rate
Section titled “High Error Rate”{ "event": "error.high_rate", "timestamp": "2024-01-20T10:30:00Z", "data": { "error_rate": 0.15, "threshold": 0.1, "time_window": "5m", "provider": "openai", "model": "gpt-4", "error_types": [ { "type": "rate_limit_exceeded", "count": 25 }, { "type": "invalid_request", "count": 10 } ] }}Webhook Security
Section titled “Webhook Security”1. Signature Verification
Section titled “1. Signature Verification”UniCraft signs webhook payloads with your secret:
const crypto = require("crypto");
function verifyWebhookSignature(payload, signature, secret) { const expectedSignature = crypto .createHmac("sha256", secret) .update(payload) .digest("hex");
return crypto.timingSafeEqual( Buffer.from(signature), Buffer.from(expectedSignature) );}
// Express.js exampleapp.post("/webhooks/unicraft", (req, res) => { const signature = req.headers["x-unicraft-signature"]; const payload = JSON.stringify(req.body);
if (!verifyWebhookSignature(payload, signature, process.env.WEBHOOK_SECRET)) { return res.status(401).send("Invalid signature"); }
// Process webhook console.log("Webhook received:", req.body); res.status(200).send("OK");});2. IP Whitelisting
Section titled “2. IP Whitelisting”Restrict webhook access to specific IP addresses:
const allowedIPs = ["192.168.1.100", "10.0.0.50"];
function verifyIP(req, res, next) { const clientIP = req.ip || req.connection.remoteAddress;
if (!allowedIPs.includes(clientIP)) { return res.status(403).send("IP not allowed"); }
next();}
app.post("/webhooks/unicraft", verifyIP, (req, res) => { // Process webhook});Webhook Endpoint Implementation
Section titled “Webhook Endpoint Implementation”1. Express.js Example
Section titled “1. Express.js Example”const express = require("express");const crypto = require("crypto");const app = express();
app.use(express.json());
// Webhook endpointapp.post("/webhooks/unicraft", (req, res) => { const signature = req.headers["x-unicraft-signature"]; const payload = JSON.stringify(req.body);
// Verify signature if (!verifyWebhookSignature(payload, signature, process.env.WEBHOOK_SECRET)) { return res.status(401).send("Invalid signature"); }
const event = req.body;
// Handle different events switch (event.event) { case "request.completed": handleRequestCompleted(event.data); break; case "request.failed": handleRequestFailed(event.data); break; case "cost.exceeded": handleCostExceeded(event.data); break; case "provider.unavailable": handleProviderUnavailable(event.data); break; default: console.log("Unknown event:", event.event); }
res.status(200).send("OK");});
function handleRequestCompleted(data) { console.log("Request completed:", data.request_id); // Update database, send notifications, etc.}
function handleRequestFailed(data) { console.log("Request failed:", data.request_id, data.error); // Log error, alert team, etc.}
function handleCostExceeded(data) { console.log("Cost exceeded:", data.budget_name, data.excess); // Send alert, pause requests, etc.}
function handleProviderUnavailable(data) { console.log("Provider unavailable:", data.provider); // Switch to backup provider, alert team, etc.}
app.listen(3000, () => { console.log("Webhook server running on port 3000");});2. Python Flask Example
Section titled “2. Python Flask Example”from flask import Flask, request, jsonifyimport hmacimport hashlibimport json
app = Flask(__name__)
def verify_webhook_signature(payload, signature, secret): expected_signature = hmac.new( secret.encode('utf-8'), payload.encode('utf-8'), hashlib.sha256 ).hexdigest()
return hmac.compare_digest(signature, expected_signature)
@app.route('/webhooks/unicraft', methods=['POST'])def webhook(): signature = request.headers.get('X-UniCraft-Signature') payload = json.dumps(request.json)
# Verify signature if not verify_webhook_signature(payload, signature, os.environ['WEBHOOK_SECRET']): return jsonify({'error': 'Invalid signature'}), 401
event = request.json
# Handle different events if event['event'] == 'request.completed': handle_request_completed(event['data']) elif event['event'] == 'request.failed': handle_request_failed(event['data']) elif event['event'] == 'cost.exceeded': handle_cost_exceeded(event['data']) elif event['event'] == 'provider.unavailable': handle_provider_unavailable(event['data'])
return jsonify({'status': 'OK'})
def handle_request_completed(data): print(f"Request completed: {data['request_id']}") # Update database, send notifications, etc.
def handle_request_failed(data): print(f"Request failed: {data['request_id']} - {data['error']}") # Log error, alert team, etc.
def handle_cost_exceeded(data): print(f"Cost exceeded: {data['budget_name']} - ${data['excess']}") # Send alert, pause requests, etc.
def handle_provider_unavailable(data): print(f"Provider unavailable: {data['provider']}") # Switch to backup provider, alert team, etc.
if __name__ == '__main__': app.run(port=3000)Webhook Management
Section titled “Webhook Management”1. List Webhooks
Section titled “1. List Webhooks”// Get all webhooksconst webhooks = await fetch("https://api.unicraft.com/v1/webhooks", { headers: { Authorization: "Bearer your-unicraft-api-key", },});
const webhookList = await webhooks.json();console.log("Webhooks:", webhookList);2. Update Webhook
Section titled “2. Update Webhook”// Update webhookconst updatedWebhook = await fetch( "https://api.unicraft.com/v1/webhooks/webhook_123", { method: "PUT", headers: { Authorization: "Bearer your-unicraft-api-key", "Content-Type": "application/json", }, body: JSON.stringify({ name: "Updated Webhook", events: ["request.completed", "cost.exceeded"], enabled: true, }), });3. Delete Webhook
Section titled “3. Delete Webhook”// Delete webhookconst deleted = await fetch( "https://api.unicraft.com/v1/webhooks/webhook_123", { method: "DELETE", headers: { Authorization: "Bearer your-unicraft-api-key", }, });4. Test Webhook
Section titled “4. Test Webhook”// Test webhookconst test = await fetch( "https://api.unicraft.com/v1/webhooks/webhook_123/test", { method: "POST", headers: { Authorization: "Bearer your-unicraft-api-key", }, });
const testResult = await test.json();console.log("Test result:", testResult);Best Practices
Section titled “Best Practices”1. Webhook Design
Section titled “1. Webhook Design”- Idempotency: Make webhook handlers idempotent
- Retry Logic: Implement retry logic for failed webhooks
- Error Handling: Handle errors gracefully
- Logging: Log all webhook events for debugging
2. Security
Section titled “2. Security”- Signature Verification: Always verify webhook signatures
- HTTPS: Use HTTPS for webhook endpoints
- IP Whitelisting: Restrict access to known IPs
- Rate Limiting: Implement rate limiting on webhook endpoints
3. Performance
Section titled “3. Performance”- Async Processing: Process webhooks asynchronously
- Queue System: Use message queues for high-volume webhooks
- Monitoring: Monitor webhook performance and failures
- Scaling: Scale webhook endpoints based on load
4. Reliability
Section titled “4. Reliability”- Timeout Handling: Set appropriate timeouts
- Dead Letter Queue: Handle failed webhooks
- Monitoring: Monitor webhook delivery success rates
- Alerting: Set up alerts for webhook failures
Troubleshooting
Section titled “Troubleshooting”Common Issues
Section titled “Common Issues”-
Webhook Not Receiving Events
- Check webhook URL accessibility
- Verify webhook is enabled
- Check event configuration
-
Signature Verification Fails
- Verify webhook secret
- Check payload format
- Ensure proper signature generation
-
Webhook Timeouts
- Optimize webhook processing
- Increase timeout settings
- Use async processing
-
Duplicate Events
- Implement idempotency
- Use event IDs for deduplication
- Handle retries properly
Debug Tips
Section titled “Debug Tips”- Enable Logging: Log all webhook events
- Test Endpoints: Use webhook testing tools
- Monitor Delivery: Track webhook delivery success
- Check Logs: Review UniCraft webhook logs
Support
Section titled “Support”For support with webhooks:
- Documentation: UniCraft Docs
- API Reference: UniCraft API Docs
- Community: UniCraft Community
- Support: support@unicraft.com
Next Steps
Section titled “Next Steps”After setting up webhooks:
- Test Webhooks: Test all webhook events
- Monitor Delivery: Set up monitoring for webhook delivery
- Handle Events: Implement proper event handling
- Scale Infrastructure: Scale webhook endpoints as needed
- Document Processes: Document webhook handling procedures