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

# Check iMessage, RCS or SMS support

> Checks which service Blujay would use to reach a US phone number from one of your numbers: `iMessage`, `RCS` or `SMS`. If Blujay can't confirm iMessage or RCS, the result is `SMS`.

If Blujay already checked the same recipient from the same number in the last five minutes (through this endpoint, the Blujay app, or a send), you get that answer with `source: cached`. Cached answers are free and never limited.

A fresh check runs from your number and shares its capacity with your messages, which always go first. Each of your numbers can run 30 fresh checks per clock hour and 100 per UTC day. Over a limit, or while the number is busy, the call returns `429 RATE_LIMIT_EXCEEDED` with `Retry-After`.

This endpoint counts toward your read request limit, not your write limit.




## OpenAPI

````yaml /api-reference/openapi.yaml post /v1/capability/evaluate_service
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/capability/evaluate_service:
    post:
      tags:
        - Capability
      summary: Check iMessage, RCS or SMS support
      description: >
        Checks which service Blujay would use to reach a US phone number from
        one of your numbers: `iMessage`, `RCS` or `SMS`. If Blujay can't confirm
        iMessage or RCS, the result is `SMS`.


        If Blujay already checked the same recipient from the same number in the
        last five minutes (through this endpoint, the Blujay app, or a send),
        you get that answer with `source: cached`. Cached answers are free and
        never limited.


        A fresh check runs from your number and shares its capacity with your
        messages, which always go first. Each of your numbers can run 30 fresh
        checks per clock hour and 100 per UTC day. Over a limit, or while the
        number is busy, the call returns `429 RATE_LIMIT_EXCEEDED` with
        `Retry-After`.


        This endpoint counts toward your read request limit, not your write
        limit.
      operationId: evaluatePublicCapabilityService
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/EvaluateCapabilityRequest'
            examples:
              checkPhone:
                value:
                  number: '+15555550123'
                  from_phone_number_id: phone_abc123
      responses:
        '200':
          description: The service Blujay would use.
          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/CapabilityServiceResult'
              examples:
                imessage:
                  summary: iMessage-capable number
                  value:
                    status: success
                    data:
                      number: '+15555550123'
                      service: iMessage
                      checked_at: '2026-10-14T12:00:00.000Z'
                      source: fresh
                    trace_id: trc_8f2a1c0e4b7d
                    timestamp: '2026-10-14T12:00:00.000Z'
                cached:
                  summary: Cached answer from a recent check
                  value:
                    status: success
                    data:
                      number: '+15555550123'
                      service: iMessage
                      checked_at: '2026-10-14T11:58:12.000Z'
                      source: cached
                    trace_id: trc_8f2a1c0e4b7d
                    timestamp: '2026-10-14T12:00:00.000Z'
                smsFallback:
                  summary: SMS result (iMessage and RCS not confirmed)
                  value:
                    status: success
                    data:
                      number: '+15555550123'
                      service: SMS
                      checked_at: '2026-10-14T12:00:00.000Z'
                      source: fresh
                    trace_id: trc_8f2a1c0e4b7d
                    timestamp: '2026-10-14T12:00:00.000Z'
        '400':
          $ref: '#/components/responses/ValidationError'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
        '429':
          description: >
            Your number can't run another fresh check yet. `details[0].limit`
            tells you why:

            - `line_capacity`: the number is busy with messages or your recent
            checks.

            - `line_hourly_quota`: it has run 30 fresh checks this clock hour.

            - `line_daily_quota`: it has run 100 fresh checks this UTC day.


            Retry after `Retry-After` seconds.
          headers:
            Retry-After:
              description: Whole seconds until a fresh check can run from this number.
              schema:
                type: integer
            X-Trace-ID:
              $ref: '#/components/headers/XTraceID'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
              examples:
                hourlyQuota:
                  value:
                    status: error
                    error:
                      code: RATE_LIMIT_EXCEEDED
                      message: >-
                        This phone number cannot run another capability check
                        yet
                      type: rate_limit
                      http_status: 429
                      retryable: true
                      doc_url: https://docs.blujay.io/errors/rate-limit-exceeded
                      details:
                        - limit: line_hourly_quota
                      retry_after: 1260
                    trace_id: trc_8f2a1c0e4b7d
                    timestamp: '2026-10-14T12:39:00.000Z'
        '500':
          description: Unexpected server error.
          headers:
            X-Trace-ID:
              $ref: '#/components/headers/XTraceID'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
        '503':
          description: >-
            Capability checks are temporarily unavailable
            (`CAPABILITY_CHECK_UNAVAILABLE`). Retry after `Retry-After` seconds.
          headers:
            Retry-After:
              schema:
                type: integer
            X-Trace-ID:
              $ref: '#/components/headers/XTraceID'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
      security:
        - PublicApiKey: []
components:
  schemas:
    EvaluateCapabilityRequest:
      type: object
      additionalProperties: false
      required:
        - number
      description: >-
        `from_phone_number_id` is optional only when your workspace has exactly
        one active number. With more than one, leave it out and you get `400
        PHONE_NUMBER_REQUIRED`; send it to choose the number.
      properties:
        number:
          type: string
          description: The US phone number to check.
          examples:
            - '+15555550123'
        from_phone_number_id:
          $ref: '#/components/schemas/PhoneNumberId'
    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.
    CapabilityServiceResult:
      type: object
      additionalProperties: false
      required:
        - number
        - service
        - checked_at
        - source
      properties:
        number:
          type: string
          examples:
            - '+15555550123'
        service:
          type: string
          enum:
            - iMessage
            - RCS
            - SMS
          description: >-
            `SMS` means either that SMS is confirmed or that Blujay couldn't
            confirm iMessage or RCS.
        checked_at:
          type: string
          examples:
            - '2026-10-14T17:01:00.000Z'
          format: date-time
          description: >-
            When the check ran. For a cached answer, this is earlier than your
            request.
        source:
          type: string
          enum:
            - cached
            - fresh
          description: >-
            `fresh` when this request ran a check (or joined one already
            running); `cached` when Blujay reused a recent answer: up to five
            minutes old for a confirmed answer, or 30 seconds for an
            inconclusive `SMS` answer.
    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.
    PhoneNumberId:
      type: string
      examples:
        - phone_abc123
      pattern: ^phone_[A-Za-z0-9_-]+$
    TraceId:
      type: string
      examples:
        - trc_8f2a1c0e4b7d
      pattern: ^trc_[A-Za-z0-9_-]+$
    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'
    Unauthorized:
      description: >-
        The API key is missing or invalid (`UNAUTHORIZED`), revoked
        (`API_KEY_REVOKED`) or expired (`API_KEY_EXPIRED`).
      headers:
        X-Trace-ID:
          $ref: '#/components/headers/XTraceID'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorEnvelope'
    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.