Webhooks are automated HTTP POST requests sent by Cadana when events occur on the platform. Use them to get real-time updates for transactions, payroll, KYC, and more.
Webhook Structure
Every webhook follows this envelope structure:
{
"eventType": "transaction.succeeded",
"id": "e13b9e14-c062-42ea-8563-8fc9223b29b5",
"version": "1.0",
"timestamp": 1681006175,
"data": {
...
}
}
| Field | Description |
|---|
id | Unique webhook ID. Use this to deduplicate — retried webhooks are sent with the same id. |
eventType | The event type (e.g., transaction.succeeded). See Events for the full list. |
version | Webhook version |
timestamp | Unix timestamp when the webhook was sent |
data | Event-specific payload. See Events for payload structures. |
Getting Started
- Navigate to Settings → Developers → Webhooks in the Dashboard
- Click Add Webhook
- Enter the URL where you want to receive events
Handle Events
After registering an endpoint, Cadana sends an HTTP POST request to your URL every time a subscribed event occurs. Parse the eventType field to determine how to handle each event.
Respond Promptly
Your endpoint must return a 2xx status code to acknowledge receipt. Any response outside the 2xx range — including 3xx redirects — is treated as a failure and will trigger retries.
Respond with 200 OK immediately, then process the payload asynchronously via a message queue. This prevents timeouts.
Verifying Webhooks
Every webhook includes signature headers you should verify to confirm it was sent by Cadana.
| Header | Description |
|---|
svix-id | Unique message ID from the delivery provider |
svix-timestamp | Unix timestamp of the webhook |
svix-signature | HMAC-SHA256 signature of the payload |
Verification
Use the Svix libraries to verify signatures automatically:
import { Webhook } from "svix";
const wh = new Webhook("your-signing-secret");
const payload = wh.verify(body, headers);
from svix.webhooks import Webhook
wh = Webhook("your-signing-secret")
payload = wh.verify(body, headers)
wh, _ := svix.NewWebhook("your-signing-secret")
payload, _ := wh.Verify(body, headers)
Your signing secret is available in Settings → Developers → Webhooks in the Dashboard.
For manual verification, see the Svix manual verification docs.
Retry Policy
If your endpoint fails to respond with a 2xx status code, Cadana retries delivery with exponential backoff:
| Attempt | Delay |
|---|
| 1st retry | 5 seconds |
| 2nd retry | 5 minutes |
| 3rd retry | 30 minutes |
| 4th retry | 2 hours |
| 5th retry | 5 hours |
| 6th retry | 10 hours |
| 7th retry | 24 hours |
After all retries are exhausted (~3 days), the webhook is marked as failed.
Best Practices
- Respond immediately — Return
200 OK first, process asynchronously. Don’t do heavy work before responding.
- Deduplicate — Use the
id field to detect and skip duplicate deliveries. Retried webhooks keep the same id.
- Fetch the latest state — Webhooks can arrive out of order. After receiving an event, fetch the resource via API (e.g.,
GET /v1/payouts/{id}) to get the latest state.
- Implement reconciliation — Webhook delivery is not guaranteed. Periodically poll the API to catch any missed events.
- Verify signatures — Always verify the
svix-signature header before processing a webhook to prevent spoofing.