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

# Send an SMS

> Queues one SMS for delivery. The price is quoted from the destination network and the number of segments, and your balance is charged when the message is handed to the carrier. The response returns right away with status `queued`; follow the message with [Get an SMS](/api-reference/sms/get) or a `callback` URL.



## OpenAPI

````yaml api-reference/openapi.yaml POST /messages/sms
openapi: 3.1.0
info:
  title: OTPBay API
  version: 1.0.0
  description: >-
    Send one-time passwords over Telegram and SMS, verify the codes your users
    enter, and send transactional SMS from your own sender ID.
  contact:
    name: OTPBay support
    email: hello@otpbay.com
servers:
  - url: https://api.otpbay.com/v1
    description: Production
security:
  - bearerAuth: []
tags:
  - name: Project
    description: The project that owns the API key.
  - name: Verify
    description: >-
      Send a code and check it. OTPBay generates the code and falls back from
      Telegram to SMS.
  - name: SMS
    description: Send any text message from one of your approved sender IDs.
  - name: Telegram
    description: Send a one-time code to a Telegram account through the Telegram Gateway.
paths:
  /messages/sms:
    post:
      tags:
        - SMS
      summary: Send an SMS
      description: >-
        Queues one SMS for delivery. The price is quoted from the destination
        network and the number of segments, and your balance is charged when the
        message is handed to the carrier. The response returns right away with
        status `queued`; follow the message with [Get an
        SMS](/api-reference/sms/get) or a `callback` URL.
      operationId: sendSms
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/SendSmsRequest'
            example:
              to: '+447700900123'
              from: Acme
              body: Your Acme order 1042 has shipped.
              callback: https://example.com/webhooks/otpbay
              metadata:
                order_id: '1042'
      responses:
        '201':
          description: The SMS was saved and queued.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SmsMessage'
              example:
                sid: SM6650c4b7c2d3e4f5a6b7c8d9
                status: queued
                to: '+447700900123'
                from: Acme
                body: Your Acme order 1042 has shipped.
                sms_segments: 1
                cost: '0.04'
                metadata:
                  order_id: '1042'
                date_created: '2026-09-26T10:20:11.302Z'
                processed_at: null
        '400':
          $ref: '#/components/responses/InvalidJson'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/InsufficientBalance'
        '403':
          $ref: '#/components/responses/ChannelDisabled'
        '422':
          description: >-
            `INVALID_REQUEST_BODY`, `SENDER_ID_REQUIRED` (no `from` and no
            default sender ID), `SENDER_ID_NOT_APPROVED` or
            `DESTINATION_NOT_PRICED`.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error:
                  code: SENDER_ID_NOT_APPROVED
                  message: '"Acme" is not an approved sender ID for this project.'
        '503':
          $ref: '#/components/responses/ServiceUnavailable'
