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

# List webhook delivery attempts

> Returns the attempts Blujay made to deliver events to this subscription. Each attempt shows the HTTP status your endpoint returned and, when it failed, an `error_code` and `error_message`. Filter by `event_id` to see every attempt for one event.



## OpenAPI

````yaml /api-reference/openapi.yaml get /v1/webhook-subscriptions/{subscription_id}/deliveries
openapi: 3.1.0
info:
  title: Blujay API
  version: 1.0.0
  description: >-
    The Blujay API lets you send and receive iMessage, RCS and SMS messages from
    your

    Blujay phone numbers, manage contacts, and receive real-time webhooks.


    Every response uses the same JSON envelope and carries a `trace_id` you can
    share

    with support. Authenticate with your workspace API key.
servers:
  - url: https://api.blujay.io
    description: Production
security:
  - PublicApiKey: []
tags:
  - name: Auth
    description: Check which workspace and credential a request is using.
  - name: Chats
    description: >-
      Direct and group conversations between your Blujay numbers and your
      contacts.
  - name: Messages
    description: Send, read, edit, unsend and retry messages.
  - name: Phone Numbers
    description: >-
      Your Blujay numbers, whether each can send right now, and their live
      sending limits.
  - name: Capability
    description: >-
      Check whether a phone number can be reached by iMessage, RCS or SMS before
      you send.
  - name: Contacts
    description: Create, find, update, tag, assign and opt out contacts.
  - name: vCards
    description: >-
      Saved contact cards that you can send in a message. Recipients get a
      native contact card over iMessage, SMS or RCS.
  - name: Team Members
    description: People in your workspace you can assign contacts to.
  - name: Workflows
    description: Enroll contacts in workflows you start manually.
  - name: Attachments
    description: >-
      Upload files once and reuse them in messages, or download files from
      messages.
  - name: Webhooks
    description: Subscribe to events, inspect delivery attempts and verify signatures.
paths:
  /v1/webhook-subscriptions/{subscription_id}/deliveries:
    get:
      tags:
        - Webhooks
      summary: List webhook delivery attempts
      description: >-
        Returns the attempts Blujay made to deliver events to this subscription.
        Each attempt shows the HTTP status your endpoint returned and, when it
        failed, an `error_code` and `error_message`. Filter by `event_id` to see
        every attempt for one event.
      operationId: listPublicWebhookDeliveries
      parameters:
        - $ref: '#/components/parameters/WebhookSubscriptionId'
        - $ref: '#/components/parameters/Cursor'
        - $ref: '#/components/parameters/Limit'
        - name: event_id
          in: query
          required: false
          schema:
            $ref: '#/components/schemas/EventId'
          description: Return only attempts for this event.
      responses:
        '200':
          description: A page of delivery attempts.
          headers:
            X-Trace-ID:
              $ref: '#/components/headers/XTraceID'
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/SuccessEnvelope'
                  - type: object
                    required:
                      - data
                    properties:
                      data:
                        $ref: '#/components/schemas/PublicWebhookDeliveryAttemptList'
              examples:
                deliveredMessageEvent:
                  summary: A successful delivery
                  value:
                    status: success
                    data:
                      data:
                        - event_id: evt_abc123
                          event_type: message.read
                          attempt_number: 1
                          delivery_mode: automatic
                          status: success
                          http_status: 200
                          error_code: null
                          error_message: null
                          scheduled_at: '2026-10-14T17:01:00.000Z'
                          started_at: '2026-10-14T17:01:01.000Z'
                          completed_at: '2026-10-14T17:01:01.500Z'
                          next_retry_at: null
                          created_at: '2026-10-14T17:01:00.000Z'
                          updated_at: '2026-10-14T17:01:01.500Z'
                      has_more: false
                      limit: 25
                    trace_id: trc_8f2a1c0e4b7d
                    timestamp: '2026-10-14T17:01:02.000Z'
                retriedAfter503:
                  summary: A delivery that succeeded on retry
                  value:
                    status: success
                    data:
                      data:
                        - event_id: evt_abc123
                          event_type: message.delivered
                          attempt_number: 2
                          delivery_mode: automatic
                          status: success
                          http_status: 200
                          error_code: null
                          error_message: null
                          scheduled_at: '2026-10-14T17:01:11.000Z'
                          started_at: '2026-10-14T17:01:11.000Z'
                          completed_at: '2026-10-14T17:01:11.400Z'
                          next_retry_at: null
                          created_at: '2026-10-14T17:01:01.000Z'
                          updated_at: '2026-10-14T17:01:11.400Z'
                        - event_id: evt_abc123
                          event_type: message.delivered
                          attempt_number: 1
                          delivery_mode: automatic
                          status: failed
                          http_status: 503
                          error_code: HTTP_RETRYABLE_RESPONSE
                          error_message: Remote endpoint returned retryable status 503
                          scheduled_at: '2026-10-14T17:01:00.000Z'
                          started_at: '2026-10-14T17:01:00.000Z'
                          completed_at: '2026-10-14T17:01:01.000Z'
                          next_retry_at: '2026-10-14T17:01:11.000Z'
                          created_at: '2026-10-14T17:01:00.000Z'
                          updated_at: '2026-10-14T17:01:01.000Z'
                      has_more: false
                      limit: 25
                    trace_id: trc_8f2a1c0e4b7d
                    timestamp: '2026-10-14T17:02:00.000Z'
        '400':
          $ref: '#/components/responses/ValidationError'
        '404':
          $ref: '#/components/responses/NotFound'
      security:
        - PublicApiKey: []
