Send a message
Submits a single outbound SMS message (standard text or hexadecimal binary) for immediate or scheduled delivery.
POST /api/v2/messages
Table of contents
Endpoint summary
| Property | Value |
| HTTP method | POST |
| Endpoint path | /api/v2/messages |
| Authentication | Authorization: Bearer <api_key> or Authorization: Basic <base64(username:password)> |
| Content-Type | application/json |
| Success status code | 201 Created |
Note: A 201 Created response confirms that the SMS message has been validated, created, and queued for dispatch. It returns the Location header containing the direct resource URI (/api/v2/messages/{messageId}). It does not guarantee final handset delivery to the recipient.
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 (SendMessageRequest)
The request body must be a JSON object with strictly case-sensitive camelCase property names.
| Field | Type | Required | Default | Description |
to |
string | Yes | — | Destination recipient phone number in E.164 format (e.g., "+36201002001"). Must be a single non-empty phone number. (To send to multiple recipients at once, use POST /api/v2/messages:batchSend.) |
from |
string | Optional | null |
Sender MSISDN (E.164 format) or alphanumeric sender ID. If omitted or whitespace, the sender resolves to null and is omitted from the response. |
type |
string | Optional | "text" |
Message payload type: "text" or "binary". |
content |
string | Conditional | — | Text content of the SMS message. Required when type is "text". Must not be provided when type is "binary". |
hexContent |
string | Conditional | — | Even-length hexadecimal-encoded binary payload (0-9, A-F). Required when type is "binary". Must not be provided when type is "text". |
userDataHeader |
string | Optional | null |
Even-length hexadecimal-encoded User Data Header (UDH). Only permitted when type is "binary". |
dataCoding |
integer | Optional | 4 |
Data coding scheme (DCS) integer between 0 and 255. Only permitted when type is "binary" (defaults to 4). |
scheduledAt |
string (ISO 8601) | Optional | createdAt |
Deferred dispatch timestamp with timezone offset (e.g., "2026-10-21T18:00:00+02:00"). When scheduled in the future (scheduledAt > createdAt), the message is placed into the "postponed" folder. |
expiresAt |
string (ISO 8601) | Optional | scheduledAt + 7 days |
Expiration deadline with timezone offset after which delivery is cancelled. Defaults to scheduledAt + 7 days (or createdAt + 7 days if unscheduled). Must be strictly later than scheduledAt. |
clientReference |
string | Optional | null |
Client-defined correlation identifier echoed back in the send response. |
webhook |
object (WebhookConfig) |
Optional | null |
Per-message webhook notification configuration for delivery status updates. |
webhook object (WebhookConfig)
| Field | Type | Required | Default | Description |
url |
string | Conditional | — | Target absolute http:// or https:// endpoint URL to notify on status updates. Required when webhook is provided and notify is true (or omitted). |
notify |
boolean | Optional | true |
Whether status notifications are enabled (true or false) for this message. |
Payload validation rules
- Text vs. Binary Mutual Exclusivity:
- When
typeis"text"(or omitted),contentis required and must be non-empty. Binary fields (hexContent,userDataHeader,dataCoding) must not be set. - When
typeis"binary",hexContentis required and must contain an even number of hexadecimal characters (0-9,A-F). Thecontentfield must not be set.
- When
- Schedule & Expiration:
expiresAtmust be strictly later thanscheduledAt(expiresAt > scheduledAt).
Responses
Response headers
| Header | Description |
Content-Type |
application/json |
Location |
Absolute path URI to the created message resource: /api/v2/messages/{messageId}. |
201 Created (SendMessageResponse)
Returns the queued message representation (SendMessageResponse). 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 of the message. |
clientReference |
string | Client correlation identifier echoed from the request. Omitted if not provided in the request. |
folder |
string | Initial message folder: "outbox" for immediate dispatch, or "postponed" when scheduledAt > createdAt. |
from |
string | Sender phone number or alphanumeric ID. Omitted if no sender was specified. |
to |
string | Destination recipient phone number. |
type |
string | 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 message was accepted. |
scheduledAt |
string (ISO 8601) | Effective dispatch timestamp (equals createdAt if not explicitly scheduled). |
expiresAt |
string (ISO 8601) | Effective expiration deadline timestamp. |
updatedAt |
string (ISO 8601) | Timestamp of the latest status update. |
Error responses (ApiErrorResponse)
When a request fails authentication, JSON parsing, or field validation, the API returns a structured ApiErrorResponse object.
| 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 empty, contains invalid JSON syntax, or violates field validation rules (e.g., missing to, missing content, multiple recipients in to, invalid webhook.url, or expiresAt <= scheduledAt). |
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. |
error.action |
string | Recommended action to resolve the error. |
error.timestamp |
string (ISO 8601) | Timestamp when the error occurred. |
Examples
1. Send a standard text SMS
Submits a text SMS with a sender and recipient phone number for immediate delivery.
Request headers:
POST /api/v2/messages HTTP/1.1 Host: localhost:9509 Authorization: Bearer <api_key> Content-Type: application/json
Request body:
{
"from": "+36201002000",
"to": "+36201002001",
"content": "Message 1 goes to 1 number"
}
Response (201 Created):
Location:/api/v2/messages/26385eed-6a6c-4deb-b549-dc055211a71dContent-Type:application/json
{
"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"
}
2. Send an SMS without sender (from omitted)
Submits an outbound SMS without specifying the from address. When from is omitted, it resolves to null and is excluded from the JSON response.
Request headers:
POST /api/v2/messages HTTP/1.1 Host: localhost:9509 Authorization: Bearer <api_key> Content-Type: application/json
Request body:
{
"to": "+36201002001",
"content": "Message dispatched without sender address"
}
Response (201 Created):
Location:/api/v2/messages/26385eed-6a6c-4deb-b549-dc055211a71dContent-Type:application/json
{
"messageId": "26385eed-6a6c-4deb-b549-dc055211a71d",
"folder": "outbox",
"to": "+36201002001",
"type": "text",
"content": "Message dispatched without sender address",
"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. Send an SMS with per-message webhook
Submits an outbound SMS with a custom per-message webhook URL for delivery status notifications (message.status.updated).
Request headers:
POST /api/v2/messages HTTP/1.1 Host: localhost:9509 Authorization: Bearer <api_key> Content-Type: application/json
Request body:
{
"from": "+36201002000",
"to": "+36201002001",
"content": "Message 1 goes to 1 number",
"webhook": {
"url": "https://client.example.com/api/sms/webhook",
"notify": true
}
}
Response (201 Created):
Location:/api/v2/messages/26385eed-6a6c-4deb-b549-dc055211a71dContent-Type:application/json
{
"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"
}
4. Send a binary SMS (binary)
Submits a binary SMS message with a hexadecimal-encoded payload, User Data Header (UDH), and data coding scheme (DCS).
Request headers:
POST /api/v2/messages HTTP/1.1 Host: localhost:9509 Authorization: Bearer <api_key> Content-Type: application/json
Request body:
{
"from": "+36201002000",
"to": "+36201002001",
"type": "binary",
"hexContent": "0605040B8423F0",
"userDataHeader": "050003340201",
"dataCoding": 4
}
Response (201 Created):
Location:/api/v2/messages/37492ffd-7b7d-4efc-c65a-ed166322b82eContent-Type:application/json
{
"messageId": "37492ffd-7b7d-4efc-c65a-ed166322b82e",
"folder": "outbox",
"from": "+36201002000",
"to": "+36201002001",
"type": "binary",
"hexContent": "0605040B8423F0",
"userDataHeader": "050003340201",
"dataCoding": 4,
"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"
}
5. Send a scheduled and expiring SMS
Submits an SMS configured for future dispatch (scheduledAt) and a custom expiration deadline (expiresAt).
Request headers:
POST /api/v2/messages HTTP/1.1 Host: localhost:9509 Authorization: Bearer <api_key> Content-Type: application/json
Request body:
{
"from": "+36201002000",
"to": "+36201002001",
"content": "Message 1 goes to 1 number",
"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
}
}
Response (201 Created):
Location:/api/v2/messages/8f3b2a1c-9d4e-4f5a-b6c7-1a2b3c4d5e6fContent-Type:application/json
{
"messageId": "8f3b2a1c-9d4e-4f5a-b6c7-1a2b3c4d5e6f",
"folder": "postponed",
"from": "+36201002000",
"to": "+36201002001",
"type": "text",
"content": "Message 1 goes to 1 number",
"status": "queued",
"statusDescription": "Accepted for delivery",
"createdAt": "2026-10-21T10:20:00+02:00",
"scheduledAt": "2026-10-21T18:00:00+02:00",
"expiresAt": "2026-10-22T06:00:00+02:00",
"updatedAt": "2026-10-21T10:20:00+02:00"
}
Note: When a message has deferred dispatch (scheduledAt > createdAt), it is assigned to the postponed folder while its delivery status remains queued awaiting dispatch.
6. Error: Missing required to field (422 Unprocessable Entity)
Returned when the required to recipient phone number is omitted from the request payload.
Response (422 Unprocessable Entity):
{
"error": {
"code": 422,
"description": "The 'to' field is required.",
"action": "Provide a valid recipient phone number in the 'to' field.",
"timestamp": "2026-10-21T10:21:00+02:00"
}
}
7. Error: Malformed JSON syntax (422 Unprocessable Entity)
Returned when the request body cannot be parsed as valid JSON.
Response (422 Unprocessable Entity):
{
"error": {
"code": 422,
"description": "Failed to parse JSON body. Syntax error at line 5, column 12 (unexpected token).",
"action": "Ensure the request body contains valid JSON syntax matching the expected request schema.",
"timestamp": "2026-10-21T13:53:00+02:00"
}
}