Beta

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.

Real-time
HMAC Signed
Auto Retry

Setup

  1. 1

    Create Endpoint

    Create an endpoint on your server to receive POST requests

  2. 2

    Configure in Dashboard

    Add webhook URL and select events in SkyAIApp Dashboard

  3. 3

    Verify Signature

    Verify requests are from SkyAIApp

  4. 4

    Handle Events

    Execute actions based on event type

Available Events

EventTriggered When
route.completedRouting request completed
route.failedRouting request failed
agent.step.completedAgent step completed
agent.run.completedAgent run completed
agent.run.failedAgent run failed
model.fallbackModel fallback triggered
guardrail.blockedContent blocked by guardrails
usage.thresholdUsage 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=5257a869e7ecebeda32affa62cdca3fa51cad7e77a0e56ff536d0ce8e108d8bd

Verification Steps

  1. 1.Extract timestamp (t) and signature (v1)
  2. 2.Construct signed string: timestamp + '.' + raw_body
  3. 3.Calculate HMAC-SHA256 using webhook secret
  4. 4.Compare computed signature with received signature
  5. 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

Webhooks | SkyAIApp Docs — SkyAIApp