Guides
Webhooks
Receive delivery, creative, billing, and reporting events at an HTTPS endpoint you register. Each webhook includes a signed JSON payload. Failed deliveries are retried, and signing keys can rotate with an overlap period.
Payload
Use webhooks when another application needs to respond to a change without repeatedly polling Riptide. A creative-approval event, for example, can update your team's review queue. The payload below identifies the event and creative; verify its signature and deduplicate its ID before acting on it.
POST https://hooks.acme.example/riptide
Content-Type: application/json
X-Riptide-Webhook-Timestamp: 1767225600
X-Riptide-Webhook-Signature-256: t=1767225600,v1=9f2c...e1
{ "id": "evt_01J...", "type": "creative.approved", "occurred_at": "2026-01-01T00:00:00Z",
"tenant_id": "1c9e...", "data": { "creative_id": "...", "ref": "spring-15s" } } | Event type | When |
|---|---|
delivery.impression, delivery.click | Per-event delivery notifications (subscribe narrowly; volume follows traffic). |
delivery.line_item_ended | A line item reached its end date or goal. |
delivery.alert_fired | A delivery alert rule fired (under-delivery, pacing, error rate). |
creative.approved, creative.rejected | Creative review outcomes. |
billing.invoice_created, billing.payment_failed | An invoice was created or a payment failed. |
reporting.scheduled_report_delivered | A scheduled report's result was delivered. |
Verify the signature
Each v1 value is HMAC-SHA256(secret, "<timestamp>.<raw body>"), hex
encoded. Recompute it under your secret over the exact bytes received, accept when any v1
matches, and require the timestamp to be within five minutes of your current time.
Deduplicate accepted events by ID before processing them. During rotation, the header
carries two v1 values, with the current secret first.
// Go (reference verifier in the repository: libs/webhooks)
mac := hmac.New(sha256.New, secret)
mac.Write([]byte(ts + "." + string(body)))
ok := hmac.Equal(mac.Sum(nil), providedV1)
# Python
expected = hmac.new(secret, f"{ts}.".encode() + body, hashlib.sha256).hexdigest()
ok = any(hmac.compare_digest(expected, v1) for v1 in provided_v1s) and abs(time.time() - int(ts)) < 300 Retries and rotation
The default policy allows five delivery attempts in total. After a non-2xx response or
timeout, retries wait 30 seconds, 1 minute, 2 minutes, and 4 minutes. After the last failed
attempt, replay the delivery from the API or console once you have fixed the cause.
Call rotateWebhookSecret to receive a new secret. Both secrets sign deliveries
during the grace period, allowing your receiver to switch keys.
| Operation | Purpose |
|---|---|
createWebhookSubscription | Register the URL and event types. Save the signing secret returned in the response; it is shown once. |
listWebhookSubscriptions, getWebhookSubscription, updateWebhookSubscription, deleteWebhookSubscription | Manage subscriptions. |
listWebhookDeliveries, replayWebhookDelivery | Inspect attempts and replay a delivery by id. |
rotateWebhookSecret | Start a rotation: deliveries carry two signatures until the grace window ends. |
Connect a webhook receiver
Start with a receiver that verifies signatures and stores accepted events. Use the Python SDK to register its public HTTPS endpoint and the event types your application needs.