Overview
Dancity sends an HTTPPOST request to your configured webhook URL whenever a transaction event occurs. This allows you to keep your system in sync without polling the transactions endpoint.
Setting up your webhook URL
- Go to your API Key page
- Enter your webhook URL under Webhook URL — it must be HTTPS
- Click Save Webhook URL
Your webhook URL must be publicly accessible. Localhost URLs will not work in
production. Use a tool like ngrok during local development.
Event payload
All webhook payloads share the same envelope structure:Event types
| Event | Description |
|---|---|
transaction.success | A VAS purchase or transfer completed successfully |
transaction.failed | A transaction failed |
transaction.pending | Transaction is awaiting confirmation |
wallet.funded | Your wallet was funded |
wallet.debited | Your wallet was debited |
Verifying webhook signatures
Every webhook request includes anX-Dancity-Signature header. You must verify this signature to confirm the request is genuinely from Dancity and has not been tampered with.
The signature is computed as:
webhookSecret is shown when you first generate your API key. Store it securely — it is not shown again.
Verification examples
Retry policy
If your endpoint returns any HTTP status other than2xx, Dancity will retry the delivery with exponential backoff:
| Attempt | Delay |
|---|---|
| 1st retry | 30 seconds |
| 2nd retry | 5 minutes |
| 3rd retry | 30 minutes |
| 4th retry | 2 hours |
| 5th retry | 8 hours |
Best practices
Respond quickly
Respond quickly
Return a
200 response as fast as possible — ideally within 5 seconds.
Move any heavy processing (database writes, emails) to an async job/queue.Make handlers idempotent
Make handlers idempotent
You may receive the same event more than once due to retries. Use
transactionId or reference as a unique key to ensure you don’t process
the same transaction twice.Log everything
Log everything
Save the raw payload and the
X-Dancity-Signature header for every incoming
webhook. This makes debugging failed deliveries much easier.Test locally with ngrok
Test locally with ngrok
Run
ngrok http 3000 to get a public HTTPS URL that tunnels to your local
server. Set that URL as your webhook URL during development.