openapi: 3.0.0
info:
  title: Instasent Transactional API (A2P Messaging API)
  description: |
    Instasent Transactional API, also known as the **A2P Messaging API**.
    Send SMS, perform lookups and manage transactional traffic from your
    application.
  version: 1.0.0
  contact:
    name: Instasent
    email: dev@instasent.com
    url: https://instasent.com
  license:
    name: Instasent
    url: https://www.instasent.com/aviso-legal
externalDocs:
  url: https://docs.instasent.com,
  description: Access to external documentation
servers:
  - url: https://api.instasent.com
    description: Instasent Transactional API (A2P Messaging API)
security:
  - BearerAuth: []
tags:
  - name: account
    description: Account related operations
  - name: lookup
    description: Lookup related operations
  - name: price
    description: Price related operations
  - name: sms
    description: Sms related operations
paths:
  /sms:
    get:
      operationId: sms-list
      summary: List SMS
      description: |
        Request SMS collection, paginated via `page` and `per_page`.

        - Results are sorted by creation date, descending.
        - Only SMS charged within the **last 21 days** are returned.
        - SMS in `draft`, `unpaid` and `error` status are always excluded.

        To track SMS status changes in real time, use delivery report webhooks.
      tags:
        - sms
      parameters:
        - name: page
          in: query
          description: 'Page number, zero-based. Maximum: 100.'
          required: false
          schema:
            type: integer
            minimum: 0
            maximum: 100
            default: 0
        - name: per_page
          in: query
          description: 'Number of results per page. Maximum: 50.'
          required: false
          schema:
            type: integer
            minimum: 1
            maximum: 50
            default: 50
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                type: object
                properties:
                  entities:
                    type: array
                    items:
                      $ref: '#/components/schemas/ResponseSmsItem'
                  metadata:
                    $ref: '#/components/schemas/ListMetadata'
                required:
                  - entities
                  - metadata
        '400':
          $ref: '#/components/responses/WrongRequestError'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '429':
          $ref: '#/components/responses/RateLimitError'
        '500':
          $ref: '#/components/responses/InternalError'
      path: /sms
      method: GET
    post:
      operationId: sms-create
      summary: Create an SMS
      description: |
        Create an SMS.

        ### Sender resolution

        Two ways to identify the sender, in order of preference:

        | # | Body field          | Behavior                                                                                                                                | When to use                                                                              |
        |---|---------------------|-----------------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------|
        | 1 | `sender` (id)       | Direct lookup of one of your senders. **Recommended.** Unknown ids return `422`.                                                | All traffic where you have a sender for that destination. Stable across renames; unambiguous. |
        | 2 | `from` (3–14 chars) | Alphanumeric sender name. Matches one of your senders by name; if none matches, delivered via the wildcard route.               | Wildcard route, or backwards compatibility for clients that pass the sender name only.        |

        Notes:

        - When `sender` is provided, `from` may be omitted; the response always returns the sender's canonical name.
        - When both `sender` and `from` are sent, **`sender` wins** and `from` in the response is overwritten with the sender's name.
        - Mode #1 always identifies a sender — it never falls through to the wildcard route. Mode #2 is the only path that can produce wildcard route traffic.
      tags:
        - sms
      requestBody:
        $ref: '#/components/requestBodies/SmsItemBody'
      responses:
        '201':
          description: Success
          content:
            application/json:
              schema:
                type: object
                properties:
                  entity:
                    $ref: '#/components/schemas/ResponseSmsItem'
                required:
                  - entity
        '400':
          $ref: '#/components/responses/WrongRequestError'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '402':
          $ref: '#/components/responses/NoFundsError'
        '413':
          $ref: '#/components/responses/RequestTooLarge'
        '422':
          $ref: '#/components/responses/ValidationError'
        '429':
          $ref: '#/components/responses/RateLimitError'
        '500':
          $ref: '#/components/responses/InternalError'
      path: /sms
      method: POST
  /sms/{id}:
    get:
      operationId: sms-view
      summary: Get an SMS
      description: Request single SMS
      tags:
        - sms
      parameters:
        - name: id
          in: path
          description: SMS identifier
          required: true
          schema:
            type: string
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                type: object
                properties:
                  entity:
                    $ref: '#/components/schemas/ResponseSmsItem'
                required:
                  - entity
        '400':
          $ref: '#/components/responses/WrongRequestError'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '404':
          $ref: '#/components/responses/NotFound'
        '429':
          $ref: '#/components/responses/RateLimitError'
        '500':
          $ref: '#/components/responses/InternalError'
      path: /sms/{id}
      method: GET
  /sms/bulk:
    post:
      operationId: sms-create-bulk
      summary: Create a Bulk SMS
      description: |
        Create an SMS collection (up to 100 items per call).

        Sender resolution is identical to `POST /sms` and is applied per
        item — see that endpoint's description for the full rules. **The
        `sender` (id) field is the recommended form**; an alphanumeric
        `from` is for the wildcard route or backwards-compatible clients.
      tags:
        - sms
      requestBody:
        $ref: '#/components/requestBodies/SmsCollectionBody'
      responses:
        '201':
          description: Success
          content:
            application/json:
              schema:
                type: object
                properties:
                  entities:
                    type: array
                    items:
                      $ref: '#/components/schemas/ResponseSmsItem'
                  errors:
                    type: array
                    items:
                      type: object
                      properties:
                        fields:
                          type: object
                          properties:
                            to:
                              type: array
                              items:
                                type: string
        '400':
          $ref: '#/components/responses/WrongRequestError'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '402':
          $ref: '#/components/responses/NoFundsError'
        '413':
          $ref: '#/components/responses/RequestTooLarge'
        '422':
          $ref: '#/components/responses/ValidationError'
        '429':
          $ref: '#/components/responses/RateLimitError'
        '500':
          $ref: '#/components/responses/InternalError'
      path: /sms/bulk
      method: POST
  /lookup:
    get:
      operationId: lookup-list
      summary: List Lookup
      description: |
        Request Lookup collection, paginated via `page` and `per_page`.

        - Results are sorted by creation date, descending.
        - Lookups in `enqueued`, `unpaid` and `error` status are always excluded.
      tags:
        - lookup
      parameters:
        - name: page
          in: query
          description: 'Page number, zero-based.'
          required: false
          schema:
            type: integer
            minimum: 0
            default: 0
        - name: per_page
          in: query
          description: 'Number of results per page. Maximum: 50.'
          required: false
          schema:
            type: integer
            minimum: 1
            maximum: 50
            default: 50
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                type: object
                properties:
                  entities:
                    type: array
                    items:
                      $ref: '#/components/schemas/ResponseLookupItem'
                  metadata:
                    $ref: '#/components/schemas/ListMetadata'
                required:
                  - entities
                  - metadata
        '400':
          $ref: '#/components/responses/WrongRequestError'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '429':
          $ref: '#/components/responses/RateLimitError'
        '500':
          $ref: '#/components/responses/InternalError'
      path: /lookup
      method: GET
    post:
      operationId: lookup-create
      summary: Create a Lookup
      description: Create a Lookup
      tags:
        - lookup
      requestBody:
        $ref: '#/components/requestBodies/LookupItemBody'
      responses:
        '201':
          description: Success
          content:
            application/json:
              schema:
                type: object
                properties:
                  entity:
                    $ref: '#/components/schemas/ResponseLookupItem'
                required:
                  - entity
        '400':
          $ref: '#/components/responses/WrongRequestError'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '402':
          $ref: '#/components/responses/NoFundsError'
        '413':
          $ref: '#/components/responses/RequestTooLarge'
        '422':
          $ref: '#/components/responses/ValidationError'
        '429':
          $ref: '#/components/responses/RateLimitError'
        '500':
          $ref: '#/components/responses/InternalError'
      path: /lookup
      method: POST
  /lookup/{id}:
    get:
      operationId: lookup-view
      summary: Get a Lookup
      description: Request single Lookup
      tags:
        - lookup
      parameters:
        - name: id
          in: path
          description: Lookup identifier
          required: true
          schema:
            type: string
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                type: object
                properties:
                  entity:
                    $ref: '#/components/schemas/ResponseLookupItem'
                required:
                  - entity
        '400':
          $ref: '#/components/responses/WrongRequestError'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '404':
          $ref: '#/components/responses/NotFound'
        '429':
          $ref: '#/components/responses/RateLimitError'
        '500':
          $ref: '#/components/responses/InternalError'
      path: /lookup/{id}
      method: GET
  /organization/account:
    get:
      operationId: account-balance
      summary: Get account balance
      description: Request organization balance
      tags:
        - account
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                type: object
                properties:
                  entity:
                    type: object
                    properties:
                      currency:
                        type: string
                      available:
                        type: number
                    required:
                      - currency
                      - available
                required:
                  - entity
        '400':
          $ref: '#/components/responses/WrongRequestError'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '429':
          $ref: '#/components/responses/RateLimitError'
        '500':
          $ref: '#/components/responses/InternalError'
      path: /organization/account
      method: GET
  /sms/price-profile/me/countries:
    get:
      operationId: sms-price-country
      summary: Get SMS price
      description: Request Sms country prices
      tags:
        - price
        - sms
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                type: object
                properties:
                  entities:
                    type: array
                    items:
                      type: object
                      properties:
                        currency:
                          type: string
                        price:
                          type: number
                      required:
                        - currency
                        - price
                required:
                  - entities
        '400':
          $ref: '#/components/responses/WrongRequestError'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '429':
          $ref: '#/components/responses/RateLimitError'
        '500':
          $ref: '#/components/responses/InternalError'
      path: /sms/price-profile/me/countries
      method: GET
  /lookup/price-profile/me/countries:
    get:
      operationId: lookup-price-country
      summary: Get Lookup price
      description: Request Lookup country prices
      tags:
        - price
        - lookup
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                type: object
                properties:
                  entities:
                    type: array
                    items:
                      type: object
                      properties:
                        currency:
                          type: string
                        price:
                          type: number
                      required:
                        - currency
                        - price
                required:
                  - entities
        '400':
          $ref: '#/components/responses/WrongRequestError'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '429':
          $ref: '#/components/responses/RateLimitError'
        '500':
          $ref: '#/components/responses/InternalError'
      path: /lookup/price-profile/me/countries
      method: GET
