Webhooks #
All /webhooks endpoints: list, create, update, delete, rotate-secret, deliveries, stats.
The /webhooks/* endpoints manage outbound webhook subscriptions. For the
verification model see Webhooks; for a
worked walkthrough see Webhook setup.
GET /webhooks/
GET /webhooks/List every webhook registered on the account.
curl -u "$DD_KEY:$DD_SECRET" \ https://api.datadistillers.com/api/v1/webhooks/
Returns an array of WebhookResponse:
[
{
"id": "wh_p7q8r9",
"url": "https://api.example.com/dd-webhook",
"description": "Production extraction events",
"events": ["extraction.completed", "extraction.failed"],
"is_active": true,
"created_at": "2026-04-01T00:00:00Z",
"updated_at": "2026-04-29T18:24:11Z"
}
]
Note: secret_key is never returned by GET. It's only shown at creation
and rotation.
POST /webhooks/
POST /webhooks/Register a new webhook.
curl -u "$DD_KEY:$DD_SECRET" \
-X POST https://api.datadistillers.com/api/v1/webhooks/ \
-H 'Content-Type: application/json' \
-d '{
"url": "https://api.example.com/dd-webhook",
"description": "Production extraction events",
"events": ["extraction.completed", "extraction.failed"]
}'
| Field | Required | Notes |
|---|---|---|
url | yes | HTTPS only. ≤ 2083 chars. Must resolve to a public IP. |
description | no | ≤ 255 chars. |
events | yes | Non-empty array of WebhookEventType. |
WebhookEventType is one of extraction.completed, extraction.failed,
artifact.processed.
Returns 201 Created + WebhookCreateResponse. The secret_key field is
shown exactly once; store it before discarding the response.
{
"id": "wh_p7q8r9",
"url": "https://api.example.com/dd-webhook",
"events": ["extraction.completed", "extraction.failed"],
"is_active": true,
"created_at": "2026-05-03T09:00:00Z",
"updated_at": "2026-05-03T09:00:00Z",
"secret_key": "whsec_b2c3d4e5f6…"
}
PATCH /webhooks/{id}
PATCH /webhooks/{id}Update url, description, active state, or subscribed events. Partial.
curl -u "$DD_KEY:$DD_SECRET" \
-X PATCH https://api.datadistillers.com/api/v1/webhooks/wh_p7q8r9 \
-H 'Content-Type: application/json' \
-d '{ "is_active": false }'
Changing the url re-runs SSRF + HTTPS validation; failed validation
returns 400.
Setting is_active: false stops new deliveries without deleting the record.
Useful for emergency pause without losing the secret or delivery history.
DELETE /webhooks/{id}
DELETE /webhooks/{id}Remove a webhook permanently.
curl -u "$DD_KEY:$DD_SECRET" \ -X DELETE https://api.datadistillers.com/api/v1/webhooks/wh_p7q8r9
Returns 204 No Content.
The jobs.webhook_id foreign key is SET NULL, so in-flight jobs complete
without notification rather than failing. Already-queued retries are
abandoned (the delivery worker skips the call when the webhook is gone).
POST /webhooks/{id}/rotate-secret
POST /webhooks/{id}/rotate-secretRotate the signing secret. The previous secret remains valid for a 24-hour overlap window so receivers have time to roll out the new value without gaps in verification.
curl -u "$DD_KEY:$DD_SECRET" \ -X POST https://api.datadistillers.com/api/v1/webhooks/wh_p7q8r9/rotate-secret
Returns the same shape as creation, with the new secret_key:
{
"id": "wh_p7q8r9",
"secret_key": "whsec_NEW_value_…",
"url": "https://api.example.com/dd-webhook",
"events": ["extraction.completed", "extraction.failed"]
}
During the 24h overlap window, your verifier should accept either secret. After the window expires, only the new key is valid.
GET /webhooks/{id}/deliveries
GET /webhooks/{id}/deliveriesPaginated delivery log for a webhook. Newest first.
| Param | Type | Default | Notes |
|---|---|---|---|
status_filter | success | failed | – | Filter by terminal outcome. |
event_type | string | – | e.g. extraction.completed. |
limit | integer | 50 | 1–200. |
offset | integer | 0 | Standard offset pagination. |
curl -u "$DD_KEY:$DD_SECRET" \ 'https://api.datadistillers.com/api/v1/webhooks/wh_p7q8r9/deliveries?status_filter=failed&limit=20'
Each entry includes attempt_number (1–4), response_status_code,
is_success, and duration_ms. Use these to triage delivery failures:
401s usually mean signature verification, 5xx means handler crashes,
sustained 4xx-on-attempt-1 with no retries means your handler is rejecting
the call format.
GET /webhooks/{id}/stats
GET /webhooks/{id}/statsAggregated delivery statistics over a rolling window.
| Param | Type | Default | Notes |
|---|---|---|---|
days | integer | 30 | 1–90. |
curl -u "$DD_KEY:$DD_SECRET" \ 'https://api.datadistillers.com/api/v1/webhooks/wh_p7q8r9/stats?days=7'
Response:
{
"total_events": 8421,
"success_rate": 99.12,
"failures_last_24h": 3,
"avg_latency_ms": 142
}
Wire success_rate < 99 and failures_last_24h > N into your monitoring.
A drop in success rate is usually a sign of a recently shipped handler bug
or an upstream incident on the destination side.
Errors
| Status | Cause |
|---|---|
400 | Invalid URL (HTTP, private IP, > 2083 chars), empty events. |
401 | Auth missing or invalid. |
403 | Webhook belongs to a different account. |
404 | webhook_id doesn't exist. |
422 | Body shape didn't validate. |