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

# Get the pairing status of a trial

> Reads a trial by its pairing code, without a credential, and returns the trial key once after pairing.

* **Credential:** none. The pairing code in `token` identifies the trial, and the prospect sees that code. Call this operation from your backend only, never from a browser: see [How a trial works](/guides/trials#how-a-trial-works).
* **Events:** none. A call made after the pairing window ended, for a trial that the prospect has not paired, sets the trial to `revoked` and sends no event: see [Statuses](/guides/trials#statuses).
* **Personal data:** `paired_handle`, the prospect's phone number or the email address of their Apple ID. Request it only when needed, do not copy it into logs, tickets or other tools, and refer to a prospect by an id of your own.
* **Trial key:** the first call after pairing returns `trial_api_key`, if it is made within 1 hour of pairing. Every later call omits it.
* **Retries:** do not retry this call automatically: the first read after pairing returns the trial key once. See [Read the status and the trial key](/guides/trials#read-the-status-and-the-trial-key).
* **Caching:** the response carries `Cache-Control: no-store`, whatever its status.
* **Rate limit:** each call counts against the [request-rate limit](/errors-and-rate-limits#rate-limits).

## Errors

| Status | `error.code` | When |
| - | - | - |
| 400 | `validation_failed` | `token` is missing, empty or longer than 64 characters. |
| 404 | `trial_not_found` | No trial has this pairing code. |
| 410 | `pairing_expired` | The pairing window ended before the prospect paired, or the trial is revoked, whatever the reason. A `200` never carries `status: revoked`. Start another trial. |

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


## OpenAPI

````yaml GET /v1/trial/status
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/trial/status:
    get:
      summary: Get the pairing status of a trial
      description: >-
        This read changes the trial: the first call after pairing returns the
        trial key once, and a call made after the pairing window ended without a
        pairing revokes the trial. Call it only from the backend that stores the
        key, and never retry it automatically. Returns the state of a trial from
        its pairing code. Needs no credential: `token`, the pairing code that
        the prospect sees and types, is the only input. `status` is
        `pairing_pending`, `active` or `dormant`. The response carries
        `paired_handle`, the phone number or email address of the prospect, and
        never carries your metadata.


        After pairing, the first call returns `trial_api_key` once, and later
        calls omit it. The key can be read that first time for 1 hour after the
        pairing: after that hour it is never returned and the trial cannot send,
        so revoke the trial and start another. Whoever calls first after the
        pairing receives the key: call from your backend as soon as
        `trial.linked` arrives.


        Returns `410 pairing_expired` for a revoked trial, whatever the reason
        of the revoke, and for a trial whose pairing window ended without a
        pairing: that call also revokes the trial, and no event is sent. Returns
        `404 trial_not_found` when no trial has this code. `paired_handle` is
        personal data.
      parameters:
        - schema:
            type: string
            minLength: 1
            maxLength: 64
            description: >-
              The pairing code, as returned in `token` by `POST /v1/trial/init`.
              Case-insensitive, and surrounding spaces are ignored. From 1 to 64
              characters.
            example: K7M2XQ9
          required: true
          description: >-
            The pairing code, as returned in `token` by `POST /v1/trial/init`.
            Case-insensitive, and surrounding spaces are ignored. From 1 to 64
            characters.
          name: token
          in: query
      responses:
        '200':
          description: The state of the trial.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TrialStatusEnvelope'
        '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'
        '404':
          description: >-
            Not found. `error.code` is `trial_not_found`: no trial has this
            pairing code.
          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: []
components:
  schemas:
    TrialStatusEnvelope:
      type: object
      properties:
        success:
          type: boolean
          enum:
            - true
          description: Always `true` on a success response.
        data:
          $ref: '#/components/schemas/TrialStatusData'
        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.
    TrialStatusData:
      type: object
      properties:
        trial_id:
          type: string
          description: 'Id of the trial: `trl_` followed by 25 letters or digits.'
        token:
          type: string
          description: The pairing code of the trial.
        status:
          type: string
          enum:
            - pairing_pending
            - active
            - dormant
            - revoked
          description: >-
            `pairing_pending` until the prospect pairs, then `active` or
            `dormant`. `revoked` is declared and never returned here: a revoked
            trial returns `410 pairing_expired`.
        pairing_expires_at:
          type: string
          nullable: true
          description: >-
            End of the pairing window while `status` is `pairing_pending`.
            `null` once the trial is paired.
        pool_line_id:
          type: string
          nullable: true
          description: Id of the line the trial runs on (`line_`). Never `null`.
        pool_line_number:
          type: string
          nullable: true
          description: >-
            Phone number of the line the trial runs on. `null` until the trial
            is paired.
        paired_handle:
          type: string
          nullable: true
          description: >-
            Handle of the prospect, as the line's device reports it: a phone
            number or an email address. `null` until the trial is paired.
            Personal data.
        trial_api_key:
          type: string
          description: >-
            The trial key: `isnap_test_` followed by 43 characters. Present only
            in the first response after pairing, and only when that call is made
            within 1 hour of the pairing. It works on `POST /v1/messages`, `GET
            /v1/messages` and `GET /v1/trial/activity` only.
        activity_rule:
          type: object
          nullable: true
          properties:
            max_outbound_without_inbound:
              type: integer
              description: >-
                Number of messages the trial key can send in a row without a
                reply, a reaction or a read receipt from the prospect.
            outbound_since_last_inbound:
              type: integer
              description: >-
                Messages sent with the trial key since the last reply, reaction
                or read receipt from the prospect. The trial becomes `dormant`
                when this number reaches `max_outbound_without_inbound`.
          required:
            - max_outbound_without_inbound
            - outbound_since_last_inbound
          description: >-
            The limit on messages sent without a reply, and where the trial
            stands against it. When the trial runs on an iMessage line, a read
            by the prospect does not count: only a reply or a reaction does.
            `null` until the trial is paired.
      required:
        - trial_id
        - token
        - status
        - pairing_expires_at
        - pool_line_id
        - pool_line_number
        - paired_handle
        - activity_rule
      description: The state of a trial, read from its pairing code.
  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.