Skip to content
New to this? Read the Send SMS guide.

Send an SMS

POST
/v2/sms
curl --request POST \
--url https://api.connect.ms/v2/sms \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '{ "sender": "example", "recipient": "example", "content": "example", "template": { "name": "example", "data": { "additionalProperty": "example" } }, "kind": "transactional", "clientReference": "example", "clientTag": "example", "scheduledAt": "2026-04-15T12:00:00Z", "validitySeconds": 1, "unicode": "allow", "shortenLinks": true, "trackClicks": true, "bypassSuppressions": true, "link": { "include": true, "mode": "unsubscribe", "preText": "example" } }'

Queues one message for sending, immediately or at scheduledAt, with content given directly or rendered from a stored template. The response is the message as queued; its progress is reported by sms.* events and webhooks.

Connect-Version
string

The API version to use, for example 2026-10-01. Defaults to the version set on your API key.

Idempotency-Key
string

A unique value of up to 255 characters, so a retried request is not acted on twice. Required for keys in Strict API Mode.

A message to send. Provide exactly one of content and template.name.

Media typeapplication/json

A message to send. Provide exactly one of content and template.name.

object
sender
required

Sender for the SMS: an approved sender name, a verified UK mobile number in 07 format, or one of your inbound numbers in E.164 format.

string
>= 1 characters
recipient
required

Recipient Number (E.164 format) for the SMS.

string
>= 1 characters
content

The message text, up to 5,000 characters. Cannot be combined with template.name; template.data renders merge fields in it.

string
nullable 0 <= 5000 characters
template
One of:

A stored template to render, or merge data for rendering the content field.

object
name

The name of a stored template, up to 64 characters; its merge fields are rendered with data. Cannot be combined with content.

string
nullable 0 <= 64 characters
data
One of:

A JSON object.

object
key
additional properties
kind
One of:

The kind of message: transactional (service messages, the default), marketing (promotional, subject to opt-outs and the unsubscribe link) or authentication (one-time codes).

string
Allowed values: transactional marketing authentication
clientReference

Your own reference for this individual message, up to 64 characters, returned on the message and its events.

string
nullable 0 <= 64 characters
clientTag

A grouping tag for usage reporting, up to 64 characters. Stored in lower case with anything other than letters and digits replaced by hyphens.

string
nullable 0 <= 64 characters
scheduledAt

When (UTC, ISO 8601) to send the message: at least 5 minutes and at most 12 months ahead. If not specified, the message is sent immediately.

string format: date-time
nullable
validitySeconds

How long the message stays eligible to send, between 60 and 172800 seconds. If omitted or 0 there is no window: a message the workspace cannot pay for fails immediately instead of being held until credit returns.

integer format: int32
nullable >= 60 <= 172800
unicode
One of:

How characters outside the GSM alphabet are handled: allow (send as written, using UCS-2 when needed), deny (reject the request if the content you send has any; a stored template is not checked), smart (replace curly quotes, dashes, ellipses and unusual spaces with GSM equivalents and remove emoji, leaving letters untouched) or strip (as smart, then fold accented letters that GSM lacks to their base letter and remove anything else outside the GSM alphabet, so the message always sends as GSM-7).

string
Allowed values: allow deny strip smart
shortenLinks

Whether to shorten links in the content. Omit to follow the workspace setting.

boolean
nullable
trackClicks

Whether to give each shortened link a tracking code for this message, so its clicks can be read per message. Every link is then shortened. Omit to follow the workspace setting; cannot be true when shortenLinks is false.

boolean
nullable
bypassSuppressions

Send even if the recipient is on the suppression list. Defaults to false; a connected app cannot set it to true.

boolean
nullable
link
One of:

Overrides the workspace’s message link settings for this send.

object
include

Whether to append a link. Omit to follow the workspace setting; the link is never added to authentication messages, and a connected app cannot set this to false.

boolean
nullable
mode
One of:

What the appended link offers the recipient: unsubscribe (opt out of marketing), reply (send a reply from the web) or both.

