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 toglobals. Forwebhook, bothwebhook.notifyandwebhook.urlmerge independently withglobals.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
tofield contains N phone numbers, the item expands into N independent outbound messages in themessagesresponse array, each assigned its own uniquemessageIdwhile retaining the sameclientReference. - All-or-nothing validation: All items in
messagesare validated before any message is queued. If any item fails validation, the entire batch is rejected with422 Unprocessable Entity, and the error description is prefixed with[<clientReference>](or[messages[<index>]]ifclientReferencewas 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-01inherits the globalfrom,scheduledAt,expiresAt, andwebhooksettings.req-02overridesfrom, sets an earlierexpiresAt, 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"
}
}