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

# GET /v1/subscriptions/:id/events

> List delivery history for a subscription. Each event shows its status, attempt count, last HTTP response, and the payload that was sent.

This endpoint returns the delivery history for a subscription in reverse chronological order. Each item in the list represents one webhook event — including the payload that was delivered, the current delivery status, how many attempts were made, and the last HTTP response received from your endpoint.

## Request

```
GET /v1/subscriptions/:id/events
```

### Path parameters

<ParamField path="id" type="string" required>
  The subscription ID (e.g. `sub_2QkP9aB7xN...`).
</ParamField>

### Query parameters

<ParamField query="limit" type="integer">
  Number of events to return per page. Must be between 1 and 200. Defaults to `50`.
</ParamField>

<ParamField query="nextPageToken" type="string">
  Opaque cursor returned by the previous response. Pass this value verbatim to fetch the next page. Omit or leave empty to start from the most recent events.
</ParamField>

```bash theme={null}
curl "https://api.offthehook.dev/v1/subscriptions/sub_2QkP9aB7xN.../events" \
  -H "Authorization: Bearer oth_YOUR_API_KEY"
```

## Response

**200 OK** — a paginated list of `EventView` objects.

```json theme={null}
{
  "items": [
    {
      "id": "evt_8xN9kP2QbA...",
      "subscriptionId": "sub_2QkP9aB7xN...",
      "kind": "wallet.transfer.broadcasted",
      "chainId": "tron:mainnet",
      "status": "delivered",
      "attempts": 1,
      "deliveryCount": 1,
      "responseStatus": 200,
      "responseBody": "OK",
      "payload": { "id": "evt_8xN9kP2QbA...", "kind": "wallet.transfer.broadcasted", "date": "...", "data": {} },
      "dateCreated": "2026-05-08T12:34:56Z"
    }
  ],
  "nextPageToken": null
}
```

<ResponseField name="items[].id" type="string">
  Unique event ID. This value is sent in the `webhook-id` delivery header — use it as your idempotency key to deduplicate retried deliveries.
</ResponseField>

<ResponseField name="items[].subscriptionId" type="string">
  The subscription this event belongs to.
</ResponseField>

<ResponseField name="items[].kind" type="string">
  The event type, e.g. `wallet.transfer.broadcasted` or `service.ping`.
</ResponseField>

<ResponseField name="items[].chainId" type="string | null">
  CAIP-2 identifier for the chain this event originated on. `null` for service events like `service.ping` that are not chain-specific.
</ResponseField>

<ResponseField name="items[].status" type="string">
  Current delivery status. One of:

  * `pending` — queued and awaiting delivery or in the retry schedule.
  * `delivered` — your endpoint returned a 2xx response.
  * `failed` — all automatic retry attempts were exhausted without a successful delivery.
</ResponseField>

<ResponseField name="items[].attempts" type="integer">
  Number of delivery attempts in the current dispatch cycle. This counter resets to `0` each time you call [POST /retry](/api/events/retry).
</ResponseField>

<ResponseField name="items[].deliveryCount" type="integer">
  Monotonically increasing count of successful deliveries for this event across all dispatch cycles. Normally `0` or `1`; greater than `1` only if the event was retried after a prior successful delivery.
</ResponseField>

<ResponseField name="items[].responseStatus" type="integer | null">
  The HTTP status code returned by your endpoint on the most recent delivery attempt. `null` if no attempt has been made yet or the request did not receive an HTTP response (e.g. network timeout).
</ResponseField>

<ResponseField name="items[].responseBody" type="string | null">
  The response body returned by your endpoint, truncated for storage. `null` if no response body was received.
</ResponseField>

<ResponseField name="items[].payload" type="object">
  The exact Standard Webhooks envelope that was (or will be) sent to your endpoint, including `id`, `kind`, `date`, and `data`.
</ResponseField>

<ResponseField name="items[].dateCreated" type="string">
  ISO 8601 timestamp of when this event was first created.
</ResponseField>

<ResponseField name="nextPageToken" type="string | null">
  Cursor for the next page. `null` when you have reached the last page.
</ResponseField>

## Errors

| Code                       | HTTP | Description                                                                      |
| -------------------------- | ---- | -------------------------------------------------------------------------------- |
| `not_found`                | 404  | The subscription ID does not exist or belongs to a different API key.            |
| `invalid_pagination_token` | 400  | The `nextPageToken` value is malformed or was issued by a different API version. |
| `unauthorized`             | 401  | The `Authorization` header is missing or the key is invalid.                     |
