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

# Replay a delivery

> Creates a new delivery of the event of a finished delivery, to the current URL of the subscription.

* **Credential:** an account API key. A trial key returns `401 unauthorized`.
* **Line-scoped keys:** the list of a [line-scoped key](/authentication#line-scoped-keys) is not
  applied here: the key replays any delivery of the account.
* **`Idempotency-Key`:** not honored. A call sent twice creates two deliveries of the same event, with
  the same `event_id`.
* **Events:** none. The operation delivers again the event of the delivery, with its `event_id` and
  its content unchanged: it creates no new event.
* **Guide:** [Replays](/webhooks/delivery#replays). Only a delivery whose `status` is `success`
  or `failed` can be replayed, while its record exists. The replay goes to the URL the
  subscription has now, signed with the secret it has now.

## Errors

| Status | `error.code` | When |
| - | - | - |
| 400 | `validation_failed` | `id` is not `wh_` followed by 25 letters or digits, or `delivery_id` is not `whd_` followed by 25 letters or digits. |
| 404 | `not_found` | Your account has no subscription with this id, or the subscription has no delivery with this id: the id is unknown, the record was deleted at the end of its retention, or the delivery belongs to another subscription. |
| 422 | `delivery_not_terminal` | The delivery is still `pending`. |
| 503 | `replay_enqueue_failed` | iSnap could not queue the replay. The new delivery exists with status `failed`: call again. |

The errors that every operation shares are in [Errors](/errors-and-rate-limits#errors).


## OpenAPI

````yaml POST /v1/webhooks/{id}/deliveries/{delivery_id}/replay
openapi: 3.0.0
info:
  title: iSnap API
  version: 2.45.0
  description: >-
    The iSnap API sends and receives iMessage, RCS and SMS on real phone lines,
    manages those lines, and reports events through webhooks. Every message is
    sent to a real recipient, with an `isnap_live_` key and with an
    `isnap_test_` key alike. Retry a `429` after `Retry-After` seconds. Retry a
    `500` or a `503` up to 2 times, with exponential backoff. Do not retry any
    other `4xx`: fix the request. Retry a write only on an operation that honors
    `Idempotency-Key`, with the key of the first attempt. Responses carry
    personal data: handles, names and message text.
servers:
  - url: https://api.isnap.ai
security:
  - bearerAuth: []
paths:
  /v1/webhooks/{id}/deliveries/{delivery_id}/replay:
    post:
      summary: Replay a delivery
      description: >-
        Creates a new delivery of the event of a finished delivery, sent to the
        current URL of the webhook subscription, signed with its current signing
        secret, on the same schedule of attempts. Accepts an API key. The
        original delivery must be in status `success` or `failed`: a `pending`
        delivery returns `422 delivery_not_terminal`. The new delivery has its
        own id, `replay_of` set to the original, the same `event_id` and the
        same content: a receiver that deduplicates on `event_id` sees a
        duplicate. A delivery can be replayed while its record exists, which is
        at least 72 hours after its creation; once the record is deleted, the
        operation returns `404 not_found`. There is no limit on the number of
        replays of a delivery.


        The replay is accepted whatever the state of the subscription: for an
        inactive subscription the new delivery ends `failed` without a request,
        and for a suspended one it waits until the subscription resumes, then
        ends `failed` if it was created more than 24 hours earlier. When the
        replay uses all its attempts, `failure_count` rises by 1. Returns `503
        replay_enqueue_failed` when iSnap cannot queue the replay: the new
        delivery then exists with status `failed`, and the call can be repeated.
      parameters:
        - schema:
            type: string
            pattern: ^wh_[0-9A-Za-z]{25}$
            description: >-
              Id of the webhook subscription, as returned in `id` by `POST
              /v1/webhooks`: `wh_` followed by 25 letters or digits.
            example: wh_3Kp8Rn9Fh2Lm5Qx7Vw1Yz4Bc6
          required: true
          description: >-
            Id of the webhook subscription, as returned in `id` by `POST
            /v1/webhooks`: `wh_` followed by 25 letters or digits.
          name: id
          in: path
        - schema:
            type: string
            pattern: ^whd_[0-9A-Za-z]{25}$
            description: >-
              Id of the delivery to replay, as returned in `id` by `GET
              /v1/webhooks/{id}/deliveries`: `whd_` followed by 25 letters or
              digits.
            example: whd_8Tc4Vn1Kq6Zr3Mx9Hb2Yf7Lp5
          required: true
          description: >-
            Id of the delivery to replay, as returned in `id` by `GET
            /v1/webhooks/{id}/deliveries`: `whd_` followed by 25 letters or
            digits.
          name: delivery_id
          in: path
      responses:
        '202':
          description: The new delivery, not sent yet.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WebhookDeliveryReplayEnvelope'
        '400':
          description: >-
            Invalid request. `error.code` is `validation_failed` when a
            parameter, a header or the body does not match its schema:
            `error.issues` then lists each problem.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
        '401':
          description: No valid credential. `error.code` is `unauthorized`.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
        '404':
          description: >-
            Not found. `error.code` is `not_found`: the account has no webhook
            subscription with this id, or the subscription has no delivery with
            this id. The record of a delivery is deleted at least 72 hours after
            its creation.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
        '429':
          description: >-
            Too many requests. `error.code` is `rate_limit_exceeded` when more
            than 100 requests came from the same network address in 60 seconds,
            whatever their API key or account: wait `error.retry_after` seconds.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
        '500':
          description: >-
            Unexpected failure. `error.code` is `internal_error`. An operation
            that takes a JSON body also returns it when the body, sent as
            `application/json`, is not valid JSON. Quote `trace_id` when you
            report it to iSnap.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
      security:
        - bearerAuth: []
components:
  schemas:
    WebhookDeliveryReplayEnvelope:
      type: object
      properties:
        success:
          type: boolean
          enum:
            - true
          description: Always `true` on a success response.
        data:
          $ref: '#/components/schemas/WebhookDeliveryReplay'
        trace_id:
          type: string
          description: >-
            Trace id of the request that produced this response: 32 lowercase
            hexadecimal characters. Quote it when you report a problem to iSnap.
        request_id:
          type: string
          description: >-
            Id of the request that produced this response: `req_` followed by 25
            letters or digits.
      required:
        - success
        - data
        - trace_id
        - request_id
    ErrorEnvelope:
      type: object
      properties:
        success:
          type: boolean
          enum:
            - false
          description: Always `false` on an error response.
        data:
          nullable: true
          description: Always `null` on an error response.
        error:
          type: object
          properties:
            status:
              type: integer
              description: The HTTP status of the response.
            code:
              type: string
              description: >-
                Stable machine-readable code that names the refusal. Branch on
                this value.
            message:
              type: string
              description: >-
                Text for a person. It can change between versions: do not branch
                on it.
            retry_after:
              type: integer
              nullable: true
              description: >-
                Seconds to wait before the next attempt. Set on the `429`
                responses that know a delay, where the `Retry-After` header
                carries the same value. When it is above 60 seconds, do not wait
                in a request: schedule the call, or report the time. `null` on
                every other error.
            retry_at:
              type: string
              nullable: true
              description: >-
                ISO 8601 timestamp at which the refusal ends. Set only on `429
                rebind_cap_reached`. `null` on every other error.
            issues:
              type: array
              nullable: true
              items:
                type: object
                properties:
                  path:
                    type: array
                    items:
                      anyOf:
                        - type: string
                        - type: number
                    description: >-
                      Where the problem is: the field names and array indexes
                      that lead to it.
                  message:
                    type: string
                    description: Text for a person.
                  code:
                    type: string
                    description: >-
                      Kind of problem. On `validation_failed`, for example
                      `invalid_type`, `invalid_value`, `invalid_format`,
                      `invalid_union`, `invalid_key`, `invalid_element`,
                      `too_small`, `too_big`, `not_multiple_of`,
                      `unrecognized_keys` or `custom`. The list is open: read
                      `path` and `message`.
                  min:
                    type: integer
                    description: >-
                      Smallest accepted value. Present only on
                      `limit_out_of_bounds`, `mac_quantity_not_a_pack`,
                      `byop_reduction_strands_mac_sessions` and
                      `byop_reduction_strands_byod_lines`.
                  max:
                    type: integer
                    description: >-
                      Largest accepted value. Present only on
                      `limit_out_of_bounds` and
                      `mac_sessions_exceed_byop_lines`, and on the `too_big`
                      issue of an `Idempotency-Key` header longer than 255
                      characters.
                required:
                  - path
                  - message
                  - code
              description: >-
                Problems found in the request, one entry each. Set on most `400
                validation_failed` responses and on the refusals that name a
                field: a refused `handle` of `POST /v1/lookup` has `issues:
                null`. `null` on every other error.
          required:
            - status
            - code
            - message
            - retry_after
            - retry_at
            - issues
          description: >-
            What went wrong. The six fields are always present; `retry_after`,
            `retry_at` and `issues` are `null` when they do not apply.
        trace_id:
          type: string
          description: >-
            Trace id of the request that produced this response: 32 lowercase
            hexadecimal characters. Quote it when you report a problem to iSnap.
        request_id:
          type: string
          description: >-
            Id of the request that produced this response: `req_` followed by 25
            letters or digits.
      required:
        - success
        - data
        - error
        - trace_id
        - request_id
      description: The body of an error response.
    WebhookDeliveryReplay:
      type: object
      properties:
        delivery_id:
          type: string
          description: 'Id of the new delivery: `whd_` followed by 25 letters or digits.'
        replay_of:
          type: string
          description: Id of the delivery that was replayed.
        status:
          type: string
          enum:
            - pending
          description: 'Always `pending`: the new delivery is not sent yet.'
      required:
        - delivery_id
        - replay_of
        - status
      description: The delivery that a replay created.
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      description: >-
        An API key created in the iSnap dashboard, or a trial key, sent as
        `Authorization: Bearer <key>`. An API key starts with `isnap_live_` or
        `isnap_test_`; both act on the same account, lines and billing. A trial
        key acts on its trial only.

````

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