components:
  schemas:
    SendSmsRequest:
      type: object
      required:
        - to
        - body
      additionalProperties: false
      properties:
        to:
          $ref: '#/components/schemas/PhoneNumber'
        from:
          type: string
          minLength: 3
          maxLength: 11
          pattern: ^(?=.*[A-Za-z])[A-Za-z0-9]{3,11}$
          description: >-
            One of your project's approved sender IDs: 3–11 letters and digits
            with at least one letter. Defaults to the SMS default sender ID from
            project settings.
          example: Acme
        body:
          type: string
          maxLength: 10240
          description: >-
            Message text. Long messages are split into segments and billed per
            segment: 160 characters (153 per part) for plain text, 70 (67 per
            part) if the text contains any non-ASCII character such as emoji or
            accented letters.
          example: Your Acme order 1042 has shipped.
        metadata:
          $ref: '#/components/schemas/Metadata'
        callback:
          $ref: '#/components/schemas/CallbackUrl'
    SmsMessage:
      type: object
      required:
        - sid
        - status
        - to
        - from
        - body
        - sms_segments
        - cost
        - metadata
        - date_created
        - processed_at
      properties:
        sid:
          type: string
          pattern: ^SM[a-f0-9]{24}$
          description: Unique SMS ID.
          example: SM6650c4b7c2d3e4f5a6b7c8d9
        status:
          type: string
          enum:
            - queued
            - processing
            - sent
            - failed
            - enqueue_failed
          description: >-
            `queued` → `processing` → `sent` when the carrier accepts the
            message, or `failed` after retries. `enqueue_failed` means the
            message was saved but never queued.
        to:
          $ref: '#/components/schemas/PhoneNumber'
        from:
          type:
            - string
            - 'null'
          description: Sender ID the message was sent from.
          example: Acme
        body:
          type: string
          example: Your Acme order 1042 has shipped.
        sms_segments:
          type: integer
          description: Number of billed segments.
          example: 1
        cost:
          allOf:
            - $ref: '#/components/schemas/Money'
          description: Price of the message (per-segment price × segments).
          example: '0.04'
        metadata:
          $ref: '#/components/schemas/Metadata'
        date_created:
          type: string
          format: date-time
        processed_at:
          type:
            - string
            - 'null'
          format: date-time
          description: When the carrier accepted the message.
        last_error:
          type: string
          description: Latest delivery error. Only present when there is one.
    Error:
      type: object
      required:
        - error
      properties:
        error:
          type: object
          required:
            - code
            - message
          properties:
            code:
              type: string
              description: >-
                Stable, machine-readable error code. Branch on this, not on
                `message`.
              example: INSUFFICIENT_BALANCE
            message:
              type: string
              description: Human-readable explanation. The wording can change.
              example: Insufficient balance for this verification.
    PhoneNumber:
      type: string
      description: >-
        Destination phone number in international format. OTPBay normalizes it
        to E.164, so `+1 (415) 555-2671` becomes `+14155552671`.
      example: '+14155552671'
    Metadata:
      type: object
      description: >-
        Your own key-value data, returned in responses and webhooks. At most 32
        keys of 1–64 characters. Values are strings (up to 512 characters),
        numbers or booleans.
      maxProperties: 32
      additionalProperties:
        oneOf:
          - type: string
            maxLength: 512
          - type: number
          - type: boolean
      example:
        user_id: usr_1042
    CallbackUrl:
      type: string
      format: uri
      maxLength: 2048
      description: >-
        Public `http` or `https` URL that receives [status webhooks](/webhooks).
        Localhost, private and link-local addresses are rejected. Defaults to
        the channel's default callback from project settings.
      example: https://example.com/webhooks/otpbay
    Money:
      type: string
      pattern: ^\d+\.\d{2}$
      description: Amount in US dollars as a decimal string.
      example: '0.02'
  responses:
    InvalidJson:
      description: '`INVALID_JSON` or `INVALID_E164`.'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error:
              code: INVALID_JSON
              message: Invalid JSON body
    Unauthorized:
      description: '`MISSING_API_KEY` or `INVALID_API_KEY`.'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error:
              code: INVALID_API_KEY
              message: Invalid API key.
    InsufficientBalance:
      description: '`INSUFFICIENT_BALANCE` — top up your project balance.'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error:
              code: INSUFFICIENT_BALANCE
              message: Insufficient balance for this SMS destination.
    ChannelDisabled:
      description: >-
        `CHANNEL_DISABLED` — the channel is turned off in project settings, or
        `IP_NOT_ALLOWED`.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error:
              code: CHANNEL_DISABLED
              message: SMS is turned off for this project.
    ServiceUnavailable:
      description: >-
        `QUEUE_UNAVAILABLE`, `PRICING_NOT_CONFIGURED`, `TELEGRAM_UNAVAILABLE` or
        `TELEGRAM_NOT_CONFIGURED` — a temporary problem on our side. Retry with
        backoff.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error:
              code: QUEUE_UNAVAILABLE
              message: >-
                SMS saved but queue is unavailable — try again later or check
                Redis.
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      description: >-
        Your project API key, sent as `Authorization: Bearer otp_live_...`.
        Create keys on the **API Keys** page of the dashboard.

````