> ## Documentation Index
> Fetch the complete documentation index at: https://docs.salesive.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Webhook deliveries

> List your app's delivery attempts, replay one from its stored identifiers, and send a synthetic app/test event.

## Authentication

These routes are for the **app owner's merchant session**, never an `app_` token:

```http theme={null}
Authorization: Bearer <merchant-session-token>
```

Every call checks that the app belongs to the signed-in developer. The log holds no request or
response bodies, no headers, no signatures and no secrets. Each row is one attempt: the first try,
each retry, each replay and each test.

## List deliveries

```http theme={null}
GET /api/v1/apps/developer/:id/webhook-deliveries?status=failed&limit=50
```

| Parameter | Notes |
| - | - |
| `topic` | An exact topic such as `orders/fulfilled`. |
| `status` | `failed` or `delivered`. Omit for both. |
| `limit` | 1 to 100. Default 50. |
| `cursor` | The `next` value from the previous page. The older `before` name is also accepted. |

```json theme={null}
{
  "status": 200,
  "success": true,
  "message": "Webhook deliveries",
  "data": {
    "items": [
      {
        "_id": "66b1f0a3c2d4e5f6a7b8c9d0",
        "installation": "66b1f0a3c2d4e5f6a7b8c9d1",
        "shop": "6680aabbccddeeff00112200",
        "environment": "production",
        "topic": "orders/fulfilled",
        "resource": "orders",
        "resourceId": "66b1f0a3c2d4e5f6a7b8c9d2",
        "attempt": 2,
        "ok": false,
        "responseStatus": 500,
        "durationMs": 812,
        "error": null,
        "url": "https://yourapp.com/webhooks/salesive",
        "createdAt": "2026-11-07T09:41:12.000Z"
      }
    ],
    "retentionDays": 14,
    "next": "2026-11-07T09:41:12.000Z"
  }
}
```

`url` is the target without its query string or fragment. `error` is a short transport message, never
a response body. `next` is `null` when the page was not full.

## Replay one delivery

```http theme={null}
POST /api/v1/apps/developer/:id/webhook-deliveries/:deliveryId/replay
```

```json theme={null}
{
  "status": 200,
  "success": true,
  "message": "Replay queued",
  "data": {
    "queued": true,
    "topic": "orders/fulfilled",
    "rebuilt": true,
    "message": "The event is rebuilt from its stored identifiers. The original payload is not stored."
  }
}
```

The log holds no body, so a replay **rebuilds** the notify-only envelope from the stored topic,
resource, `resourceId` and shop. It gets a **new event id**, so it is a new delivery rather than a
byte-for-byte copy; a dedupe check keyed on the original `id` will not suppress it. The replay goes
to the installation's current URL and is signed with the current secret for that environment, with
one attempt and no retries.

You can replay up to **30 deliveries an hour** per app. Over the limit returns `429`. `POST
/api/v1/apps/developer/:id/webhook-deliveries/:deliveryId/resend` is an accepted older name for the
same operation.

| Status | Meaning |
| - | - |
| `404` | The app is not yours, or the delivery id does not belong to it. |
| `429` | More than 30 replays in the last hour. |

## Send a test event

```http theme={null}
POST /api/v1/apps/developer/:id/webhook-test
Content-Type: application/json

{ "topic": "app/test" }
```

Sends one synthetic `app/test` event to one active installation. It carries `test: true`, the
installation id as `resourceId` and no store record, so it can never leak real data.

```json theme={null}
{
  "status": 200,
  "success": true,
  "message": "Test event queued",
  "data": {
    "queued": true,
    "topic": "app/test",
    "installationId": "66b1f0a3c2d4e5f6a7b8c9d1"
  }
}
```

* `topic` is optional and must be `app/test` if present. Any other topic returns `400`.
* `installationId` is optional. Without it the most recent active installation is used.
* The app must have a webhook URL and at least one active installation, or the call returns `400`.
* One attempt, no retries. Up to **10 test events an hour** per app; over the limit returns `429`.

## Retention

Rows are removed after **14 days** by a TTL index. `retentionDays` in the list response repeats that
number. The [developer analytics](https://docs.salesive.com/apps-api/developer-analytics.md) webhook totals read the same rows,
so they cover at most the last 14 days.

## Next steps

> [card] [Webhooks](https://docs.salesive.com/apps-api/webhooks.md)
>
> Topics, signatures and retry rules.

> [card] [Developer analytics](https://docs.salesive.com/apps-api/developer-analytics.md)
>
> The totals that sit on top of this log.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.