Webhooks
Webhooks
If you pass a webhook_url to Submit, the server sends exactly one signed POST when all lines in the batch have finished enriching.
Delivery guarantees
- Completion is detected on the fly, without blocking enrichment.
- Delivery runs through a dedicated Temporal workflow. It is deduplicated (a single webhook is sent per project, even under concurrent completions) and retried with backoff.
- After retries are exhausted, the webhook is marked failed and remains inspectable.
Payload
The body is minimal:
{
"project_id": "...",
"event": "enrichment.completed",
"status": "completed",
"counts": { "total": 100, "enriched": 100, "failed": 0 }
}The webhook is a notification only. It does not carry the enriched data: after receiving it, the client must still call ExportCSV (see Project Lifecycle) to retrieve the results.
Verifying the signature
Each delivery is signed with a secret specific to your organization:
- Header
X-Dango-Signature: sha256=...is the HMAC-SHA256 of your organization’s webhook secret over the string"{timestamp}.{body}". - The same timestamp is also sent in the
X-Dango-Timestampheader, which guards against replay attacks.
To verify, recompute the HMAC-SHA256 over "{X-Dango-Timestamp}.{raw body}" using your webhook secret and compare it against the X-Dango-Signature header.
SSRF protection. Because the webhook URL is client-provided, delivery refuses to connect to loopback, private, or link-local addresses. The check runs on the resolved IP, which also defeats DNS rebinding. A
webhook_url therefore cannot be used to reach 169.254.169.254, localhost, or the internal network.