Inkbox

> # Documentation index
> Fetch the complete documentation index at: https://inkbox.ai/sitemap.xml
> Use this file to discover all available pages before exploring further.

---

# Webhook Deliveries
description: Inspect the webhook delivery log and replay missed deliveries to their subscription's current URL

---


# Webhook Deliveries

Every time Inkbox POSTs an event to one of your endpoints, it records the attempt in a **delivery log**: the signed request body that was sent, the HTTP response your endpoint returned (or the transport error, if it never responded), how long it took, and whether the row was a replay. Use this log to see exactly what was — or wasn't — delivered, and to re-send a delivery your endpoint missed.

The log covers both [subscription](/docs/api/webhooks/subscriptions) deliveries (`message.*`, `text.*`, `imessage.*`) and the per-number `phone.incoming_call` deliveries. Subscription deliveries carry a `webhook_subscription_id`; incoming-call deliveries instead carry a `phone_number_id` and are **not replayable** (their response body drives live call routing, so there's nothing meaningful to replay).

## Auth

| Caller | Visibility |
| :--- | :--- |
| [Admin-scoped API key](/docs/api-keys) | Every delivery in the organization. |
| Human session via the [Inkbox Console](https://inkbox.ai/console) | Every delivery in the organization. |
| Claimed [agent-scoped API key](/docs/api-keys) | Deliveries for subscriptions and numbers belonging to that agent's identity. |

---

## List deliveries `GET`


List logged delivery attempts visible to the caller, newest first. Returns an object with a `deliveries` array — not a bare array.

### Query parameters

| Parameter | Type | Description |
| :--- | :--- | :--- |
| `subscription_id` | UUID | Filter to one subscription's deliveries. |
| `phone_number_id` | UUID | Filter to a phone number's incoming-call deliveries. |
| `event_type` | string | Filter by event type (e.g. `message.received`). |
| `success` | boolean | `true` returns only deliveries with a 2xx response; `false` returns failures (non-2xx or no response). |
| `limit` | integer | Page size, `1`–`200`. Defaults to `50`. |
| `offset` | integer | Row offset for pagination. Defaults to `0`. |

Filters AND-combine.

### Response (200)

```json
{
    "deliveries": [
        {
            "id": "0a4e2c11-9f3b-4d8a-bf21-7a1e2c3d4e5f",
            "organization_id": "org_2abc123def456",
            "webhook_subscription_id": "9e1b3f2d-c4a6-4f8e-91bf-71d2c2e4f0a1",
            "phone_number_id": null,
            "event_id": "evt_8f2c1a9b7d6e5f4a3b2c1d0e",
            "event_type": "message.received",
            "url": "https://yourapp.example.com/webhooks/inkbox",
            "request_payload": "{\\"event_type\\": \\"message.received\\", \\"timestamp\\": \\"2026-04-10T18:00:00Z\\", \\"data\\": {}}",
            "response_status": 200,
            "response_body": "ok",
            "error_detail": null,
            "duration_ms": 142,
            "is_replay": false,
            "created_at": "2026-04-10T18:00:01Z"
        }
    ]
}
```

### Code examples

**cURL**

```bash
curl -X GET "https://inkbox.ai/api/v1/webhooks/deliveries?success=false&limit=50" \\
    -H "X-API-Key: YOUR_API_KEY"
```

**JavaScript**

```javascript
const url = new URL("https://inkbox.ai/api/v1/webhooks/deliveries");
url.searchParams.set("success", "false");
const response = await fetch(url, {
    headers: { "X-API-Key": "YOUR_API_KEY" },
});
const { deliveries } = await response.json();
```

**Python**

```python
import requests

response = requests.get(
    "https://inkbox.ai/api/v1/webhooks/deliveries",
    headers={"X-API-Key": "YOUR_API_KEY"},
    params={"success": False, "limit": 50},
)
deliveries = response.json()["deliveries"]
```

---

## Replay delivery `POST`


Re-deliver a logged event to its subscription's **current** URL, and record a new delivery row (with `is_replay` set to `true`) for the attempt.

Replay reuses the original event's envelope `event_id`, so it only recovers a **miss**: a [well-behaved receiver](/docs/webhooks) that already processed the original event dedupes the replay away by `event_id`. Replay does **not** force reprocessing — it helps only endpoints that never successfully received the event in the first place. The request is freshly signed with a new request id and timestamp so it passes your receiver's freshness check.

### Path parameters

| Parameter | Type | Description |
| :--- | :--- | :--- |
| `delivery_id` | UUID | The logged delivery to replay. |

### Response (200)

Returns the new replay delivery row (`is_replay: true`). See [Delivery object](#delivery-object).

### Error responses

| Status | Reason |
| :--- | :--- |
| `404` | Delivery does not exist or is not visible to the caller. |
| `422` | The delivery is an incoming-call delivery, which is not replayable. |
| `409` | The subscription is no longer active. |
| `409` | The subscription no longer subscribes to this event type. |

### Code examples

**cURL**

```bash
curl -X POST "https://inkbox.ai/api/v1/webhooks/deliveries/DELIVERY_ID/replay" \\
    -H "X-API-Key: YOUR_API_KEY"
```

**JavaScript**

```javascript
const response = await fetch(
    `https://inkbox.ai/api/v1/webhooks/deliveries/${deliveryId}/replay`,
    {
        method: "POST",
        headers: { "X-API-Key": "YOUR_API_KEY" },
    }
);
const delivery = await response.json();
```

**Python**

```python
import requests

response = requests.post(
    f"https://inkbox.ai/api/v1/webhooks/deliveries/{delivery_id}/replay",
    headers={"X-API-Key": "YOUR_API_KEY"},
)
delivery = response.json()
```

---

## Delivery object

| Field | Type | Description |
| :--- | :--- | :--- |
| `id` | UUID | Unique delivery identifier. |
| `organization_id` | string | Owning organization (e.g. `"org_2abc123def456"`). |
| `webhook_subscription_id` | UUID \| null | Subscription this delivery targeted. `null` for incoming-call deliveries. |
| `phone_number_id` | UUID \| null | Phone number for incoming-call deliveries (which have no subscription). `null` otherwise. |
| `event_id` | string | The envelope event id (`evt_…`) shared across every delivery of the same event. For incoming-call rows this is the call id. |
| `event_type` | string | The event type that was delivered. |
| `url` | string | The destination URL the request was sent to. |
| `request_payload` | string | The raw signed request body that was delivered. |
| `response_status` | integer \| null | HTTP status your endpoint returned. `null` if the request never got a response. |
| `response_body` | string \| null | A truncated snippet of your endpoint's response body. |
| `error_detail` | string \| null | Transport error summary, when the request failed to complete. |
| `duration_ms` | integer \| null | How long the attempt took, in milliseconds. |
| `is_replay` | boolean | `true` if this row was produced by a manual replay. |
| `created_at` | string | ISO 8601 timestamp the attempt was made. |

The `event_id` is the same `evt_…` value carried in the webhook payload envelope, so you can correlate a delivery row with the event your endpoint received and use it for idempotent processing.

## Related

- [Webhook subscriptions reference](/docs/api/webhooks/subscriptions) — subscription CRUD
- [Webhooks guide](/docs/webhooks) — payload verification, typed receiver examples, idempotency
- [Signing keys](/docs/signing-keys) — the org-level HMAC key used to sign webhook bodies