components:
  parameters:
    WebhookSubscriptionId:
      name: subscription_id
      in: path
      required: true
      schema:
        $ref: '#/components/schemas/WebhookSubscriptionId'
    Cursor:
      name: cursor
      in: query
      description: >-
        The `next_cursor` value from the previous page. Leave it out to get the
        first page.
      schema:
        type: string
    Limit:
      name: limit
      in: query
      description: Maximum number of items to return.
      schema:
        type: integer
        minimum: 1
        maximum: 100
        default: 25
  schemas:
    EventId:
      type: string
      examples:
        - evt_abc123
      pattern: ^evt_[A-Za-z0-9_-]+$
    SuccessEnvelope:
      type: object
      description: Wraps every successful response. The result is in `data`.
      required:
        - status
        - trace_id
        - timestamp
      properties:
        status:
          type: string
          enum:
            - success
        trace_id:
          $ref: '#/components/schemas/TraceId'
        timestamp:
          type: string
          examples:
            - '2026-10-14T17:01:00.000Z'
          format: date-time
        client_request_id:
          type: string
          description: >-
            Your `X-Request-ID` header value, echoed back when you send one. Not
            included on the send responses (`POST /v1/chats`, `POST
            /v1/chats/{chat_id}/messages`, `POST
            /v1/messages/{message_id}/retry`); keep your own mapping from your
            request ID to the returned message ID there.
    PublicWebhookDeliveryAttemptList:
      type: object
      additionalProperties: false
      required:
        - data
        - has_more
        - limit
      properties:
        data:
          type: array
          items:
            $ref: '#/components/schemas/PublicWebhookDeliveryAttempt'
        next_cursor:
          type: string
          examples:
            - AbC9xQ2nRk7vT1mZ
        has_more:
          type: boolean
        limit:
          type: integer
          examples:
            - 25
    WebhookSubscriptionId:
      type: string
      examples:
        - whsub_abc123
      pattern: ^whsub_[A-Za-z0-9_-]+$
    TraceId:
      type: string
      examples:
        - trc_8f2a1c0e4b7d
      pattern: ^trc_[A-Za-z0-9_-]+$
    PublicWebhookDeliveryAttempt:
      type: object
      additionalProperties: false
      required:
        - event_id
        - event_type
        - attempt_number
        - delivery_mode
        - status
        - http_status
        - error_code
        - error_message
        - scheduled_at
        - started_at
        - completed_at
        - next_retry_at
        - created_at
        - updated_at
      properties:
        event_id:
          $ref: '#/components/schemas/EventId'
        event_type:
          $ref: '#/components/schemas/WebhookEventType'
        delivery_mode:
          type: string
          enum:
            - automatic
            - replay
        attempt_number:
          type: integer
          examples:
            - 1
          minimum: 1
        status:
          type: string
          enum:
            - pending
            - success
            - failed
        http_status:
          type:
            - integer
            - 'null'
          examples:
            - 200
        error_code:
          type:
            - string
            - 'null'
          description: >
            Why the attempt didn't succeed. Null for a successful attempt.

            - `HTTP_RETRYABLE_RESPONSE`: your endpoint returned 408, 429 or 5xx.
            Blujay retries.

            - `HTTP_4XX_RESPONSE`, `HTTP_UNEXPECTED_RESPONSE`: your endpoint
            returned a status Blujay doesn't retry.

            - `WEBHOOK_DELIVERY_NETWORK_ERROR`, `WEBHOOK_DELIVERY_TIMEOUT`: the
            request didn't complete. Blujay retries.

            - `WEBHOOK_REDIRECT_LIMIT_EXCEEDED`, `WEBHOOK_REDIRECT_INVALID`,
            `WEBHOOK_URL_INVALID`, `WEBHOOK_URL_UNSAFE`,
            `WEBHOOK_URL_UNRESOLVABLE`: the subscription URL or its redirects
            can't be used.

            - `WEBHOOK_SIGNING_SECRET_UNAVAILABLE`: Blujay couldn't sign the
            request. Blujay retries.

            - `WEBHOOK_PAYLOAD_INVALID`: the stored event couldn't be sent.

            - `WEBHOOK_SUBSCRIPTION_INACTIVE`: the subscription is disabled or
            no longer includes the event type.

            - `WEBHOOK_PHONE_NUMBER_EXCLUDED`: the subscription's
            `phone_number_filter` no longer includes the event's number.

            - `WEBHOOK_EVENT_NO_LONGER_DELIVERABLE`: the event no longer applies
            to this subscription, so Blujay won't deliver it.

            - `WEBHOOK_DELIVERY_INTERRUPTED`: Blujay stopped this attempt. Later
            attempts for the same event show whether it was delivered.

            - `WEBHOOK_ATTEMPT_LIMIT_EXHAUSTED`: Blujay stopped after the
            maximum number of attempts.
          enum:
            - HTTP_RETRYABLE_RESPONSE
            - HTTP_4XX_RESPONSE
            - HTTP_UNEXPECTED_RESPONSE
            - WEBHOOK_DELIVERY_NETWORK_ERROR
            - WEBHOOK_DELIVERY_TIMEOUT
            - WEBHOOK_REDIRECT_LIMIT_EXCEEDED
            - WEBHOOK_REDIRECT_INVALID
            - WEBHOOK_URL_INVALID
            - WEBHOOK_URL_UNSAFE
            - WEBHOOK_URL_UNRESOLVABLE
            - WEBHOOK_SIGNING_SECRET_UNAVAILABLE
            - WEBHOOK_PAYLOAD_INVALID
            - WEBHOOK_SUBSCRIPTION_INACTIVE
            - WEBHOOK_PHONE_NUMBER_EXCLUDED
            - WEBHOOK_EVENT_NO_LONGER_DELIVERABLE
            - WEBHOOK_DELIVERY_INTERRUPTED
            - WEBHOOK_ATTEMPT_LIMIT_EXHAUSTED
            - null
        error_message:
          type:
            - string
            - 'null'
        scheduled_at:
          type: string
          examples:
            - '2026-10-14T17:01:00.000Z'
          format: date-time
        started_at:
          examples:
            - '2026-10-14T17:01:00.000Z'
          type:
            - string
            - 'null'
          format: date-time
        completed_at:
          examples:
            - '2026-10-14T17:01:00.000Z'
          type:
            - string
            - 'null'
          format: date-time
        next_retry_at:
          examples:
            - '2026-10-14T17:01:00.000Z'
          type:
            - string
            - 'null'
          format: date-time
        created_at:
          type: string
          examples:
            - '2026-10-14T17:01:00.000Z'
          format: date-time
        updated_at:
          type: string
          examples:
            - '2026-10-14T17:01:00.000Z'
          format: date-time
    ErrorEnvelope:
      type: object
      description: >-
        Wraps every error response. Branch on `error.code`, and include
        `trace_id` when you contact support.
      required:
        - status
        - error
        - trace_id
        - timestamp
      properties:
        status:
          const: error
        error:
          $ref: '#/components/schemas/PublicError'
        trace_id:
          $ref: '#/components/schemas/TraceId'
        timestamp:
          type: string
          examples:
            - '2026-10-14T17:01:00.000Z'
          format: date-time
        client_request_id:
          type: string
          description: Your `X-Request-ID` header value, echoed back when you send one.
    WebhookEventType:
      type: string
      description: >-
        Every event type that can appear on a subscription or in a webhook. Some
        types are recognized only so older subscriptions keep working and may
        never be sent. You can add only the types in
        `WebhookSubscribableEventType`.
      enum:
        - message.accepted
        - message.sent
        - message.delivered
        - message.read
        - message.failed
        - message.received
        - reaction.added
        - reaction.removed
        - participant.added
        - participant.removed
        - chat.group_name_updated
        - phone_number.status_updated
        - contact.tag_added
        - contact.assigned
        - chat.typing_indicator.started
        - chat.typing_indicator.stopped
        - message.edited
        - message.unsent
    PublicError:
      type: object
      required:
        - code
        - message
        - type
        - http_status
        - retryable
        - doc_url
        - details
      properties:
        code:
          type: string
          description: Stable, machine-readable error code. Branch on this value.
          examples:
            - RATE_LIMIT_EXCEEDED
            - QUEUE_UNAVAILABLE
            - FEATURE_NOT_ENABLED
        message:
          type: string
          description: Human-readable explanation. It can change, so don't parse it.
        type:
          type: string
          description: Broad error category.
          examples:
            - validation
            - auth
            - idempotency
            - rate_limit
            - queue
            - feature_gate
        http_status:
          type: integer
          description: The HTTP status code of the response.
          enum:
            - 400
            - 401
            - 403
            - 404
            - 409
            - 413
            - 415
            - 422
            - 429
            - 500
            - 502
            - 503
        retryable:
          type: boolean
          description: Whether sending the same request again later can succeed.
        doc_url:
          type: string
          format: uri
          description: Link to documentation for this error code.
        details:
          type: array
          description: >-
            Extra structured context, such as the fields that failed validation
            or the limit you hit.
          items:
            type: object
            additionalProperties: true
        retry_after:
          type: integer
          minimum: 1
          description: >-
            Seconds to wait before retrying. Also sent as the `Retry-After`
            header.
        reset_at:
          type: string
          examples:
            - '2026-10-14T17:01:00.000Z'
          format: date-time
          description: When the limit you hit resets.
  headers:
    XTraceID:
      description: >-
        Unique ID for this request. It matches `trace_id` in the body. Include
        it when you contact Blujay support.
      schema:
        $ref: '#/components/schemas/TraceId'
  responses:
    ValidationError:
      description: The request is invalid. `details` lists the fields that failed.
      headers:
        X-Trace-ID:
          $ref: '#/components/headers/XTraceID'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorEnvelope'
          examples:
            invalidInput:
              value:
                status: error
                error:
                  code: VALIDATION_ERROR
                  message: Request validation failed
                  type: validation
                  http_status: 400
                  retryable: false
                  doc_url: https://docs.blujay.io/errors/validation-error
                  details: []
                trace_id: trc_8f2a1c0e4b7d
                timestamp: '2026-10-14T00:00:00.000Z'
    NotFound:
      description: The resource doesn't exist or isn't in your workspace.
      headers:
        X-Trace-ID:
          $ref: '#/components/headers/XTraceID'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorEnvelope'
  securitySchemes:
    PublicApiKey:
      type: http
      scheme: bearer
      bearerFormat: blu_...
      description: >
        Your workspace API key, sent as `Authorization: Bearer blu_...`.
        Workspace admins can find it in the Blujay app under **API**.


        An API key has full access to your workspace and works on every
        endpoint. There is no test mode: every key sends real messages and
        changes real data, so keep it secret and use it only from your server.


        Each API key can make 600 read requests and 120 write requests per
        minute, plus 60 attachment requests per minute. Over a limit you get
        `429 RATE_LIMIT_EXCEEDED` with `Retry-After`.

````

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