Skip to main content

Delivery lifecycle

Every time a subscribed event fires, DeepSmith creates a delivery for each active webhook that matches the event type. Each delivery follows this lifecycle:

Delivery statuses

StatusDescription
deliveredSuccessfully delivered on the first attempt
recoveredFailed initially but succeeded on a retry attempt
failedAll 3 attempts failed
pendingDelivery is queued or in progress

Retry policy

Failed deliveries are retried automatically with exponential backoff:
AttemptDelayTotal elapsed
1stImmediate0s
2nd10 seconds~10s
3rd60 seconds~70s
A delivery is considered failed when your endpoint returns a non-2xx HTTP status code, the connection times out (15 second limit), or a connection error occurs.
If all 3 attempts fail, the delivery is marked as failed and the webhook’s consecutive_failures counter is incremented.

Auto-disable

When a webhook accumulates 10 consecutive failures, it is automatically disabled to protect your endpoint from unnecessary traffic. When a webhook is auto-disabled:
  • Its status changes to DISABLED
  • No further deliveries are sent
  • You can re-enable it from Settings > Webhooks, which resets the failure counter
Monitor the consecutive_failures field on your webhooks. If it’s climbing, check your endpoint’s health before it reaches 10 and gets disabled.

Viewing delivery history

Open a webhook from Settings > Webhooks and navigate to the Deliveries tab. You can filter deliveries by event type and status (delivered, failed, recovered).

Sample delivery log

{
  "code": 1260,
  "messages": "Webhook deliveries retrieved successfully.",
  "data": {
    "data": [
      {
        "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
        "webhook_id": "9f2a3b4c-5d6e-7f8a-9b0c-1d2e3f4a5b6c",
        "event_type": "content.status_updated",
        "payload": {
          "event": "content.status_updated",
          "timestamp": "2026-04-16T10:30:00+00:00",
          "workspace_id": "019d917f-5d2b-71e7-90f4-4b8bd1cfe98b",
          "is_test": false,
          "data": {
            "id": "7d0e1f2a-3b4c-5d6e-7f8a-9b0c1d2e3f4a",
            "title": "10 Strategies for Content Marketing in 2026",
            "status": "PUBLISHED",
            "slug": "content-marketing-strategies-2026"
          }
        },
        "http_status": 200,
        "response_body": "{\"received\":true}",
        "response_time_ms": 185,
        "attempt": 1,
        "max_attempts": 3,
        "delivery_status": "delivered",
        "successful": true,
        "is_test": false,
        "delivered_at": "2026-04-16T10:30:01.000000Z",
        "created_at": "2026-04-16T10:30:00.000000Z"
      },
      {
        "id": "b2c3d4e5-f6a7-8901-bcde-f12345678901",
        "webhook_id": "9f2a3b4c-5d6e-7f8a-9b0c-1d2e3f4a5b6c",
        "event_type": "agent_task.status_updated",
        "payload": {
          "event": "agent_task.status_updated",
          "timestamp": "2026-04-16T09:15:00+00:00",
          "workspace_id": "019d917f-5d2b-71e7-90f4-4b8bd1cfe98b",
          "is_test": false,
          "data": {
            "id": "6c5d4e3f-2a1b-0c9d-8e7f-6a5b4c3d2e1f",
            "name": "Write article: Content Marketing",
            "status": "SUCCEEDED"
          }
        },
        "http_status": 500,
        "response_body": "{\"error\":\"Internal Server Error\"}",
        "response_time_ms": 12500,
        "attempt": 3,
        "max_attempts": 3,
        "delivery_status": "failed",
        "successful": false,
        "is_test": false,
        "delivered_at": "2026-04-16T09:16:10.000000Z",
        "created_at": "2026-04-16T09:15:00.000000Z"
      }
    ],
    "links": {},
    "meta": {
      "current_page": 1,
      "last_page": 5,
      "per_page": 20,
      "total": 93
    }
  }
}

Delivery fields

