Send multiple messages

Submits multiple outbound SMS messages in a single batch request, supporting shared global defaults (globals), per-message overrides, and single or multiple recipients per message item.

POST /api/v2/messages:batchSend

Table of contents

Endpoint summary

Property Value
HTTP method POST
Endpoint path /api/v2/messages:batchSend
Authentication Authorization: Bearer <api_key> or Authorization: Basic <base64(username:password)>
Content-Type application/json
Success status code 202 Accepted

Note: Each recipient in the batch generates a separate queued message in the response. When a message item specifies multiple phone numbers in to, the response includes an individual entry for each recipient with its own messageId while sharing the item's clientReference.

Request

Request headers

Header Required Description
Authorization Yes Credentials identifying the user account context (Bearer <api_key> or Basic <credentials>).
Content-Type Yes Must be application/json.

Request body

The request body must be a JSON object with strictly case-sensitive camelCase property names.

Root parameters (BatchSendMessagesRequest)

Field Type Required Description
globals object (BatchGlobals) Optional Shared default settings inherited across all items in messages unless explicitly overridden on an individual item.
messages object[] (SendMessageRequest[]) Yes Non-empty array of message items to dispatch.

globals object (BatchGlobals)

Defines default dispatch attributes applied to every item in messages when the corresponding field is omitted on the item.

Field Type Required Default Description
from string Optional null Default sender MSISDN (E.164 format) or alphanumeric sender ID. If omitted in both the item and globals, sender resolves to null.
type string Optional "text" Default message payload type: "text" or "binary".
content string Optional — Default text content for "text" messages.
hexContent string Optional — Default even-length hexadecimal-encoded payload for "binary" messages.
userDataHeader string Optional null Default even-length hexadecimal-encoded User Data Header (UDH) for "binary" messages.
dataCoding integer Optional 4 Default data coding scheme (DCS) integer (0–255) for "binary" messages.
scheduledAt string (ISO 8601) Optional createdAt Default deferred dispatch timestamp with timezone offset.
expiresAt string (ISO 8601) Optional scheduledAt + 7 days Default expiration deadline timestamp with timezone offset.
webhook object (WebhookConfig) Optional null Default webhook configuration for status notifications.

messages[] item object (SendMessageRequest)

Each element in the messages array defines one message specification (which may target one or multiple recipients). Any optional attribute omitted on the item is inherited from globals.

Field Type Required Default Description
to string | string[] Yes — Single destination phone number (e.g., "+36201002001") or non-empty array of phone numbers (e.g., [ "+36201003001", "+36201003002" ]) in E.164 format.
clientReference string Optional null Client-defined correlation identifier echoed back on every expanded message generated from this item. Also used to identify the item in validation error messages.
from string Optional globals.from Sender MSISDN (E.164) or alphanumeric sender ID. Overrides globals.from.
type string Optional globals.type | "text" Message payload type ("text" or "binary"). Overrides globals.type.
content string Conditional globals.content Text content of the SMS. Required (either on the item or via globals.content) when effective type is "text". Must not be resolved when effective type is "binary".
hexContent string Conditional globals.hexContent Even-length hexadecimal-encoded binary payload (0-9, A-F). Required (either on the item or via globals.hexContent) when effective type is "binary". Must not be resolved when effective type is "text".
userDataHeader string Optional globals.userDataHeader Even-length hexadecimal-encoded User Data Header (UDH). Only permitted when effective type is "binary".
dataCoding integer Optional globals.dataCoding | 4 Data coding scheme (DCS) integer between 0 and 255. Only permitted when effective type is "binary".
scheduledAt string (ISO 8601) Optional globals.scheduledAt | createdAt Deferred dispatch timestamp. When scheduled in the future (scheduledAt > createdAt), expanded messages are placed in the "postponed" folder.
expiresAt string (ISO 8601) Optional globals.expiresAt | scheduledAt + 7 days Expiration deadline timestamp. Must be strictly later than the effective scheduledAt.
webhook object (WebhookConfig) Optional globals.webhook Per-message webhook notification configuration. Overrides globals.webhook (individual sub-properties url and notify fall back to globals.webhook if omitted).

webhook object (WebhookConfig)

Field Type Required Default Description
url string Conditional globals.webhook.url Target absolute http:// or https:// endpoint URL to notify on status updates. Required when effective notify is true and no URL is inherited from globals.webhook.url.
notify boolean Optional globals.webhook.notify | true Whether status notifications are active (true or false). Set to false on an item to disable a global webhook for that item without needing to repeat url.

