Webhooks
Real-time event notifications
Receive real-time event notifications from SkyAIApp without polling the API.
Overview
Webhooks allow you to subscribe to specific events (such as agent completion, model fallback, cost threshold exceeded), and SkyAIApp will send an HTTP POST request to your configured URL when events occur.
Setup
- 1
Create Endpoint
Create an endpoint on your server to receive POST requests
- 2
Configure in Dashboard
Add webhook URL and select events in SkyAIApp Dashboard
- 3
Verify Signature
Verify requests are from SkyAIApp
- 4
Handle Events
Execute actions based on event type
Available Events
| Event | Triggered When |
|---|---|
| route.completed | Routing request completed |
| route.failed | Routing request failed |
| agent.step.completed | Agent step completed |
| agent.run.completed | Agent run completed |
| agent.run.failed | Agent run failed |
| model.fallback | Model fallback triggered |
| guardrail.blocked | Content blocked by guardrails |
| usage.threshold | Usage exceeds threshold |
Payload Format
{
"id": "evt_abc123",
"type": "route.completed",
"created": 1734220800,
"data": {
"route_id": "route_xyz789",
"model": "gpt-5.2-instant",
"provider": "openai",
"goal": "cost",
"usage": {
"prompt_tokens": 42,
"completion_tokens": 156,
"total_tokens": 198
},
"routing": {
"selected_model": "gpt-5.2-instant",
"fallback_model": null,
"cache_hit": false,
"latency_ms": 847,
"cost_usd": 0.00156
},
"metadata": {
"user_id": "user_123",
"session_id": "session_456"
}
}
}Signature Verification
Security Note
Always verify webhook signatures to prevent forged requests.
Each webhook request includes a signature in the header:
X-SkyAI-Signature: t=1734220800,v1=5257a869e7ecebeda32affa62cdca3fa51cad7e77a0e56ff536d0ce8e108d8bdVerification Steps
- 1.Extract timestamp (t) and signature (v1)
- 2.Construct signed string: timestamp + '.' + raw_body
- 3.Calculate HMAC-SHA256 using webhook secret
- 4.Compare computed signature with received signature
- 5.Verify timestamp is within reasonable range (5 minutes)
Implementation Examples
Node.js / Express
import crypto from 'crypto';
import express from 'express';
const app = express();
const WEBHOOK_SECRET = process.env.SKYAI_WEBHOOK_SECRET;
app.post('/webhooks/skyai',
express.raw({ type: 'application/json' }),
(req, res) => {
const signature = req.headers['x-skyai-signature'];
const [timestamp, receivedSig] = signature.split(',').map(s => s.split('=')[1]);
// Verify signature
const signedString = `${timestamp}.${req.body}`;
const expectedSig = crypto
.createHmac('sha256', WEBHOOK_SECRET)
.update(signedString)
.digest('hex');
if (expectedSig !== receivedSig) {
return res.status(401).send('Invalid signature');
}
// Verify timestamp (within 5 minutes)
const now = Math.floor(Date.now() / 1000);
if (Math.abs(now - parseInt(timestamp)) > 300) {
return res.status(401).send('Timestamp too old');
}
// Handle event
const event = JSON.parse(req.body);
console.log('Event received:', event.type);
switch (event.type) {
case 'route.completed':
// Handle routing completion
break;
case 'agent.run.completed':
// Handle agent completion
break;
// ... other events
}
res.json({ received: true });
}
);Python / FastAPI
import hashlib
import hmac
import time
from fastapi import FastAPI, Request, HTTPException
app = FastAPI()
WEBHOOK_SECRET = os.environ["SKYAI_WEBHOOK_SECRET"]
@app.post("/webhooks/skyai")
async def skyai_webhook(request: Request):
signature = request.headers.get("X-SkyAI-Signature")
parts = dict(item.split("=") for item in signature.split(","))
timestamp, received_sig = parts["t"], parts["v1"]
# Verify signature
body = await request.body()
signed_string = f"{timestamp}.{body.decode()}"
expected_sig = hmac.new(
WEBHOOK_SECRET.encode(),
signed_string.encode(),
hashlib.sha256
).hexdigest()
if not hmac.compare_digest(expected_sig, received_sig):
raise HTTPException(status_code=401, detail="Invalid signature")
# Verify timestamp
if abs(time.time() - int(timestamp)) > 300:
raise HTTPException(status_code=401, detail="Timestamp too old")
# Handle event
event = await request.json()
print(f"Event received: {event['type']}")
if event["type"] == "route.completed":
# Handle routing completion
pass
elif event["type"] == "agent.run.completed":
# Handle agent completion
pass
return {"received": True}Retry Logic
If your endpoint returns a non-2xx status code, SkyAIApp will automatically retry.
Retry Strategy
- • Maximum 3 retries
- • Exponential backoff: 1min, 5min, 30min
- • Stop retrying after timeout
- • View retry history in dashboard
💡 Tip: Ensure your endpoint is idempotent to safely handle duplicate requests.
Get Started with Webhooks
Configure your first webhook in the dashboard
Was this page helpful?
Let us know how we can improve