FieldTypeDescription
iduuidDelivery ID
webhook_iduuidParent webhook ID
event_typestringEvent type that triggered this delivery
payloadobjectFull payload that was sent
http_statusinteger|nullHTTP response status (null for connection errors)
response_bodystring|nullResponse body (truncated to 2048 chars)
response_time_msinteger|nullResponse time in milliseconds
attemptintegerWhich attempt this was (1, 2, or 3)
max_attemptsintegerMaximum attempts (always 3)
delivery_statusstringComputed status: delivered, recovered, failed, or pending
successfulbooleanWhether the delivery succeeded
is_testbooleanWhether this was a test delivery
delivered_atdatetimeWhen the delivery was attempted
created_atdatetimeWhen the delivery was created

Retrying a failed delivery

From the delivery log, click Retry on any failed delivery. This re-queues the delivery with the original event type and payload. The new attempt appears as a separate entry in the delivery log.
{
  "code": 1261,
  "messages": "Webhook delivery retried successfully.",
  "data": {
    "id": "b2c3d4e5-f6a7-8901-bcde-f12345678901",
    "webhook_id": "9f2a3b4c-5d6e-7f8a-9b0c-1d2e3f4a5b6c",
    "event_type": "agent_task.status_updated",
    "payload": {
      "event": "agent_task.status_updated",
      "timestamp": "2026-04-16T09:15:00+00:00",
      "workspace_id": "019d917f-5d2b-71e7-90f4-4b8bd1cfe98b",
      "is_test": false,
      "data": {
        "id": "6c5d4e3f-2a1b-0c9d-8e7f-6a5b4c3d2e1f",
        "name": "Write article: Content Marketing",
        "status": "SUCCEEDED"
      }
    },
    "http_status": 500,
    "response_body": "{\"error\":\"Internal Server Error\"}",
    "response_time_ms": 12500,
    "attempt": 3,
    "max_attempts": 3,
    "delivery_status": "failed",
    "successful": false,
    "is_test": false,
    "delivered_at": "2026-04-16T09:16:10.000000Z",
    "created_at": "2026-04-16T09:15:00.000000Z"
  }
}
Only failed deliveries can be retried. The retry button is not available for successful deliveries.

Performance stats

The webhook detail page shows performance charts for Event deliveries (total vs. failed) and Response time (min, avg, max). You can switch between three time periods:
PeriodBucket sizeDescription
Last 24 hoursHourlyGood for investigating recent issues
This weekDailyDefault view for ongoing monitoring
Last 30 daysDailyLong-term health overview

Sample stats response

{
  "code": 1276,
  "messages": "Webhook stats retrieved successfully.",
  "data": {
    "deliveries": [
      { "date": "2026-04-10", "total": 12, "failed": 1 },
      { "date": "2026-04-11", "total": 15, "failed": 0 },
      { "date": "2026-04-12", "total": 8, "failed": 0 },
      { "date": "2026-04-13", "total": 11, "failed": 2 },
      { "date": "2026-04-14", "total": 14, "failed": 0 },
      { "date": "2026-04-15", "total": 10, "failed": 0 },
      { "date": "2026-04-16", "total": 13, "failed": 1 }
    ],
    "response_times": [
      { "date": "2026-04-10", "min": 85, "avg": 210, "max": 12500 },
      { "date": "2026-04-11", "min": 92, "avg": 180, "max": 340 },
      { "date": "2026-04-12", "min": 78, "avg": 195, "max": 290 },
      { "date": "2026-04-13", "min": 88, "avg": 1200, "max": 15000 },
      { "date": "2026-04-14", "min": 80, "avg": 175, "max": 310 },
      { "date": "2026-04-15", "min": 90, "avg": 200, "max": 350 },
      { "date": "2026-04-16", "min": 82, "avg": 250, "max": 4500 }
    ]
  }
}

Best practices

Return a 200 status code as fast as possible. Process the webhook payload asynchronously (e.g., queue a background job) rather than doing heavy work in the request handler. DeepSmith enforces a 15-second timeout.
Use the X-Webhook-Delivery header to deduplicate deliveries. Your endpoint may receive the same event more than once due to retries.
Check the error_rate on your webhooks and the performance charts regularly. A rising error rate indicates your endpoint may have issues.
Don’t process webhooks synchronously. Push them onto a queue (SQS, Redis, RabbitMQ) and process them asynchronously. This keeps your endpoint responsive and prevents timeouts.
Log incoming webhook payloads and your processing results. DeepSmith’s delivery history shows what was sent, but your logs capture how your application handled it.