Inheritance, expansion & validation rules

  • Global inheritance: For each item in messages, effective fields are resolved by taking the item's property if specified, or falling back to globals. For webhook, both webhook.notify and webhook.url merge independently with globals.webhook (allowing an item to specify {"notify": false} to opt out of a global webhook, or {"url": "..."} to override just the target URL).
  • Recipient expansion: If an item's to field contains N phone numbers, the item expands into N independent outbound messages in the messages response array, each assigned its own unique messageId while retaining the same clientReference.
  • All-or-nothing validation: All items in messages are validated before any message is queued. If any item fails validation, the entire batch is rejected with 422 Unprocessable Entity, and the error description is prefixed with [<clientReference>] (or [messages[<index>]] if clientReference was not provided).

Response

202 Accepted

Returns a BatchSendMessagesResponse object containing the list of queued message representations for each expanded recipient.

Root object (BatchSendMessagesResponse)

Field Type Description
messages object[] (MessageResponse[]) Array of queued message objects in the order of expansion.

messages[] item object (MessageResponse)

Properties with null values (such as an omitted from, clientReference, or unused text/binary fields) are omitted from the serialized JSON output.

Field Type Description
messageId string (UUID) Server-assigned unique identifier for this recipient's message.
clientReference string Client correlation identifier echoed from the source batch item. Omitted if not provided on the item.
folder string Initial message folder: "outbox" for immediate dispatch, or "postponed" when scheduledAt > createdAt.
from string Effective sender phone number or alphanumeric ID. Omitted if no sender was specified in the item or globals.
to string Single destination recipient phone number for this expanded message.
type string Effective message payload type ("text" or "binary").
content string Text payload content. Present only when type is "text".
hexContent string Uppercase hexadecimal-encoded binary payload. Present only when type is "binary".
userDataHeader string Uppercase hexadecimal-encoded User Data Header (UDH). Present only when provided on a "binary" message.
dataCoding integer Data coding scheme (DCS). Present only when type is "binary".
status string Initial lifecycle delivery status. Always "queued" upon acceptance.
statusDescription string Human-readable status label ("Accepted for delivery").
createdAt string (ISO 8601) Server-assigned timestamp when the batch was accepted.
scheduledAt string (ISO 8601) Effective dispatch timestamp.
expiresAt string (ISO 8601) Effective expiration deadline timestamp.
updatedAt string (ISO 8601) Timestamp of the latest status update.

Error responses

When a batch request fails authentication, JSON parsing, or validation on any message item, the entire batch is rejected and the API returns a structured ApiErrorResponse object.

Common error status codes:

Status code Condition Description
401 Unauthorized Missing or invalid credentials Authentication credentials were not provided or could not be resolved to an active user.
422 Unprocessable Entity Malformed JSON or validation error Request body is invalid, messages is missing or empty, or an individual item violates field validation rules (e.g., missing to, missing effective content, or invalid schedule/expiration window).

Error schema (ApiErrorResponse):

Field Type Description
error.code integer HTTP status code (e.g., 401, 422).
error.description string Explanation of the specific error condition (prefixed with [<clientReference>] or [messages[<index>]] for item-level errors).
error.action string Recommended action to resolve the error.
error.timestamp string (ISO 8601) Timestamp when the error occurred.

Examples

1. Send a batch of SMS messages (single and multiple recipients)

Submits two message items: req-01 targets a single phone number, while req-02 targets an array of two phone numbers (expanding into three total queued messages).

Request headers:

POST /api/v2/messages:batchSend HTTP/1.1
Host: localhost:9509
Authorization: Bearer <api_key>
Content-Type: application/json

Request body:

{
  "messages": [
    {
      "clientReference": "req-01",
      "from": "+36201002000",
      "to": "+36201002001",
      "content": "Message 1 goes to 1 number"
    },
    {
      "clientReference": "req-02",
      "from": "+36201003000",
      "to": [
        "+36201003001",
        "+36201003002"
      ],
      "content": "Message 2 goes to 2 numbers"
    }
  ]
}

Response (202 Accepted):