components:
  securitySchemes:
    BearerAuth:
      type: http
      scheme: bearer
  requestBodies:
    SmsItemBody:
      description: A single SMS item
      required: true
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/RequestSmsItem'
    SmsCollectionBody:
      description: A collection of SMS items
      required: true
      content:
        application/json:
          schema:
            type: array
            items:
              $ref: '#/components/schemas/RequestSmsItem'
            minItems: 1
            maxItems: 100
    LookupItemBody:
      description: A single Lookup item
      required: true
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/RequestLookupItem'
  schemas:
    ListMetadata:
      type: object
      description: Pagination metadata for list responses
      properties:
        count:
          type: integer
          description: Number of entities in the current page
        total_count:
          type: integer
          description: Total number of entities matching the listing
        items_per_page:
          type: integer
          description: Page size applied to the request
        page_number:
          type: integer
          description: Zero-based page number of the current page
      required:
        - count
        - total_count
        - items_per_page
        - page_number
    RequestSmsItem:
      type: object
      description: |
        SMS request payload. The sender is identified via either `sender`
        (recommended) or `from` — see the sender resolution table on the
        `POST /sms` endpoint. At least one of the two must be provided.
      properties:
        clientId:
          type: string
          maxLength: 40
          description: Must be unique per SMS
        sender:
          type: string
          description: |
            **Recommended.** Id of one of your senders. When provided,
            `from` may be omitted; the response always returns the
            sender's canonical name in `from`. Unknown ids return `422`.
        from:
          type: string
          minLength: 3
          maxLength: 14
          description: |
            Alphanumeric sender name. Matches one of your senders by
            name; if no match, delivered via the wildcard route. The
            only form that produces wildcard route traffic. Max 11
            chars (alphanumeric) or 14 digits (numeric). Optional when
            `sender` is provided.
        to:
          type: string
          maxLength: 15
          description: E164 format
        text:
          type: string
        allowUnicode:
          type: boolean
          default: false
      required:
        - to
        - text
    ResponseSmsItem:
      type: object
      properties:
        id:
          type: string
        clientId:
          type: string
          nullable: true
          default: null
        status:
          type: string
        statusCode:
          type: integer
          nullable: true
          default: null
        sender:
          type: string
          nullable: true
          description: Id of the sender used for delivery (resolved server-side). Null when the message went via the wildcard route.
        from:
          type: string
          description: |
            Sender name actually used for delivery. For traffic routed
            via a sender this is the sender's canonical name; for
            traffic routed via the wildcard route this is the
            client-supplied name.
        country:
          type: string
        to:
          type: string
        normalizedTo:
          type: string
        charsCount:
          type: integer
        text:
          type: string
        deliveredText:
          type: string
        messagesCount:
          type: integer
        encoding:
          type: string
        unicode:
          type: boolean
        allowUnicode:
          type: boolean
        charged:
          type: boolean
        pricePerSms:
          type: number
        priceUser:
          type: number
        createdAt:
          type: string
        chargedAt:
          type: string
          nullable: true
          default: null
        scheduledAt:
          type: string
          nullable: true
          default: null
        sentAt:
          type: string
          nullable: true
          default: null
        deliveredAt:
          type: string
          nullable: true
          default: null
      required:
        - id
        - clientId
        - status
        - from
        - country
        - to
        - normalizedTo
        - charsCount
        - text
        - deliveredText
        - messagesCount
        - encoding
        - unicode
        - allowUnicode
        - charged
        - createdAt
    RequestLookupItem:
      type: object
      properties:
        to:
          type: string
          maxLength: 15
          description: E164 format
      required:
        - to
    ResponseLookupItem:
      type: object
      properties:
        id:
          type: string
        status:
          type: string
        subscriberStatus:
          type: string
          nullable: true
          default: null
        statusCode:
          type: integer
          nullable: true
          default: null
        country:
          type: string
        imsi:
          type: string
          nullable: true
          default: null
        servingMsc:
          type: string
          nullable: true
          default: null
        to:
          type: string
        normalizedTo:
          type: string
        ported:
          type: boolean
        roaming:
          type: boolean
        network:
          type: string
        charged:
          type: boolean
        pricePerSms:
          type: number
        createdAt:
          type: string
        deliveredAt:
          type: string
          nullable: true
          default: null
      required:
        - id
        - status
        - country
        - to
        - normalizedTo
    ResponseErrorDetail:
      type: object
      properties:
        title:
          type: string
        status:
          type: integer
        detail:
          type: string
      required:
        - title
        - status
        - detail
    ResponseErrorMessage:
      type: object
      properties:
        message:
          type: string
        code:
          type: integer
      required:
        - message
    ResponseErrorValidation:
      type: object
      properties:
        errors:
          type: object
          properties:
            fields:
              type: object
              properties:
                to:
                  type: array
                  items:
                    type: string
          required:
            - fields
      required:
        - errors
  responses:
    WrongRequestError:
      description: Request body is malformed or something went wrong with your request
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ResponseErrorDetail'
    UnauthorizedError:
      description: You are missing or using bad credentials
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ResponseErrorDetail'
    NoFundsError:
      description: You're out of money
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ResponseErrorDetail'
    NotFound:
      description: Resource can't be found
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ResponseErrorDetail'
    RequestTooLarge:
      description: You are sending a large body in your request
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ResponseErrorDetail'
    ValidationError:
      description: Some field of your request body is not valid
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ResponseErrorValidation'
    RateLimitError:
      description: You reached your endpoint rate limit
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ResponseErrorMessage'
    InternalError:
      description: Internal server error
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ResponseErrorDetail'
