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

# Send Message

> Send a message to one or multiple recipients

<Note>
  Refer to [Authentication](/authentication) for information on how to obtain a
  bearer token. This endpoint requires the `message.sms.send.oneway` API client
  authorization scope to send one way messages. You can set up scopes on the
  [API Clients](https://cloud.belio.co.ke/team-overview/api-access-keys) page.
</Note>

### Rate Limit

This endpoint is rate limited to **400** messages per second.

## Request Modes

The required `type` field selects one of four request modes. **Free-form** modes
compose raw message text; **template** modes send a pre-approved template by
referencing its `templateId` (see [SMS Templates](/messaging/sms/templates/introduction)).

| `type`               | Kind      | Description                                          |
| -------------------- | --------- | ---------------------------------------------------- |
| `SendToEach`         | Free-form | Message tailored per recipient                       |
| `SendToMany`         | Free-form | Same message sent to multiple recipients             |
| `TemplateSendToEach` | Template  | Each recipient receives their own parameter values   |
| `TemplateSendToMany` | Template  | One shared parameter set sent to multiple recipients |

### Limits

| Rule                           | Free-form (`SendToEach` / `SendToMany`) | Template (`TemplateSendToEach` / `TemplateSendToMany`) |
| ------------------------------ | --------------------------------------- | ------------------------------------------------------ |
| Maximum recipients per request | **100**                                 | **10**                                                 |
| Maximum message length         | **960** characters                      | **960** characters (after parameters are resolved)     |
| SMS message unit size          | **160** characters                      | **160** characters                                     |

### Request Schemas

<Tabs>
  <Tab title="SendToEach">
    Send individually tailored free-form messages to multiple recipients.

    | Field            | Type      | Required | Description                        |
    | ---------------- | --------- | -------- | ---------------------------------- |
    | `type`           | string    | yes      | Must be `"SendToEach"`             |
    | `messages`       | object\[] | yes      | Per-recipient entries (**1–100**)  |
    | `receiptRequest` | object    | no       | Optional delivery receipt callback |

    Each item in `messages`:

    | Field     | Type   | Required | Description                           |
    | --------- | ------ | -------- | ------------------------------------- |
    | `phone`   | string | yes      | Recipient phone number                |
    | `message` | string | yes      | Message text (max **960** characters) |

    ```bash theme={null}
    curl --request POST \
    --url https://api.belio.co.ke/message/{serviceId} \
    --header 'Authorization: Bearer <token>' \
    --header 'Content-Type: application/json' \
    --data '{
        "type": "SendToEach",
        "messages": [
    {
        "phone": "254700111213",
        "message": "Hi Alice, your order #1042 has shipped."
    },
    {
        "phone": "254700111214",
        "message": "Hi Bob, your order #1043 has shipped."
    }
        ]
    }'
    ```
  </Tab>

  <Tab title="SendToMany">
    Send the same free-form message to multiple phone numbers.

    | Field            | Type      | Required | Description                           |
    | ---------------- | --------- | -------- | ------------------------------------- |
    | `type`           | string    | yes      | Must be `"SendToMany"`                |
    | `addresses`      | string\[] | yes      | Recipient phone numbers (**1–100**)   |
    | `message`        | string    | yes      | Message text (max **960** characters) |
    | `receiptRequest` | object    | no       | Optional delivery receipt callback    |

    ```bash theme={null}
    curl --request POST \
    --url https://api.belio.co.ke/message/{serviceId} \
    --header 'Authorization: Bearer <token>' \
    --header 'Content-Type: application/json' \
    --data '{
        "type": "SendToMany",
        "addresses": [
        "+254700111213",
        "254750108109"
        ],
        "message": "Your appointment is confirmed for tomorrow at 10am.",
        "receiptRequest": {
        "correlator": "reminder-batch-001",
        "callbackUrl": "https://example.com/dlr"
    }
    }'
    ```
  </Tab>

  <Tab title="TemplateSendToEach">
    Send the same template to multiple recipients, each with their own parameter values.

    | Field            | Type      | Required | Description                        |
    | ---------------- | --------- | -------- | ---------------------------------- |
    | `type`           | string    | yes      | Must be `"TemplateSendToEach"`     |
    | `templateId`     | string    | yes      | ID of the SMS template             |
    | `messages`       | object\[] | yes      | Per-recipient entries (**1–10**)   |
    | `receiptRequest` | object    | no       | Optional delivery receipt callback |

    Each item in `messages`:

    | Field    | Type      | Required | Description                                                                   |
    | -------- | --------- | -------- | ----------------------------------------------------------------------------- |
    | `phone`  | string    | yes      | Recipient phone number                                                        |
    | `params` | object\[] | yes      | [Template parameters](/messaging/sms/templates/parameters) for this recipient |

    ```bash theme={null}
    curl --request POST \
    --url https://api.belio.co.ke/message/{serviceId} \
    --header 'Authorization: Bearer <token>' \
    --header 'Content-Type: application/json' \
    --data '{
        "type": "TemplateSendToEach",
        "templateId": "tpl-sms-001",
        "messages": [
    {
        "phone": "254700111213",
        "params": [
    { "name": "sample", "value": "Alice" },
    { "name": "code", "value": "111111" }
        ]
    },
    {
        "phone": "254700111214",
        "params": [
    { "name": "sample", "value": "Bob" },
    { "name": "code", "value": "222222" }
        ]
    }
        ]
    }'
    ```
  </Tab>

  <Tab title="TemplateSendToMany">
    Send the same resolved template message to multiple phone numbers.

    | Field            | Type      | Required | Description                                                      |
    | ---------------- | --------- | -------- | ---------------------------------------------------------------- |
    | `type`           | string    | yes      | Must be `"TemplateSendToMany"`                                   |
    | `templateId`     | string    | yes      | ID of the SMS template                                           |
    | `addresses`      | string\[] | yes      | Recipient phone numbers (**1–10**)                               |
    | `params`         | object\[] | yes      | [Template parameter](/messaging/sms/templates/parameters) values |
    | `receiptRequest` | object    | no       | Optional delivery receipt callback                               |

    ```bash theme={null}
    curl --request POST \
    --url https://api.belio.co.ke/message/{serviceId} \
    --header 'Authorization: Bearer <token>' \
    --header 'Content-Type: application/json' \
    --data '{
        "type": "TemplateSendToMany",
        "templateId": "tpl-sms-001",
        "addresses": [
        "+254700111213",
        "254750108109"
        ],
        "params": [
    { "name": "sample", "value": "Alice" },
    { "name": "code", "value": "654321" }
        ],
        "receiptRequest": {
        "correlator": "otp-batch-001",
        "callbackUrl": "https://example.com/dlr"
    }
    }'
    ```
  </Tab>
</Tabs>

<Note>
  **Important:** for `TemplateSendToEach` and `TemplateSendToMany`, after all
  parameters are substituted, the final message must not exceed **960
  characters**. A longer resolved message is rejected with `Resolved content
        cannot be longer than 960 characters`. There is no truncation or fallback.
</Note>

## Errors

### General errors

| HTTP | Condition                  | Example `desc`                                                                                                                                                                                                       |
| ---- | -------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| 400  | Invalid phone numbers      | `Invalid phone numbers: ...`                                                                                                                                                                                         |
| 400  | Empty addresses / messages | `No valid recipients found...` or `No valid messages found...`                                                                                                                                                       |
| 400  | Too many recipients        | `Maximum number of recipients exceeded.` (100 for free-form, 10 for template modes)                                                                                                                                  |
| 400  | Template not found         | `Message template tpl-sms-001 not found.`                                                                                                                                                                            |
| 400  | Template not sendable      | `Message template tpl-sms-001 is not sendable. Current status: Active and approval status: PENDING`                                                                                                                  |
| 400  | Managed service not found  | `Managed service descriptor not found for key: otp-service`. See [Belio-managed Senders and Approval](/messaging/sms/templates/introduction#belio-managed-senders-and-approval).                                     |
| 400  | Category mismatch          | `Template category AUTHENTICATION does not match managed service descriptor category MARKETING`. See [Belio-managed Senders and Approval](/messaging/sms/templates/introduction#belio-managed-senders-and-approval). |
| 400  | Insufficient message units | Team balance error message                                                                                                                                                                                           |
| 400  | Invalid `receiptRequest`   | Correlator or callback URL validation message                                                                                                                                                                        |
| 401  | Authentication failure     | —                                                                                                                                                                                                                    |

### Template parameter validation errors

When parameter validation fails, the response is `HTTP 400` with `desc` set to `Template parameter validation failed`.

For **TemplateSendToEach**, errors are keyed by recipient phone number:

```json theme={null}
{
"desc": "Template parameter validation failed",
    "result": {
    "254700111213": [
        "Missing required parameter 'code'"
    ],
        "254700111214": [
        "Missing required parameter 'code'",
        "Parameter 'sample': Value for parameter 'sample' must be a valid name"
    ]
}
}
```

For **TemplateSendToMany**, errors are returned under a single `errors` key:

```json theme={null}
{
"desc": "Template parameter validation failed",
    "result": {
    "errors": [
        "Missing required parameter 'code'",
        "Parameter 'code': Value for parameter 'code' must not exceed 6 characters"
    ]
}
}
```

### Common parameter validation messages

| Message                                                                         | Cause                                                          |
| ------------------------------------------------------------------------------- | -------------------------------------------------------------- |
| `Missing required parameter '{name}'`                                           | Required placeholder with no default; not supplied in `params` |
| `Unknown parameter '{name}'`                                                    | Supplied parameter not defined on the template                 |
| `Duplicate parameter '{name}'`                                                  | Same `name` appears more than once in `params`                 |
| `Parameter '{name}': Value for parameter '{name}' must not exceed N characters` | Value longer than `maxLength`                                  |
| `Parameter '{name}': Value for parameter '{name}' must be alphanumeric`         | `format` is `Alphanumeric`                                     |
| `Parameter '{name}': Value for parameter '{name}' must be numeric`              | `format` is `Numeric`                                          |
| `Parameter '{name}': Value for parameter '{name}' must be a valid name`         | `format` is `Name`                                             |
| `Value for parameter '{name}' must be non-empty`                                | Empty value                                                    |
| `Value for parameter '{name}' contains forbidden characters`                    | Value contains `{`, `}`, or control characters                 |
| `Name must be a non-empty identifier using letters, digits, and underscores`    | Invalid parameter name                                         |
| `Resolved content cannot be longer than 960 characters`                         | Substituted message too long                                   |

## Success Response

On success the endpoint returns `HTTP 200`:

```json theme={null}
{
"result": {
    "type": "SmsResponse",
        "requestId": "550e8400-e29b-41d4-a716-446655440000",
        "units": {
        "Safaricom": 1,
            "Airtel": 1
    },
    "addresses": {
        "Safaricom": 1,
            "Airtel": 1
    }
}
}
```

| Field     | Description                                                               |
| --------- | ------------------------------------------------------------------------- |
| requestId | Unique ID for this send request, used to correlate with delivery receipts |
| units     | Message units consumed per mobile network channel                         |
| addresses | Number of recipients routed per channel                                   |


## OpenAPI

````yaml POST /message/{serviceId}
openapi: 3.1.0
info:
  title: Belio API
  description: OpenAPI Specification for Belio's REST API
  contact:
    name: Belio API Support
    url: https://belio.co.ke
  version: 1.0.0
servers:
  - url: https://api.belio.co.ke
    description: API Server
security:
  - bearerAuth: []
paths:
  /message/{serviceId}:
    post:
      tags:
        - Message
      description: Send a message to one or multiple recipients
      operationId: sendMessage
      parameters:
        - name: serviceId
          in: path
          required: true
          schema:
            type: string
          description: Unique identifier for the messaging service
      requestBody:
        description: Message details for sending to one or multiple recipients
        content:
          application/json:
            schema:
              oneOf:
                - title: SendToEach
                  description: Send message to a single recipient
                  type: object
                  properties:
                    type:
                      type: string
                      enum:
                        - SendToEach
                      description: Indicates sending to a single recipient
                    messages:
                      type: array
                      items:
                        type: object
                        properties:
                          text:
                            type: string
                            description: Message content to be delivered. Cannot be empty
                          phone:
                            type: string
                            description: >-
                              Recipient's phone number e.g +254712345678,
                              25412345678, 0712345678. Cannot be empty
                        additionalProperties: false
                      description: Messages and recipients
                    receiptRequest:
                      type: object
                      properties:
                        correlator:
                          type: string
                          description: Client-provided identifier for correlation
                        callbackUrl:
                          type: string
                          format: uri
                          description: URL for delivery receipt callbacks
                      additionalProperties: false
                  required:
                    - type
                    - messages
                - title: SendToMany
                  description: Send message to multiple recipients
                  type: object
                  properties:
                    type:
                      type: string
                      enum:
                        - SendToMany
                      description: Indicates sending to multiple recipients
                    message:
                      type: string
                      description: >-
                        Message content to be delivered to all recipients.
                        Cannot be empty
                    addresses:
                      type: array
                      items:
                        type: string
                      description: >-
                        List of recipients' phone numbers e.g [+254712345678,
                        25412345678, 0712345678]. Cannot be empty
                    receiptRequest:
                      type: object
                      properties:
                        correlator:
                          type: string
                          description: Client-provided identifier for correlation
                        callbackUrl:
                          type: string
                          format: uri
                          description: URL for delivery receipt callbacks
                      additionalProperties: false
                  required:
                    - type
                    - addresses
                    - message
                - title: TemplateSendToMany
                  description: >-
                    Send the same resolved template message to multiple phone
                    numbers
                  type: object
                  properties:
                    type:
                      type: string
                      enum:
                        - TemplateSendToMany
                      description: >-
                        Indicates a shared parameter set sent to multiple
                        recipients
                    templateId:
                      type: string
                      description: ID of the SMS template
                    addresses:
                      type: array
                      minItems: 1
                      maxItems: 10
                      items:
                        type: string
                      description: Recipient phone numbers (1-10)
                    params:
                      type: array
                      items:
                        $ref: '#/components/schemas/SmsTemplateParameter'
                      description: Template parameter values
                    receiptRequest:
                      type: object
                      properties:
                        correlator:
                          type: string
                          description: Client-provided identifier for correlation
                        callbackUrl:
                          type: string
                          format: uri
                          description: URL for delivery receipt callbacks
                      additionalProperties: false
                  required:
                    - type
                    - templateId
                    - addresses
                    - params
                  additionalProperties: false
                - title: TemplateSendToEach
                  description: >-
                    Send the same template to multiple recipients, each with
                    their own parameter values
                  type: object
                  properties:
                    type:
                      type: string
                      enum:
                        - TemplateSendToEach
                      description: >-
                        Indicates each recipient receives their own parameter
                        values
                    templateId:
                      type: string
                      description: ID of the SMS template
                    messages:
                      type: array
                      minItems: 1
                      maxItems: 10
                      items:
                        type: object
                        properties:
                          phone:
                            type: string
                            description: Recipient phone number
                          params:
                            type: array
                            items:
                              $ref: '#/components/schemas/SmsTemplateParameter'
                            description: Template parameters for this recipient
                        required:
                          - phone
                          - params
                        additionalProperties: false
                      description: Per-recipient entries (1-10)
                    receiptRequest:
                      type: object
                      properties:
                        correlator:
                          type: string
                          description: Client-provided identifier for correlation
                        callbackUrl:
                          type: string
                          format: uri
                          description: URL for delivery receipt callbacks
                      additionalProperties: false
                  required:
                    - type
                    - templateId
                    - messages
                  additionalProperties: false
        required: true
      responses:
        '200':
          description: Message(s) sent successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MessageSendResponse'
        '400':
          description: >-
            Bad request - invalid input parameters or template parameter
            validation failure
          content:
            application/json:
              schema:
                anyOf:
                  - $ref: '#/components/schemas/APIError'
                  - $ref: '#/components/schemas/SmsTemplateParameterValidationFailure'
        '401':
          description: Unauthenticated - invalid credentials
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIError'
        '403':
          description: Unauthorized - Permission denied
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIError'
        '404':
          description: Not Found - the requested resource does not exist
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIError'
        '429':
          description: Rate limit
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AuthError'
        '500':
          description: Internal server error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIError'
components:
  schemas:
    SmsTemplateParameter:
      type: object
      properties:
        name:
          type: string
          description: >-
            Placeholder name - must match a {{name}} placeholder in the template
            content
        value:
          type: string
          description: Substitution value inserted into the template
      required:
        - name
        - value
      additionalProperties: false
    MessageSendResponse:
      type: object
      properties:
        desc:
          type: object
          description: The response
          properties:
            requestId:
              type: string
              format: uuid
              description: Unique identifier for the message request
            units:
              type: object
              description: Number of credit units consumed by the request
              properties:
                Safaricom:
                  type: integer
                  const: 34
                  description: Number of safaricom credits consumed by request
                Airtel:
                  type: integer
                  const: 16
                  description: Number of airtel credits consumed by request
            addresses:
              type: object
              description: Number of recipient addresses processed
              properties:
                Safaricom:
                  type: integer
                  const: 34
                  description: Number of safaricom recipient addresses processed
                Airtel:
                  type: integer
                  const: 45
                  description: Number of airtel recipient addresses processed
    APIError:
      type: object
      properties:
        desc:
          type: string
        result:
          description: Optional structured error details.
    SmsTemplateParameterValidationFailure:
      type: object
      properties:
        desc:
          type: string
          const: Template parameter validation failed
        result:
          oneOf:
            - $ref: '#/components/schemas/SmsTemplateSendToManyValidationResult'
            - $ref: '#/components/schemas/SmsTemplateSendToEachValidationResult'
      required:
        - desc
        - result
      additionalProperties: false
    AuthError:
      type: object
      properties:
        error:
          type: string
        error_description:
          type: string
    SmsTemplateSendToManyValidationResult:
      type: object
      properties:
        errors:
          type: array
          items:
            type: string
          description: Validation error messages, e.g. "Missing required parameter 'code'"
      required:
        - errors
      additionalProperties: false
    SmsTemplateSendToEachValidationResult:
      type: object
      description: >-
        Validation errors keyed by recipient phone number. Only recipients with
        failures are included.
      additionalProperties:
        type: array
        items:
          type: string
      not:
        required:
          - errors
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer

````