{
  "messages": [
    {
      "clientReference": "req-01",
      "messageId": "26385eed-6a6c-4deb-b549-dc055211a71d",
      "folder": "outbox",
      "from": "+36201002000",
      "to": "+36201002001",
      "type": "text",
      "content": "Message 1 goes to 1 number",
      "status": "queued",
      "statusDescription": "Accepted for delivery",
      "updatedAt": "2026-10-21T10:21:00+02:00",
      "createdAt": "2026-10-21T10:21:00+02:00",
      "scheduledAt": "2026-10-21T10:21:00+02:00",
      "expiresAt": "2026-10-28T10:21:00+02:00"
    },
    {
      "clientReference": "req-02",
      "messageId": "8f3b2a1c-9d4e-4f5a-b6c7-1a2b3c4d5e6f",
      "folder": "outbox",
      "from": "+36201003000",
      "to": "+36201003001",
      "type": "text",
      "content": "Message 2 goes to 2 numbers",
      "status": "queued",
      "statusDescription": "Accepted for delivery",
      "updatedAt": "2026-10-21T10:21:00+02:00",
      "createdAt": "2026-10-21T10:21:00+02:00",
      "scheduledAt": "2026-10-21T10:21:00+02:00",
      "expiresAt": "2026-10-28T10:21:00+02:00"
    },
    {
      "clientReference": "req-02",
      "messageId": "9e4c3b2d-0e5f-4a6b-c7d8-2b3c4d5e6f7a",
      "folder": "outbox",
      "from": "+36201003000",
      "to": "+36201003002",
      "type": "text",
      "content": "Message 2 goes to 2 numbers",
      "status": "queued",
      "statusDescription": "Accepted for delivery",
      "updatedAt": "2026-10-21T10:21:00+02:00",
      "createdAt": "2026-10-21T10:21:00+02:00",
      "scheduledAt": "2026-10-21T10:21:00+02:00",
      "expiresAt": "2026-10-28T10:21:00+02:00"
    }
  ]
}

2. Send a batch with global webhook and per-message opt-out

Configures a global status webhook URL for the batch in globals.webhook, while req-02 selectively disables webhook notifications ("notify": false).

Request headers:

POST /api/v2/messages:batchSend HTTP/1.1
Host: localhost:9509
Authorization: Bearer <api_key>
Content-Type: application/json

Request body:

{
  "globals": {
    "webhook": {
      "url": "https://client.example.com/api/sms/webhook",
      "notify": true
    }
  },
  "messages": [
    {
      "clientReference": "req-01",
      "from": "+36201002000",
      "to": "+36201002001",
      "content": "Message 1 goes to 1 number"
    },
    {
      "clientReference": "req-02",
      "from": "+36201003000",
      "to": [
        "+36201003001",
        "+36201003002"
      ],
      "content": "Message 2 goes to 2 numbers",
      "webhook": {
        "notify": false
      }
    }
  ]
}

Response (202 Accepted):

{
  "messages": [
    {
      "clientReference": "req-01",
      "messageId": "26385eed-6a6c-4deb-b549-dc055211a71d",
      "folder": "outbox",
      "from": "+36201002000",
      "to": "+36201002001",
      "type": "text",
      "content": "Message 1 goes to 1 number",
      "status": "queued",
      "statusDescription": "Accepted for delivery",
      "updatedAt": "2026-10-21T10:21:00+02:00",
      "createdAt": "2026-10-21T10:21:00+02:00",
      "scheduledAt": "2026-10-21T10:21:00+02:00",
      "expiresAt": "2026-10-28T10:21:00+02:00"
    },
    {
      "clientReference": "req-02",
      "messageId": "91a27b9c-53e3-4d43-9831-29e1ebba5122",
      "folder": "outbox",
      "from": "+36201003000",
      "to": "+36201003001",
      "type": "text",
      "content": "Message 2 goes to 2 numbers",
      "status": "queued",
      "statusDescription": "Accepted for delivery",
      "updatedAt": "2026-10-21T10:21:00+02:00",
      "createdAt": "2026-10-21T10:21:00+02:00",
      "scheduledAt": "2026-10-21T10:21:00+02:00",
      "expiresAt": "2026-10-28T10:21:00+02:00"
    },
    {
      "clientReference": "req-02",
      "messageId": "d34e6f8a-72b1-4c55-9012-34f5a6b7c8d9",
      "folder": "outbox",
      "from": "+36201003000",
      "to": "+36201003002",
      "type": "text",
      "content": "Message 2 goes to 2 numbers",
      "status": "queued",
      "statusDescription": "Accepted for delivery",
      "updatedAt": "2026-10-21T10:21:00+02:00",
      "createdAt": "2026-10-21T10:21:00+02:00",
      "scheduledAt": "2026-10-21T10:21:00+02:00",
      "expiresAt": "2026-10-28T10:21:00+02:00"
    }
  ]
}

