ThunderPhone 2.0 is live.Self-serve, from 2¢/min.Read the announcement

Developer

Webhook Deliveries

Inspect recent webhook delivery outcomes without exposing event payloads or transcripts.

Use the delivery history endpoint to confirm whether ThunderPhone attempted a webhook, the safe outcome category, and whether another retry is scheduled. It merges the recommended webhook endpoint system with the legacy single-URL call-finished webhook.

The same recent history appears in the dashboard under Agents → select an agent → Webhooks → Recent deliveries. Each row identifies the endpoint label and the safe URL origin used by its latest attempt.

This history is recent operational state, not an immutable audit log. The endpoint system stores only the latest outcome for each queued delivery, and deleting an endpoint also deletes its delivery rows. Retrieve any records you need to retain before deleting an endpoint.

List deliveries

GET /v1/developer/webhook-deliveries

Requires an organization admin. Authenticate with a server API key, an admin session token, or OAuth authorized for the organization with integrations:read. OAuth access still uses the current user's live organization role, so members cannot read this route.

cURL
curl "https://api.thunderphone.com/v1/developer/webhook-deliveries?status=retrying&limit=50" \
  -H "Authorization: Bearer sk_live_YOUR_API_KEY"
Python
deliveries = requests.get(
    "https://api.thunderphone.com/v1/developer/webhook-deliveries",
    headers={"Authorization": "Bearer sk_live_YOUR_API_KEY"},
    params={"agent_id": 42, "since": "2026-09-18T00:00:00Z"},
).json()

Filters

ParameterTypeDescription
agent_idintegerDeliveries associated with one agent
endpoint_idUUID or legacyOne endpoint, or only the legacy single-URL webhook
event_typestringExact event type, such as telephony.complete
statusstringdelivered, retrying, or failed
sinceRFC 3339 timestampResult-change window; defaults to 7 days ago and is clamped to at most 30 days ago
limitintegerPage size, 1–50; defaults to 50
cursorstringOpaque next_cursor from the previous page; reuse it only with the same organization, filters, since, and limit

Response

{
  "results": [
    {
      "source": "endpoint",
      "endpoint_id": "00000000-0000-4000-8000-000000000001",
      "endpoint_label": "n8n production",
      "url": "https://n8n.example.com",
      "event_type": "telephony.complete",
      "call_id": 1001,
      "status": "retrying",
      "attempt_count": 2,
      "http_status": 404,
      "failure_category": "http_error",
      "last_attempt_at": "2026-09-19T16:20:00Z",
      "next_retry_at": "2026-09-19T16:25:00Z"
    }
  ],
  "limit": 50,
  "has_more": false,
  "next_cursor": null
}

source is endpoint for the endpoint-based system and legacy for the single-URL call-finished webhook. Legacy rows use endpoint_id: "legacy". url is the sanitized origin used by the most recent recorded attempt. It is null for rows created before destination snapshots were available. http_status can be null when no response was received or the legacy success path did not retain the status code. failure_category is timeout, dns, tls, connection, http_error, other, or null when there is no failure. Legacy rows created before destination snapshots were added return a generic label and url: null. next_retry_at is present only while the delivery is retrying.

Interpreting common failures

  • 404 from n8n: confirm the workflow is active, the webhook uses POST, and the production URL is configured instead of n8n's test URL.
  • 401 or 403: the destination rejected authentication. Check its credentials, authorization policy, and ThunderPhone signature verification.
  • timeout: the destination did not answer before the webhook timeout. Check its availability and response time.
  • dns: check that the configured hostname resolves publicly.
  • tls: check the certificate chain, hostname, and certificate expiry.
  • connection: check that the destination accepts and keeps HTTPS connections.
  • other: the stored failure could not be safely classified; no raw response is exposed.