Skip to main content

Overview

Webhooks allow you to receive HTTP callbacks when events occur in your Rotavision account. Instead of polling for status updates, webhooks push data to your server in real-time.

Supported Events

EventDescription
analysis.completedFairness analysis job finished
analysis.failedFairness analysis job failed
alert.triggeredGuardian alert threshold exceeded
alert.resolvedGuardian alert returned to normal
extraction.completedDocument extraction finished
extraction.failedDocument extraction failed
workflow.completedOrchestrate workflow finished
workflow.failedOrchestrate workflow failed

Setting Up Webhooks

Via Dashboard

  1. Go to Settings → Webhooks in your dashboard
  2. Click Add Endpoint
  3. Enter your endpoint URL
  4. Select events to subscribe to
  5. Save and note your signing secret

Via API

curl -X POST https://api.rotavision.com/v1/webhooks \
  -H "Authorization: Bearer rv_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://your-app.com/webhooks/rotavision",
    "events": ["analysis.completed", "alert.triggered"],
    "description": "Production webhook"
  }'
Response:
{
  "id": "wh_abc123",
  "url": "https://your-app.com/webhooks/rotavision",
  "events": ["analysis.completed", "alert.triggered"],
  "secret": "whsec_xyz789...",
  "status": "active",
  "created_at": "2026-02-01T10:00:00Z"
}
Store your webhook secret securely. You’ll need it to verify incoming webhooks.

Webhook Payload

All webhooks follow this structure:
{
  "id": "evt_abc123",
  "type": "analysis.completed",
  "created_at": "2026-02-01T10:30:00Z",
  "data": {
    "id": "analysis_xyz789",
    "model_id": "loan-approval-v2",
    "overall_score": 0.82,
    "status": "completed"
  }
}

Verifying Signatures

All webhooks are signed using HMAC-SHA256. Verify the signature to ensure the webhook came from Rotavision:
import hmac
import hashlib

def verify_webhook(payload: bytes, signature: str, secret: str) -> bool:
    expected = hmac.new(
        secret.encode(),
        payload,
        hashlib.sha256
    ).hexdigest()

    return hmac.compare_digest(f"sha256={expected}", signature)

# In your webhook handler
@app.post("/webhooks/rotavision")
def handle_webhook(request):
    payload = request.body
    signature = request.headers.get("X-Rotavision-Signature")

    if not verify_webhook(payload, signature, WEBHOOK_SECRET):
        return Response(status=401)

    event = json.loads(payload)
    # Process event...

Handling Webhooks

Best Practices

Return a 200 response within 5 seconds. Process the event asynchronously if needed.
@app.post("/webhooks/rotavision")
def handle_webhook(request):
    # Verify and enqueue
    event = verify_and_parse(request)
    queue.enqueue(process_event, event)
    return Response(status=200)  # Respond immediately
Webhooks may be delivered multiple times. Use the id field for idempotency.
def process_event(event):
    if redis.sismember("processed_events", event["id"]):
        return  # Already processed

    # Process event...

    redis.sadd("processed_events", event["id"])
    redis.expire("processed_events", 86400)  # 24 hour TTL
Always verify the X-Rotavision-Signature header before processing.
If processing fails, return a non-2xx status. We’ll retry with exponential backoff.

Retry Policy

Failed webhook deliveries are retried with exponential backoff:
AttemptDelay
1Immediate
21 minute
35 minutes
430 minutes
52 hours
68 hours
724 hours
After 7 failed attempts, the webhook is marked as failed and you’ll receive an email notification.

Testing Webhooks

Using the CLI

rotavision webhooks trigger analysis.completed \
  --endpoint wh_abc123 \
  --data '{"model_id": "test-model"}'

Using the Dashboard

  1. Go to Settings → Webhooks
  2. Click on your endpoint
  3. Click Send Test Event
  4. Select an event type
  5. Review the delivery log

Event Reference

analysis.completed

{
  "id": "evt_abc123",
  "type": "analysis.completed",
  "created_at": "2026-02-01T10:30:00Z",
  "data": {
    "id": "analysis_xyz789",
    "model_id": "loan-approval-v2",
    "overall_score": 0.82,
    "bias_detected": true,
    "metrics_summary": {
      "demographic_parity": 0.78,
      "equalized_odds": 0.91,
      "calibration": 0.85
    },
    "report_url": "https://dashboard.rotavision.com/reports/analysis_xyz789"
  }
}

alert.triggered

{
  "id": "evt_def456",
  "type": "alert.triggered",
  "created_at": "2026-02-01T10:30:00Z",
  "data": {
    "id": "alert_uvw123",
    "monitor_id": "mon_abc789",
    "model_id": "recommendation-v3",
    "metric": "prediction_drift",
    "value": 0.25,
    "threshold": 0.1,
    "severity": "high",
    "message": "Significant prediction drift detected (PSI: 0.25)"
  }
}

extraction.completed

{
  "id": "evt_ghi789",
  "type": "extraction.completed",
  "created_at": "2026-02-01T10:30:00Z",
  "data": {
    "id": "extract_mno456",
    "document_type": "aadhaar",
    "confidence": 0.97,
    "fields": {
      "name": "राहुल शर्मा",
      "name_english": "Rahul Sharma",
      "dob": "1990-05-15",
      "gender": "Male",
      "aadhaar_number": "XXXX-XXXX-1234"
    }
  }
}