Webhook Setup
Receive webhooks from CueAPI, handle payloads, and respond correctly.
Overview
When a cue fires with webhook transport, CueAPI sends a signed HTTP POST to your callback URL with the cue's payload.
What CueAPI sends
POST https://your-endpoint.com/webhook
Content-Type: application/json
X-CueAPI-Signature: v1=a1b2c3d4...
X-CueAPI-Timestamp: 1710340800
X-CueAPI-Cue-Id: cue_abc123def456
X-CueAPI-Execution-Id: 550e8400-e29b-41d4-a716-446655440000
X-CueAPI-Scheduled-For: 2026-03-13T09:00:00Z
X-CueAPI-Attempt: 1
The body is your cue's payload as JSON.
Headers
| Header | Description |
|---|---|
X-CueAPI-Signature | HMAC-SHA256 signature (v1={hex} format) |
X-CueAPI-Timestamp | Unix timestamp of when the signature was created |
X-CueAPI-Cue-Id | The cue ID that triggered this execution |
X-CueAPI-Execution-Id | Unique execution ID for this specific fire |
X-CueAPI-Scheduled-For | The scheduled time for this execution |
X-CueAPI-Attempt | Attempt number (1 = first attempt, 2+ = retries) |
Responding correctly
Your endpoint must:
- Return 2xx (200, 201, 202, etc.) to indicate success
- Respond within 30 seconds — requests that take longer are treated as failures
- Be idempotent — CueAPI uses at-least-once delivery, so you may receive the same payload twice
python
# Flask example
@app.route("/webhook", methods=["POST"])
def handle_webhook():
payload = request.json
execution_id = request.headers.get("X-CueAPI-Execution-Id")
# Check idempotency (recommended)
if already_processed(execution_id):
return {"status": "already processed"}, 200
# Do the work
process_task(payload)
return {"status": "ok"}, 200What triggers retries
CueAPI retries when:
- Your endpoint returns 4xx or 5xx
- Your endpoint times out (no response within 30s)
- Connection fails (DNS resolution failure, connection refused, etc.)
CueAPI does not retry when:
- Your endpoint returns 2xx (even if the body indicates an error)
Testing locally
For local development, use a tunneling service to expose your local server:
bash
# Using ngrok
ngrok http 8000
# Create a cue pointing to the ngrok URL
curl -X POST https://api.cueapi.ai/v1/cues \
-H "Authorization: Bearer cue_sk_..." \
-d '{
"name": "test-webhook",
"schedule": {"type": "once", "at": "2026-03-14T10:00:00Z"},
"callback": {"url": "https://abc123.ngrok.io/webhook"}
}'Or use worker transport to avoid needing a public URL entirely.
Next steps
Verify webhook signatures
Verify that webhooks are actually from CueAPI, not a malicious third party.