> ## 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 health of a BYOD line

> Returns what the device of a BYOD line last reported.

* **Credential:** an API key of the owner of the line. The operation serves BYOD lines only. See [Health](/guides/managing-lines#health) for the meaning of each field and of each `null`.
* **Line-scoped keys:** a [line-scoped key](/authentication#line-scoped-keys) gets `403 forbidden` unless the line is in its list.
* **Events:** none. For the events about the connection of a line, see [Connectivity events](/guides/managing-lines#connectivity-events).
* **Other lines:** for a rented, shared or test line, read [`GET /v1/attention`](/api-reference/lines/list-attention).

## Errors

| Status | `error.code` | When |
| - | - | - |
| 403 | `forbidden` | The request uses a line-scoped key, and the line is not in its list. |
| 403 | `rental_health_not_exposed` | The line is not a BYOD line. |
| 404 | `not_found` | No line has this id, or you do not own the line. |

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


## OpenAPI

````yaml GET /v1/lines/{id}/health
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}/health:
    get:
      summary: Get the health of a BYOD line
      description: >-
        Returns the health of a BYOD line you own: its `state` (`active`,
        `degraded` or `offline`), the last report of its device, what the device
        can do, its free storage, and the Apple ID flag. Accepts an API key.
        BYOD lines only: any other line you own returns `403
        rental_health_not_exposed`.
      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
      responses:
        '200':
          description: The health of the line.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/LineHealthEnvelope'
        '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. `rental_health_not_exposed`: the line is not a
            BYOD line.
          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:
    LineHealthEnvelope:
      type: object
      properties:
        success:
          type: boolean
          enum:
            - true
          description: Always `true` on a success response.
        data:
          $ref: '#/components/schemas/LineHealth'
        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.
    LineHealth:
      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.'
        byod:
          type: boolean
          enum:
            - true
          description: 'Always `true`: this operation serves BYOD lines only.'
        state:
          type: string
          enum:
            - active
            - degraded
            - offline
          description: >-
            `offline`: the device of the line has not reported for 5 minutes or
            more, or has not reported since it was paired, and the line was not
            already `degraded` by its reception checks. `degraded`: the line
            fails its reception checks, or its device reports with a `send_text`
            capability (and, on an iMessage line, an `imessage` capability) that
            is not `active`. A line that is `degraded` because its reception
            checks fail stays `degraded` when its device stops reporting: read
            `last_heartbeat_at`. `active`: neither applies.
        last_heartbeat_at:
          type: string
          nullable: true
          description: >-
            Timestamp of the last report of the paired device (ISO 8601, UTC).
            `null` when the line has no active device session, or when the
            device has never reported.
        daily_quota_remaining:
          type: integer
          minimum: 0
          description: >-
            The smallest room left among the three 24-hour sending limits of the
            line: new contacts, known contacts and messages. Never below 0.
        apple_id_flagged:
          type: boolean
          description: >-
            `true` once the device has reported that Apple disabled or
            challenged the Apple ID of the line. `line.apple_id_flagged` is sent
            when it becomes `true`. Only iSnap sets it back to `false`, and no
            event announces that.
        last_error:
          type: string
          nullable: true
          description: >-
            Free text of at most 1,000 characters, or `null` when the line has
            no error: the reason reported with an Apple ID flag, the
            comma-separated reasons of a line that fails its reception checks,
            among `apple_account_reauth_required`, `phone_alias_unregistered`
            and `not_receiving`, or the text reported for the last message that
            failed. It is cleared when the line recovers from an `offline` or
            `degraded` state and when iSnap clears the Apple ID flag, so it can
            hold a message failure while `state` is `active`. Do not treat it as
            a fixed list of values.
        last_offline_at:
          type: string
          nullable: true
          description: >-
            Timestamp at which the most recent offline period started (ISO 8601,
            UTC). Kept after the line recovers. `null` when the line has never
            been offline.
        bridge_version:
          type: string
          nullable: true
          description: >-
            Version of the bridge app that runs on the paired device. `null`
            when the line has no active device session, or when the device has
            not reported it.
        runtime_capabilities:
          type: object
          nullable: true
          additionalProperties:
            type: string
            enum:
              - active
              - degraded
              - disabled
          description: >-
            What the device can do, as it last reported: one entry per
            capability, each `active`, `degraded` or `disabled`. The
            capabilities reported are `imessage`, `sms_fallback`, `send_text`,
            `send_attachment`, `reactions_out`, `reaction_remove_out`,
            `mark_read_out`, `typing_out`, `effects`, `reactions_in`,
            `read_receipts_in`, `typing_in` and `lookup_probe`; ignore the ones
            you do not know. `null` when the line has no active device session,
            or when the device has not reported any.
        device_state:
          type: string
          nullable: true
          enum:
            - online
            - degraded
            - offline
            - initializing
            - blocked
            - null
          description: >-
            The state the device last reported about itself, independent of
            `state`: `online`, `degraded`, `offline`, `initializing` or
            `blocked`. `null` when the line has no active device session, or
            when the device has not reported it.
        storage_free_bytes:
          type: integer
          nullable: true
          minimum: 0
          description: >-
            Free storage on the device, in bytes, as last reported. `null` means
            not reported, not zero.
      required:
        - line_id
        - byod
        - state
        - last_heartbeat_at
        - daily_quota_remaining
        - apple_id_flagged
        - last_error
        - last_offline_at
        - bridge_version
        - runtime_capabilities
        - device_state
        - storage_free_bytes
      description: The health of a BYOD line, from the last reports of its device.
  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.