string
Allowed values: unsubscribe reply both
preText

Text placed before the link, up to 64 characters. Omit to follow the workspace setting.

string
nullable 0 <= 64 characters

The message was queued. The Location header holds its URL.

Media typeapplication/json

An SMS message, outbound or inbound. The same shape is returned by every SMS endpoint and carried by sms.* events.

object
id
required

The unique id of the message.

string
direction
required
One of:

Which way the message travelled: outbound (sent by you) or inbound (received on one of your numbers, or as a reply through a message link).

string
Allowed values: outbound inbound
kind
One of:

The kind of message: transactional (service messages, the default), marketing (promotional, subject to opt-outs and the unsubscribe link) or authentication (one-time codes).

string
Allowed values: transactional marketing authentication
sender

The sender: your sender name or number for outbound, the sending number (E.164 format) for inbound. Null for an inbound message when the caller may not see recipients.

string
nullable
recipient

The recipient number (E.164 format) for outbound, or your receiving number (or sender name, for a web reply) for inbound. Null for an outbound message when the caller may not see recipients.

string
nullable
country

The ISO 3166-1 alpha-2 country of the other party’s number, or null when it cannot be determined.

string
nullable
content

The message text as sent or received. Null when the caller may not see content.

string
nullable
channel
One of:

How an inbound message arrived: sms (a text to one of your numbers) or web (a reply through a message link).

string
Allowed values: sms web
status
required
One of:

The message status: queued (accepted, scheduled, paced or held and not yet handed to the network), sent (handed to the network, awaiting a delivery receipt), delivered, failed (see reason), cancelled, or received for an inbound message.

string
Allowed values: queued sent delivered failed cancelled received
reason
One of:

Why a message failed.

object
category
required
One of:

Why a message failed: invalid (bad number, sender or parameter), blocked (a workspace or platform rule), rejected (no route or the destination country is not enabled), unreachable (the handset could not be reached in time), undeliverable (the network gave no usable reason) or expired (the validity window passed before it could be sent).

string
Allowed values: invalid blocked rejected unreachable undeliverable expired
code
required

The specific error code in snake_case, e.g. invalid_destination_address or payment_required.

string
description
required

A short explanation of the failure.

string
retryable
required

True when the failure was not caused by the message or the recipient, so sending it again later may succeed.

boolean
hold
One of:

Why a message is waiting rather than sending.

object
reason
required
One of:

Why a message is being held: payment_required (the workspace is out of credit; the message sends once credit is restored or fails when its validity window passes).

string
Allowed values: payment_required
since
required

When (UTC) the hold began.

string format: date-time
until

When (UTC) the message fails if the hold is not lifted, or null when it has no validity window. Always null on a batch.

string format: date-time
nullable
parts
required

The number of SMS parts the content is split into.

integer format: int32
encoding
required
One of:

How the content is encoded on the network: gsm7 (the standard alphabet, 160 characters in a single-part message) or ucs2 (70 characters in a single-part message, used when the content has characters outside the GSM alphabet).

string
Allowed values: gsm7 ucs2
cost
One of:

An amount in each currency it can be priced in, as decimal strings with four decimal places. A currency with no price is null.

object
gbp

The amount in pounds sterling, e.g. “0.0350”.

string
nullable
eur

The amount in euros, e.g. “0.0410”.

string
nullable
clientReference

Your own reference for this message, as supplied when it was sent.

string
nullable
clientTag

The grouping tag for usage reporting, as stored when the message was sent (lower case, letters, digits and hyphens).

string
nullable
batchId

The id of the batch the message belongs to, or null when it was sent on its own.

string
nullable
validitySeconds

How long the message stays eligible to send, in seconds. Null when no validity window was requested.

integer format: int32
nullable
expiresAt

When (UTC) the validity window ends and the message fails if not yet sent. Null when there is no window, or while a paced message is waiting for its turn.

string format: date-time
nullable
createdAt
required

When (UTC) the message was created.

string format: date-time
scheduledAt