3. Batch messaging with global defaults and per-message overrides

Defines common from, scheduledAt, expiresAt, and webhook defaults inside globals:

  • req-01 inherits the global from, scheduledAt, expiresAt, and webhook settings.
  • req-02 overrides from, sets an earlier expiresAt, dispatches to two recipients, and disables webhook notifications.

Request headers:

POST /api/v2/messages:batchSend HTTP/1.1
Host: localhost:9509
Authorization: Bearer <api_key>
Content-Type: application/json

Request body:

{
  "globals": {
    "from": "+36201000000",
    "scheduledAt": "2026-10-21T18:00:00+02:00",
    "expiresAt": "2026-10-22T06:00:00+02:00",
    "webhook": {
      "url": "https://client.example.com/api/sms/webhook",
      "notify": true
    }
  },
  "messages": [
    {
      "clientReference": "req-01",
      "to": "+36201002001",
      "content": "Message 1: inherits global schedule, expiration, sender, and webhook"
    },
    {
      "clientReference": "req-02",
      "from": "+36201003000",
      "to": [
        "+36201003001",
        "+36201003002"
      ],
      "content": "Message 2: overrides sender, expiration, and disables webhook notification",
      "expiresAt": "2026-10-21T22:00:00+02:00",
      "webhook": {
        "notify": false
      }
    }
  ]
}

Response (202 Accepted):

{
  "messages": [
    {
      "clientReference": "req-01",
      "messageId": "26385eed-6a6c-4deb-b549-dc055211a71d",
      "folder": "postponed",
      "from": "+36201000000",
      "to": "+36201002001",
      "type": "text",
      "content": "Message 1: inherits global schedule, expiration, sender, and webhook",
      "status": "queued",
      "statusDescription": "Accepted for delivery",
      "updatedAt": "2026-10-21T10:20:00+02:00",
      "createdAt": "2026-10-21T10:20:00+02:00",
      "scheduledAt": "2026-10-21T18:00:00+02:00",
      "expiresAt": "2026-10-22T06:00:00+02:00"
    },
    {
      "clientReference": "req-02",
      "messageId": "8f3b2a1c-9d4e-4f5a-b6c7-1a2b3c4d5e6f",
      "folder": "postponed",
      "from": "+36201003000",
      "to": "+36201003001",
      "type": "text",
      "content": "Message 2: overrides sender, expiration, and disables webhook notification",
      "status": "queued",
      "statusDescription": "Accepted for delivery",
      "updatedAt": "2026-10-21T10:20:00+02:00",
      "createdAt": "2026-10-21T10:20:00+02:00",
      "scheduledAt": "2026-10-21T18:00:00+02:00",
      "expiresAt": "2026-10-21T22:00:00+02:00"
    },
    {
      "clientReference": "req-02",
      "messageId": "9e4c3b2d-0e5f-4a6b-c7d8-2b3c4d5e6f7a",
      "folder": "postponed",
      "from": "+36201003000",
      "to": "+36201003002",
      "type": "text",
      "content": "Message 2: overrides sender, expiration, and disables webhook notification",
      "status": "queued",
      "statusDescription": "Accepted for delivery",
      "updatedAt": "2026-10-21T10:20:00+02:00",
      "createdAt": "2026-10-21T10:20:00+02:00",
      "scheduledAt": "2026-10-21T18:00:00+02:00",
      "expiresAt": "2026-10-21T22:00:00+02:00"
    }
  ]
}

4. Error: Missing or empty messages array (422 Unprocessable Entity)

Returned when the request payload is missing the messages property or provides an empty array.

Response (422 Unprocessable Entity):

{
  "error": {
    "code": 422,
    "description": "The 'messages' array is required and must contain at least one item.",
    "action": "Provide an array containing 1 to 100 message items in 'messages'.",
    "timestamp": "2026-10-21T10:21:00+02:00"
  }
}

5. Error: Item-level validation failure (422 Unprocessable Entity)

Returned when an individual item in the batch fails validation (e.g., missing to destination recipient). The error description specifies the failing item via its clientReference.

Response (422 Unprocessable Entity):

{
  "error": {
    "code": 422,
    "description": "[req-02] Each batch message item must specify at least one recipient in 'to'.",
    "action": "Provide a recipient phone number or array of phone numbers in 'to'.",
    "timestamp": "2026-10-21T10:21:00+02:00"
  }
}

More information