> ## 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.

# List the queue of a line

> Lists a line's outbound messages that are held, waiting for its device, or sent without a delivery receipt, with a summary of its counters.

* **Credential:** an API key of the owner of the line. See [Reading the limits and the queue](/guides/sending-limits#reading-the-limits-and-the-queue).
* **Line-scoped keys:** a [line-scoped key](/authentication#line-scoped-keys) gets `403 forbidden` unless the line is in its list, even when the line does not exist.
* **Events:** none.
* **Personal data:** each item carries the recipient's number in `to` and the text in `body`. Request them only when needed, do not copy them into logs, tickets or other tools, and refer to a contact by an id of your own.
* **Item `status`:** `scheduled` for a held message. `queued` for a message that waits for the line's device, or that the device has and has not confirmed. `delivered_to_device` for a message whose `status` is `sent`: the device confirmed the send, and no delivery receipt has arrived. A `delivered_to_device` item stays listed until a receipt arrives or iSnap deletes the message, at least 72 hours after it recorded it.
* **Order:** by `scheduled_for`, earliest first. `queue_position` starts at 1 and counts the items of the earlier pages. Without a `status` filter, it counts the `delivered_to_device` items too.
* **Pagination:** a cursor, not tied to the `status` filter. `limit` is 1 to 100, 50 by default. An item can come back on a later page when iSnap holds its message again with a later `scheduled_for`: deduplicate on `id`. See [Cursors](/pagination#cursors).
* **Items:** a queue item is not a message object: its `body` is `""` where the message has `null`. Reaction entries are listed too.

## Errors

| Status | `error.code` | When |
| - | - | - |
| 400 | `validation_failed` | `limit` is outside 1 to 100, or `status` is not `scheduled`, `queued` or `delivered_to_device`. A cursor that cannot be read is not an error: the list restarts from the first page. |
| 403 | `forbidden` | The request uses a line-scoped key, and the line is not in its list. |
| 404 | `not_found` | No line has this id, or the line is not yours. |

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


## OpenAPI

````yaml GET /v1/lines/{id}/queue
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/lines/{id}/queue:
    get:
      summary: List the queue of a line
      description: >-
        Lists the outbound messages of a line you own that are held
        (`scheduled`), waiting for the device of the line (`queued`), or sent by
        the device and not yet reported delivered (`delivered_to_device`), with
        a summary of the counters of the line. Accepts an API key. Items are
        ordered by `scheduled_for`, earliest first, and reactions are included.
        Each item carries the recipient and the text of a message: this is
        personal data.


        Pass `next_cursor` as `cursor` to get the next page, and keep the same
        `status` filter for a whole walk. Stop when `has_more` is `false`:
        `next_cursor` is then `null`. A `cursor` that cannot be read restarts
        the list from the first page, with `200`, and nothing in the response
        says so. An item can also come back on a later page when iSnap holds its
        message again for a later time: deduplicate on `id`.
      parameters:
        - schema:
            type: string
            pattern: ^line_[0-9A-Za-z]{25}$
            description: 'Id of a line: `line_` followed by 25 letters or digits.'
          required: true
          description: 'Id of a line: `line_` followed by 25 letters or digits.'
          name: id
          in: path
        - schema:
            type: integer
            minimum: 1
            maximum: 100
            default: 50
            description: Number of items per page, from 1 to 100.
          required: false
          description: Number of items per page, from 1 to 100.
          name: limit
          in: query
        - schema:
            type: string
            description: >-
              The `next_cursor` of the previous page. Omit it for the first
              page. A value that cannot be read restarts the list from the first
              page.
          required: false
          description: >-
            The `next_cursor` of the previous page. Omit it for the first page.
            A value that cannot be read restarts the list from the first page.
          name: cursor
          in: query
        - schema:
            type: string
            enum:
              - queued
              - scheduled
              - delivered_to_device
            description: >-
              Keep the items of one status: `scheduled`, `queued` or
              `delivered_to_device`. Omit it for all three.
          required: false
          description: >-
            Keep the items of one status: `scheduled`, `queued` or
            `delivered_to_device`. Omit it for all three.
          name: status
          in: query
      responses:
        '200':
          description: 'The queue of the line: a summary and one page of items.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/QueueEnvelope'
        '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'
        '403':
          description: >-
            Refused. `forbidden`: the key is line-scoped and this line is
            outside its list.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
        '404':
          description: 'Not found. `not_found`: the line does not exist, or it is not yours.'
          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:
    QueueEnvelope:
      type: object
      properties:
        success:
          type: boolean
          enum:
            - true
          description: Always `true` on a success response.
        data:
          $ref: '#/components/schemas/QueueResponseData'
        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.
    QueueResponseData:
      type: object
      properties:
        line_id:
          type: string
          pattern: ^line_[0-9A-Za-z]{25}$
          description: 'Id of a line: `line_` followed by 25 letters or digits.'
        summary:
          $ref: '#/components/schemas/QueueSummary'
        items:
          type: array
          items:
            $ref: '#/components/schemas/QueueItem'
          description: One page of items, ordered by `scheduled_for`, earliest first.
        has_more:
          type: boolean
          description: '`true` when another page follows.'
        next_cursor:
          type: string
          nullable: true
          description: Pass it as `cursor` to get the next page. `null` on the last page.
      required:
        - line_id
        - summary
        - items
        - has_more
        - next_cursor
      description: 'The queue of a line: a summary and one page of items.'
    QueueSummary:
      type: object
      properties:
        total_queued:
          type: integer
          minimum: 0
          description: Number of items of the line whose `status` is `queued`.
        total_scheduled:
          type: integer
          minimum: 0
          description: Number of items of the line whose `status` is `scheduled`.
        total_delivered_to_device:
          type: integer
          minimum: 0
          description: Number of items of the line whose `status` is `delivered_to_device`.
        next_scheduled_at:
          type: string
          nullable: true
          description: >-
            The earliest `scheduled_for` among the held messages of the line
            (ISO 8601, UTC). `null` when the line holds none.
        timezone:
          type: string
          description: IANA time zone of the line.
        daily_new_contacts_used:
          type: integer
          minimum: 0
          description: Distinct new contacts the line messaged in the last 24 hours.
        daily_new_contact_limit:
          type: integer
          minimum: 0
          description: >-
            Sending limit: distinct new contacts the line can message per
            rolling 24 hours. A new contact is a recipient who has not messaged
            the line in the last 30 days, the default window.
        daily_known_contacts_used:
          type: integer
          minimum: 0
          description: Distinct known contacts the line messaged in the last 24 hours.
        daily_known_contact_limit:
          type: integer
          minimum: 0
          description: >-
            Sending limit: distinct known contacts the line can message per
            rolling 24 hours. A known contact is a recipient who messaged the
            line in the last 30 days, the default window.
        daily_messages_used:
          type: integer
          minimum: 0
          description: Messages the line sent in the last 24 hours.
        daily_total_message_limit:
          type: integer
          minimum: 0
          description: 'Sending limit: messages per rolling 24 hours.'
        hourly_messages_used:
          type: integer
          minimum: 0
          description: Messages the line sent in the last 60 minutes.
        hourly_message_limit:
          type: integer
          minimum: 0
          description: 'Sending limit: messages per rolling 60 minutes.'
        minute_messages_used:
          type: integer
          minimum: 0
          description: Messages the line sent in the last 60 seconds.
        minute_message_limit:
          type: integer
          minimum: 0
          description: 'Sending limit: messages per rolling 60 seconds.'
        daily_replies_used:
          type: integer
          minimum: 0
          description: >-
            Replies that used the reply lane to pass a sending limit in the last
            24 hours.
        daily_reply_limit:
          type: integer
          minimum: 0
          description: >-
            Reply-lane allowance: the number of replies per rolling 24 hours
            that can pass a sending limit through the reply lane.
        buckets_warning:
          $ref: '#/components/schemas/BucketsWarning'
      required:
        - total_queued
        - total_scheduled
        - total_delivered_to_device
        - next_scheduled_at
        - timezone
        - daily_new_contacts_used
        - daily_new_contact_limit
        - daily_known_contacts_used
        - daily_known_contact_limit
        - daily_messages_used
        - daily_total_message_limit
        - hourly_messages_used
        - hourly_message_limit
        - minute_messages_used
        - minute_message_limit
        - daily_replies_used
        - daily_reply_limit
        - buckets_warning
      description: >-
        Totals of the queue of the line, and its sending limits with their
        counters.
    QueueItem:
      type: object
      properties:
        id:
          type: string
          description: 'Id of the message: `msg_` followed by 25 letters or digits.'
        to:
          type: string
          description: The recipient of the message. Personal data.
        body:
          type: string
          nullable: true
          description: >-
            The text of the message. `null` or an empty string when the message
            has no text. Personal data.
        status:
          type: string
          enum:
            - queued
            - scheduled
            - delivered_to_device
          description: >-
            `scheduled`: iSnap holds the message until `scheduled_for`.
            `queued`: the message waits for the device of the line, or the
            device has it and has not confirmed the send. `delivered_to_device`:
            the device confirmed the send (the message `status` is `sent`) and
            no delivery receipt has arrived; such an item stays listed until a
            receipt arrives or the message is deleted.
        scheduled_for:
          type: string
          description: >-
            Planned send time of a held message (ISO 8601, UTC). For a message
            that is not held, the time it entered the queue.
        schedule_reason:
          type: string
          nullable: true
          description: >-
            Why the message is held: `minute_limit_exceeded`,
            `hourly_limit_exceeded`, `total_message_quota_exceeded`,
            `new_contact_quota_exceeded`, `known_contact_quota_exceeded`,
            `inter_message_delay`, `inter_new_contact_delay`, `quiet_hours`,
            `carrier_retry` or `pending_retry`; ignore values you do not know.
            `null` on a message that is not held.
        queue_position:
          type: integer
          minimum: 0
          description: >-
            Rank of the item in the returned order, starting at 1 and counting
            the items of earlier pages.
        is_new_contact:
          type: boolean
          nullable: true
          description: >-
            Whether the recipient counted as a new contact when the message was
            accepted or released. `null` when not known.
        target_activity_hour:
          type: integer
          nullable: true
          minimum: 0
          maximum: 23
          description: >-
            The hour of `scheduled_for`, from 0 to 23, read in `timezone`.
            `null` when the message has no planned send time.
        timezone:
          type: string
          description: >-
            IANA time zone `target_activity_hour` is read in: the time zone of
            the recipient when iSnap knows it, otherwise the time zone of the
            line.
        created_at:
          type: string
          description: Timestamp at which iSnap recorded the message (ISO 8601, UTC).
      required:
        - id
        - to
        - body
        - status
        - scheduled_for
        - schedule_reason
        - queue_position
        - is_new_contact
        - target_activity_hour
        - timezone
        - created_at
      description: >-
        One outbound message of the line that is held, waiting for the device,
        or sent and not yet reported delivered.
    BucketsWarning:
      type: object
      properties:
        new_contacts_at_80_percent:
          type: boolean
          description: >-
            `true` when `daily_new_contacts_used` is at 80% of
            `daily_new_contact_limit` or more.
        known_contacts_at_80_percent:
          type: boolean
          description: >-
            `true` when `daily_known_contacts_used` is at 80% of
            `daily_known_contact_limit` or more.
        messages_at_80_percent:
          type: boolean
          description: >-
            `true` when `daily_messages_used` is at 80% of
            `daily_total_message_limit` or more.
        hourly_at_80_percent:
          type: boolean
          description: >-
            `true` when `hourly_messages_used` is at 80% of
            `hourly_message_limit` or more.
        minute_at_80_percent:
          type: boolean
          description: >-
            `true` when `minute_messages_used` is at 80% of
            `minute_message_limit` or more.
      required:
        - new_contacts_at_80_percent
        - known_contacts_at_80_percent
        - messages_at_80_percent
        - hourly_at_80_percent
        - minute_at_80_percent
      description: >-
        One flag per sending limit: `true` from 80% of the limit. A flag is
        `false` when its limit is 0.
  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.