When (UTC) the message was asked to send, or null when no send time was given.

string format: date-time
nullable
sentAt

When (UTC) the message was handed to the network, or null if not yet sent.

string format: date-time
nullable
deliveredAt

When (UTC) the network confirmed delivery, or null if not delivered.

string format: date-time
nullable
receivedAt

When (UTC) an inbound message was received. Null for outbound messages.

string format: date-time
nullable
updatedAt
required

When (UTC) the message last changed.

string format: date-time

Example

{
"direction": "outbound",
"kind": "transactional",
"channel": "sms",
"status": "queued",
"reason": {
"category": "invalid"
},
"hold": {
"reason": "payment_required"
},
"encoding": "gsm7"
}

The request is not valid. The detail field says why, and errors lists any problems by field name.

Media typeapplication/problem+json

Why a request failed, in the RFC 9457 problem details format.

object
type
required

A URI identifying the kind of problem, ending in a code such as validation_failed, not_found, sending_blocked or rate_limited.

string
title
required

A short, fixed summary of the kind of problem.

string
status
required

The HTTP status code of the response.

integer format: int32
detail

What went wrong with this particular request, when there is more to say than the title.

string
nullable
errors

For validation failures, the problems found, keyed by field name (nested fields as template.name, list items as messages[3]).

object
key
additional properties
Array<string>
requestId
required

The id recorded for this error, matching the Request-Id header when one is sent. Quote it when contacting support.

string

Example generated

{
"type": "example",
"title": "example",
"status": 1,
"detail": "example",
"errors": {
"additionalProperty": [
"example"
]
},
"requestId": "example"
}

The API key or bearer token is missing or not valid, or the request signature could not be verified.

Media typeapplication/problem+json

Why a request failed, in the RFC 9457 problem details format.

object
type
required

A URI identifying the kind of problem, ending in a code such as validation_failed, not_found, sending_blocked or rate_limited.

string
title
required

A short, fixed summary of the kind of problem.

string
status
required

The HTTP status code of the response.

integer format: int32
detail

What went wrong with this particular request, when there is more to say than the title.

string
nullable
errors

For validation failures, the problems found, keyed by field name (nested fields as template.name, list items as messages[3]).

object
key
additional properties
Array<string>
requestId
required

The id recorded for this error, matching the Request-Id header when one is sent. Quote it when contacting support.

string

Example generated

{
"type": "example",
"title": "example",
"status": 1,
"detail": "example",
"errors": {
"additionalProperty": [
"example"
]
},
"requestId": "example"
}

The caller is not allowed to do this, or sending is blocked for the workspace (sending_blocked).

Media typeapplication/problem+json

Why a request failed, in the RFC 9457 problem details format.

object
type
required

A URI identifying the kind of problem, ending in a code such as validation_failed, not_found, sending_blocked or rate_limited.

string
title
required

A short, fixed summary of the kind of problem.

string
status
required

The HTTP status code of the response.

integer format: int32
detail

What went wrong with this particular request, when there is more to say than the title.

string
nullable
errors

For validation failures, the problems found, keyed by field name (nested fields as template.name, list items as messages[3]).

object
key
additional properties
Array<string>
requestId
required

The id recorded for this error, matching the Request-Id header when one is sent. Quote it when contacting support.

string

Example generated

{
"type": "example",
"title": "example",
"status": 1,
"detail": "example",
"errors": {
"additionalProperty": [
"example"
]
},
"requestId": "example"
}

A request with this Idempotency-Key is still being processed. Retry after the Retry-After header.

Media typeapplication/problem+json

Why a request failed, in the RFC 9457 problem details format.

object
type
required

A URI identifying the kind of problem, ending in a code such as validation_failed, not_found, sending_blocked or rate_limited.

string
title
required

A short, fixed summary of the kind of problem.

string
status
required

The HTTP status code of the response.

integer format: int32
detail

What went wrong with this particular request, when there is more to say than the title.

string
nullable
errors

For validation failures, the problems found, keyed by field name (nested fields as template.name, list items as messages[3]).

