Import a batch of SMS messages from a file
const url = 'https://api.connect.ms/v2/sms/batches/import';const form = new FormData();form.append('file', 'file');form.append('scheduledAt', '2026-04-15T12:00:00Z');form.append('validitySeconds', '1');form.append('kind', 'transactional');form.append('clientTag', 'example');form.append('shortenLinks', 'true');form.append('trackClicks', 'true');form.append('fixEncoding', 'true');form.append('bypassSuppressions', 'true');form.append('skipMessagedWithinHours', '1');form.append('columnMap', 'example');form.append('pacingRatePerPeriod', '1');form.append('pacingPeriod', 'hour');form.append('linkInclude', 'true');form.append('linkMode', 'unsubscribe');form.append('linkPreText', 'example');
const options = {method: 'POST', headers: {Authorization: 'Bearer <token>'}};
options.body = form;
try { const response = await fetch(url, options); const data = await response.json(); console.log(data);} catch (error) { console.error(error);}curl --request POST \ --url https://api.connect.ms/v2/sms/batches/import \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: multipart/form-data' \ --form file=@file \ --form scheduledAt=2026-04-15T12:00:00Z \ --form validitySeconds=1 \ --form kind=transactional \ --form clientTag=example \ --form shortenLinks=true \ --form trackClicks=true \ --form fixEncoding=true \ --form bypassSuppressions=true \ --form skipMessagedWithinHours=1 \ --form columnMap=example \ --form pacingRatePerPeriod=1 \ --form pacingPeriod=hour \ --form linkInclude=true \ --form linkMode=unsubscribe \ --form linkPreText=exampleUploads a CSV or Excel file with one message per row and queues it as a batch, immediately, at scheduledAt or paced over time. Send as multipart/form-data with the file and the settings as form fields.
Authorizations
Section titled “Authorizations”Parameters
Section titled “Parameters”Header Parameters
Section titled “Header Parameters”The API version to use, for example 2026-10-01. Defaults to the version set on your API key.
A unique value of up to 255 characters, so a retried request is not acted on twice. Required for keys in Strict API Mode.
Request Bodyrequired
Section titled “Request Bodyrequired”A multipart form: the file plus the batch settings as plain form fields.
A multipart form: the file plus the batch settings as plain form fields.
object
A CSV or Excel file with one message per row. By default the columns are sender, recipient and content, plus an optional unicode; use columnMap to name different headers. A row with an invalid sender or recipient rejects the whole import.
When (UTC, ISO 8601) to send the batch: at least 5 minutes and at most 12 months ahead. If not specified, the batch is sent immediately.
How long each message stays eligible to send, between 60 and 172800 seconds. If omitted or 0 there is no window.
The kind of message: transactional (service messages, the default), marketing (promotional, subject to opt-outs and the unsubscribe link) or authentication (one-time codes).
A grouping tag applied to every message in the batch for usage reporting, up to 64 characters. Stored in lower case with anything other than letters and digits replaced by hyphens.
Whether to shorten links in the content. Omit to follow the workspace setting.
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.
Replace curly quotes, dashes, ellipses and unusual spaces with their GSM equivalents; letters and emoji are left as they are. Defaults to false.
Send even to recipients on the suppression list. Defaults to false.
Skips recipients messaged within this many hours. One of 6, 12, 24, 48, 72 or 168.
A JSON object mapping sender, recipient, content and unicode to the file’s column headers, e.g. {“recipient”:“Mobile Number”,“content”:“Message”}. Without it, those four names are the expected headers.
How many messages to send per pacingPeriod, at least 1; the send must finish within 60 days. Set both or neither; setting them spreads delivery out instead of sending everything at once.
The period a pacing rate applies to: hour or day.
Whether to append a message link. Omit to follow the workspace setting.
What the appended link offers the recipient: unsubscribe (opt out of marketing), reply (send a reply from the web) or both.
Text placed before the message link, up to 64 characters. Omit to follow the workspace setting.
Responses
Section titled “Responses”The batch was accepted for sending. The Location header holds its URL.
A batch of SMS messages. The same shape is returned by every batch endpoint and carried by batch.* events.
object
The unique id of the batch.
How the batch was created: api (a list of messages), import (an uploaded file) or list (contact lists).
The batch status: queued (nothing has been sent yet), sending (some messages have been sent, failed or cancelled and the batch is not yet complete), paused (paced delivery paused or messages held for payment), completed or cancelled.
Message counts for the batch by status. sent includes delivered; total is every row including skipped ones.
object
Every row in the batch, including skipped ones.
Messages not yet handed to the network.
Messages handed to the network and not since failed, including those delivered.
Messages confirmed delivered.
Messages that failed.
Rows that were never queued; see skipped for why.
Messages that were cancelled.
Why rows were skipped rather than queued.
object
Recipients on the suppression list.
Recipients messaged within the skipMessagedWithinHours window.
Rows that failed validation.
Paced delivery details.
object
How many messages are sent per period.
The period a pacing rate applies to: hour or day.
Why paced delivery is paused: user (paused from the dashboard), sending_blocked (the workspace cannot send), sender_revoked (the sender is no longer approved), api_key_limit (the API key’s send limit was reached) or payment_required (the workspace is out of credit).
When (UTC) the last message is expected to send at the current rate, or null when not known.
Why a message is waiting rather than sending.
object
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).
When (UTC) the hold began.
When (UTC) the message fails if the hold is not lifted, or null when it has no validity window. Always null on a batch.
Rows that were rejected, by position. Only populated on the response that created the batch; empty everywhere else.
A row of the request that was not accepted.
object
The zero-based position of the row in the submitted messages.
What was wrong with the row.
The grouping tag applied to the batch, for usage reporting. A message can carry its own tag instead.
When (UTC) the batch was asked to send, or null when no send time was given.
When (UTC) the batch was created.
When (UTC) the last message reached a final state, or null while messages remain.
When (UTC) the batch was cancelled, or null.
Example
{ "source": "api", "status": "queued", "paced": { "period": "hour", "pauseReason": "user" }, "hold": { "reason": "payment_required" }}The request is not valid. The detail field says why, and errors lists any problems by field name.
Why a request failed, in the RFC 9457 problem details format.
object
A URI identifying the kind of problem, ending in a code such as validation_failed, not_found, sending_blocked or rate_limited.
A short, fixed summary of the kind of problem.
The HTTP status code of the response.
What went wrong with this particular request, when there is more to say than the title.
For validation failures, the problems found, keyed by field name (nested fields as template.name, list items as messages[3]).
object
The id recorded for this error, matching the Request-Id header when one is sent. Quote it when contacting support.
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.
Why a request failed, in the RFC 9457 problem details format.
object
A URI identifying the kind of problem, ending in a code such as validation_failed, not_found, sending_blocked or rate_limited.
A short, fixed summary of the kind of problem.
The HTTP status code of the response.
What went wrong with this particular request, when there is more to say than the title.
For validation failures, the problems found, keyed by field name (nested fields as template.name, list items as messages[3]).
object
The id recorded for this error, matching the Request-Id header when one is sent. Quote it when contacting support.
Example generated
{ "type": "example", "title": "example", "status": 1, "detail": "example", "errors": { "additionalProperty": [ "example" ] }, "requestId": "example"}Payment is required before the workspace can send this batch.
Why a request failed, in the RFC 9457 problem details format.
object
A URI identifying the kind of problem, ending in a code such as validation_failed, not_found, sending_blocked or rate_limited.
A short, fixed summary of the kind of problem.
The HTTP status code of the response.
What went wrong with this particular request, when there is more to say than the title.
For validation failures, the problems found, keyed by field name (nested fields as template.name, list items as messages[3]).
object
The id recorded for this error, matching the Request-Id header when one is sent. Quote it when contacting support.
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).
Why a request failed, in the RFC 9457 problem details format.
object
A URI identifying the kind of problem, ending in a code such as validation_failed, not_found, sending_blocked or rate_limited.
A short, fixed summary of the kind of problem.
The HTTP status code of the response.
What went wrong with this particular request, when there is more to say than the title.
For validation failures, the problems found, keyed by field name (nested fields as template.name, list items as messages[3]).
object
The id recorded for this error, matching the Request-Id header when one is sent. Quote it when contacting support.
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.
Why a request failed, in the RFC 9457 problem details format.
object
A URI identifying the kind of problem, ending in a code such as validation_failed, not_found, sending_blocked or rate_limited.
A short, fixed summary of the kind of problem.
The HTTP status code of the response.
What went wrong with this particular request, when there is more to say than the title.
For validation failures, the problems found, keyed by field name (nested fields as template.name, list items as messages[3]).
object
The id recorded for this error, matching the Request-Id header when one is sent. Quote it when contacting support.
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.
Why a request failed, in the RFC 9457 problem details format.
object
A URI identifying the kind of problem, ending in a code such as validation_failed, not_found, sending_blocked or rate_limited.
A short, fixed summary of the kind of problem.
The HTTP status code of the response.
What went wrong with this particular request, when there is more to say than the title.
For validation failures, the problems found, keyed by field name (nested fields as template.name, list items as messages[3]).
object
The id recorded for this error, matching the Request-Id header when one is sent. Quote it when contacting support.
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.
Why a request failed, in the RFC 9457 problem details format.
object
A URI identifying the kind of problem, ending in a code such as validation_failed, not_found, sending_blocked or rate_limited.
A short, fixed summary of the kind of problem.
The HTTP status code of the response.
What went wrong with this particular request, when there is more to say than the title.
For validation failures, the problems found, keyed by field name (nested fields as template.name, list items as messages[3]).
object
The id recorded for this error, matching the Request-Id header when one is sent. Quote it when contacting support.
Example generated
{ "type": "example", "title": "example", "status": 1, "detail": "example", "errors": { "additionalProperty": [ "example" ] }, "requestId": "example"}The API key’s send limit was reached. Retry after the Retry-After header.
Why a request failed, in the RFC 9457 problem details format.
object
A URI identifying the kind of problem, ending in a code such as validation_failed, not_found, sending_blocked or rate_limited.
A short, fixed summary of the kind of problem.
The HTTP status code of the response.
What went wrong with this particular request, when there is more to say than the title.
For validation failures, the problems found, keyed by field name (nested fields as template.name, list items as messages[3]).
object
The id recorded for this error, matching the Request-Id header when one is sent. Quote it when contacting support.
Example generated
{ "type": "example", "title": "example", "status": 1, "detail": "example", "errors": { "additionalProperty": [ "example" ] }, "requestId": "example"}The batch could not be queued right now. Retry after the Retry-After header.
Why a request failed, in the RFC 9457 problem details format.
object
A URI identifying the kind of problem, ending in a code such as validation_failed, not_found, sending_blocked or rate_limited.
A short, fixed summary of the kind of problem.
The HTTP status code of the response.
What went wrong with this particular request, when there is more to say than the title.
For validation failures, the problems found, keyed by field name (nested fields as template.name, list items as messages[3]).
object
The id recorded for this error, matching the Request-Id header when one is sent. Quote it when contacting support.
Example generated
{ "type": "example", "title": "example", "status": 1, "detail": "example", "errors": { "additionalProperty": [ "example" ] }, "requestId": "example"}