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

# Delivery History

> Query webhook delivery attempts and inspect individual delivery records.

Every time TagPay dispatches a webhook to a subscription endpoint, a delivery record is created. You can use these records to monitor delivery health, debug failures, and identify events that need replaying.

***

## List delivery attempts

Retrieve a paginated list of webhook delivery attempts for your merchant account.

```
GET https://api.tagpay.ng/v1/merchant/webhook/deliveries
```

### Query parameters

<ParamField query="subscriptionId" type="string">
  Filter deliveries to a specific subscription. Retrieve subscription IDs from [List subscriptions](/api/webhooks/subscriptions#list-subscriptions).
</ParamField>

<ParamField query="status" type="string">
  Filter by delivery status. One of `pending`, `success`, `failed`, or `retrying`.
</ParamField>

<ParamField query="eventType" type="string">
  Filter by event type, e.g. `transaction.success`.
</ParamField>

<ParamField query="startDate" type="string">
  ISO 8601 date string. Returns deliveries created on or after this timestamp.
</ParamField>

<ParamField query="endDate" type="string">
  ISO 8601 date string. Returns deliveries created on or before this timestamp.
</ParamField>

<ParamField query="page" type="number" default="1">
  Page number for pagination.
</ParamField>

<ParamField query="limit" type="number" default="20">
  Number of records per page.
</ParamField>

### Response

<ResponseField name="status" type="boolean">
  `true` when the request succeeded.
</ResponseField>

<ResponseField name="data" type="object[]">
  Array of delivery records sorted by `createdAt` descending.

  <Expandable title="Delivery object">
    <ResponseField name="id" type="string">
      Unique delivery ID (UUID).
    </ResponseField>

    <ResponseField name="subscriptionId" type="string">
      ID of the subscription this delivery belongs to.
    </ResponseField>

    <ResponseField name="merchantId" type="string">
      Your merchant ID.
    </ResponseField>

    <ResponseField name="eventType" type="string">
      The event type that triggered this delivery, e.g. `transaction.success`.
    </ResponseField>

    <ResponseField name="status" type="string">
      Current delivery status. See [Delivery statuses](#delivery-statuses).
    </ResponseField>

    <ResponseField name="attempts" type="number">
      Number of delivery attempts made so far.
    </ResponseField>

    <ResponseField name="maxAttempts" type="number">
      Maximum allowed attempts. Always `3`.
    </ResponseField>

    <ResponseField name="httpStatusCode" type="number">
      The HTTP status code returned by your endpoint on the last attempt. `null` if no attempt has completed.
    </ResponseField>

    <ResponseField name="responseTimeMs" type="number">
      Round-trip response time in milliseconds for the last attempt. `null` if unavailable.
    </ResponseField>

    <ResponseField name="response" type="object">
      The response body returned by your endpoint, stored for debugging. `null` if unavailable.
    </ResponseField>

    <ResponseField name="errorMessage" type="string">
      Error description if the last attempt failed. `null` on success.
    </ResponseField>

    <ResponseField name="reference" type="string">
      The transaction or event reference that triggered this delivery.
    </ResponseField>

    <ResponseField name="payload" type="object">
      The exact JSON payload that was (or will be) sent to your endpoint.
    </ResponseField>

    <ResponseField name="nextRetryAt" type="string">
      ISO 8601 timestamp of the next scheduled retry. `null` if no retry is scheduled.
    </ResponseField>

    <ResponseField name="deliveredAt" type="string">
      ISO 8601 timestamp of the successful delivery. `null` if not yet delivered.
    </ResponseField>

    <ResponseField name="createdAt" type="string">
      ISO 8601 timestamp when the delivery record was created.
    </ResponseField>

    <ResponseField name="subscription" type="object">
      Summary of the associated subscription.

      <Expandable title="Subscription summary">
        <ResponseField name="id" type="string">Subscription ID.</ResponseField>
        <ResponseField name="url" type="string">Endpoint URL.</ResponseField>
        <ResponseField name="description" type="string">Subscription description.</ResponseField>
      </Expandable>
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="metadata" type="object">
  Pagination metadata.

  <Expandable title="Pagination">
    <ResponseField name="page" type="number">Current page.</ResponseField>
    <ResponseField name="limit" type="number">Records per page.</ResponseField>
    <ResponseField name="total" type="number">Total matching records.</ResponseField>
    <ResponseField name="totalPages" type="number">Total pages.</ResponseField>
  </Expandable>
</ResponseField>

<RequestExample>
  ```bash cURL theme={null}
  curl --request GET \
    --url "https://api.tagpay.ng/v1/merchant/webhook/deliveries?status=failed&page=1&limit=20" \
    --header "Authorization: Bearer <token>"
  ```
</RequestExample>

<ResponseExample>
  ```json 200 theme={null}
  {
    "status": true,
    "message": "Deliveries retrieved successfully",
    "data": [
      {
        "id": "del_f6a7b8c9-d0e1-2345-fabc-678901234567",
        "subscriptionId": "sub_e5f6a7b8-c9d0-1234-efab-567890123456",
        "merchantId": "merch_001",
        "eventType": "transaction.success",
        "status": "failed",
        "attempts": 3,
        "maxAttempts": 3,
        "httpStatusCode": 500,
        "responseTimeMs": 234,
        "response": null,
        "errorMessage": "Request failed with status code 500",
        "reference": "TXN-20240401-001",
        "payload": {
          "event": "transaction.success",
          "data": {
            "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
            "reference": "TXN-20240401-001",
            "amount": 500000,
            "status": "success"
          }
        },
        "nextRetryAt": null,
        "deliveredAt": null,
        "createdAt": "2024-04-01T10:30:10.000Z",
        "subscription": {
          "id": "sub_e5f6a7b8-c9d0-1234-efab-567890123456",
          "url": "https://example.com/webhooks/tagpay",
          "description": "Production webhook endpoint"
        }
      }
    ],
    "metadata": {
      "page": 1,
      "limit": 20,
      "total": 12,
      "totalPages": 1
    }
  }
  ```
</ResponseExample>

***

## Get a single delivery

Retrieve full details for a specific delivery record, including the complete payload and subscription information.

```
GET https://api.tagpay.ng/v1/merchant/webhook/delivery/:id
```

### Path parameters

<ParamField path="id" type="string" required>
  The UUID of the delivery record.
</ParamField>

### Response

Returns a single delivery object with all fields described above, plus the full subscription detail including the `events` array.

<RequestExample>
  ```bash cURL theme={null}
  curl --request GET \
    --url "https://api.tagpay.ng/v1/merchant/webhook/delivery/del_f6a7b8c9-d0e1-2345-fabc-678901234567" \
    --header "Authorization: Bearer <token>"
  ```
</RequestExample>

<ResponseExample>
  ```json 200 theme={null}
  {
    "status": true,
    "message": "Delivery retrieved successfully",
    "data": {
      "id": "del_f6a7b8c9-d0e1-2345-fabc-678901234567",
      "subscriptionId": "sub_e5f6a7b8-c9d0-1234-efab-567890123456",
      "merchantId": "merch_001",
      "eventType": "transaction.success",
      "status": "failed",
      "attempts": 3,
      "maxAttempts": 3,
      "httpStatusCode": 500,
      "responseTimeMs": 234,
      "response": null,
      "errorMessage": "Request failed with status code 500",
      "reference": "TXN-20240401-001",
      "payload": {
        "event": "transaction.success",
        "data": {
          "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
          "reference": "TXN-20240401-001",
          "amount": 500000,
          "status": "success"
        }
      },
      "nextRetryAt": null,
      "deliveredAt": null,
      "createdAt": "2024-04-01T10:30:10.000Z",
      "subscription": {
        "id": "sub_e5f6a7b8-c9d0-1234-efab-567890123456",
        "url": "https://example.com/webhooks/tagpay",
        "description": "Production webhook endpoint",
        "events": ["transaction.success", "wallet.credit"]
      }
    }
  }
  ```

  ```json 404 theme={null}
  {
    "status": false,
    "message": "Delivery not found"
  }
  ```
</ResponseExample>

***

## Delivery statuses

Each delivery record moves through the following statuses:

| Status     | Description                                                    |
| ---------- | -------------------------------------------------------------- |
| `pending`  | The delivery has been queued and no attempt has been made yet. |
| `retrying` | A previous attempt failed and a retry is scheduled.            |
| `success`  | Your endpoint returned a `2xx` HTTP status code.               |
| `failed`   | All retry attempts were exhausted without a `2xx` response.    |

<Info>
  TagPay makes up to **3 delivery attempts** per event. After the first failure the system retries after 1 minute, then again after 5 minutes. If all three attempts fail, the delivery status becomes `failed` and no further retries are attempted automatically. Use the [replay endpoint](/api/webhooks/subscriptions#replay-a-failed-delivery) to manually retry.
</Info>