object
key
additional properties
Array<string>
requestId
required

The id recorded for this error, matching the Request-Id header when one is sent. Quote it when contacting support.

string

Example generated

{
"type": "example",
"title": "example",
"status": 1,
"detail": "example",
"errors": {
"additionalProperty": [
"example"
]
},
"requestId": "example"
}

This Idempotency-Key was already used for a different request. Use a new key.

Media typeapplication/problem+json

Why a request failed, in the RFC 9457 problem details format.

object
type
required

A URI identifying the kind of problem, ending in a code such as validation_failed, not_found, sending_blocked or rate_limited.

string
title
required

A short, fixed summary of the kind of problem.

string
status
required

The HTTP status code of the response.

integer format: int32
detail

What went wrong with this particular request, when there is more to say than the title.

string
nullable
errors

For validation failures, the problems found, keyed by field name (nested fields as template.name, list items as messages[3]).

object
key
additional properties
Array<string>
requestId
required

The id recorded for this error, matching the Request-Id header when one is sent. Quote it when contacting support.

string

Example generated

{
"type": "example",
"title": "example",
"status": 1,
"detail": "example",
"errors": {
"additionalProperty": [
"example"
]
},
"requestId": "example"
}

This API key requires an Idempotency-Key header on every POST and PATCH.

Media typeapplication/problem+json

Why a request failed, in the RFC 9457 problem details format.

object
type
required

A URI identifying the kind of problem, ending in a code such as validation_failed, not_found, sending_blocked or rate_limited.

string
title
required

A short, fixed summary of the kind of problem.

string
status
required

The HTTP status code of the response.

integer format: int32
detail

What went wrong with this particular request, when there is more to say than the title.

string
nullable
errors

For validation failures, the problems found, keyed by field name (nested fields as template.name, list items as messages[3]).

object
key
additional properties
Array<string>
requestId
required

The id recorded for this error, matching the Request-Id header when one is sent. Quote it when contacting support.

string

Example generated

{
"type": "example",
"title": "example",
"status": 1,
"detail": "example",
"errors": {
"additionalProperty": [
"example"
]
},
"requestId": "example"
}

The workspace rate limit or the API key’s send limit was reached. Retry after the Retry-After header.

Media typeapplication/problem+json

Why a request failed, in the RFC 9457 problem details format.

object
type
required

A URI identifying the kind of problem, ending in a code such as validation_failed, not_found, sending_blocked or rate_limited.

string
title
required

A short, fixed summary of the kind of problem.

string
status
required

The HTTP status code of the response.

integer format: int32
detail

What went wrong with this particular request, when there is more to say than the title.

string
nullable
errors

For validation failures, the problems found, keyed by field name (nested fields as template.name, list items as messages[3]).

object
key
additional properties
Array<string>
requestId
required

The id recorded for this error, matching the Request-Id header when one is sent. Quote it when contacting support.

string

Example generated

{
"type": "example",
"title": "example",
"status": 1,
"detail": "example",
"errors": {
"additionalProperty": [
"example"
]
},
"requestId": "example"
}

The message could not be queued right now. Retry after the Retry-After header.

Media typeapplication/problem+json

Why a request failed, in the RFC 9457 problem details format.

object
type
required

A URI identifying the kind of problem, ending in a code such as validation_failed, not_found, sending_blocked or rate_limited.

string
title
required

A short, fixed summary of the kind of problem.

string
status
required

The HTTP status code of the response.

integer format: int32
detail

What went wrong with this particular request, when there is more to say than the title.

string
nullable
errors

For validation failures, the problems found, keyed by field name (nested fields as template.name, list items as messages[3]).

object
key
additional properties
Array<string>
requestId
required

The id recorded for this error, matching the Request-Id header when one is sent. Quote it when contacting support.

string

Example generated

{
"type": "example",
"title": "example",
"status": 1,
"detail": "example",
"errors": {
"additionalProperty": [
"example"
]
},
"requestId": "example"
}