Skip to content

Send an SMS or MMS message

POST
/api/v2/messages/send
curl --request POST \
--url https://api.sipstack.com/api/v2/messages/send \
--header 'Content-Type: application/json' \
--header 'x-api-key: <x-api-key>' \
--data '{ "to": "+14165550100", "from": "+16135550200", "message": "Hi! Your appointment is confirmed for tomorrow at 2pm." }'

Sends an outbound SMS — or an MMS when media is supplied — from one of your organization’s numbers through Flare (transactional / A2P). Authenticated with an API key (sms:send scope). Subject to your plan’s message allowance and the per-client rate limit — see Rate Limits.

This path is an alias: the canonical, product-scoped path is POST /api/v2/flare/messages, and the two have identical behaviour.

Sending requires a Flare Pro-or-above plan with an active or trialing Flare subscription, and the from number must be a Flare A2P (team inbox) number. A request that fails any of these is refused with 403.

Attaching MMS media

There are three ways to attach media, and they may be combined. The total number of media parts per message is at most 10.

WayWhereField
Hosted URLs (the carrier fetches them)JSON bodymedia — also accepted as mediaUrls, or a single mediaUrl
Uploaded files, binarymultipart/form-datamedia, one file part per file
Uploaded files, base64JSON bodymediaFiles

Upload limits. Each uploaded file is at most 3,500,000 bytes (3.5 MB), and all uploaded files in one message are at most 3,500,000 bytes in total — Bandwidth’s documented MMS ceiling, so a larger payload cannot be delivered by the carrier. Accepted upload types are image/jpeg, image/png and image/gif, and only these; the declared type must be in that list and must match the file’s actual magic bytes. Video and audio MMS, and image/webp, are not currently accepted. Hosted URLs are not type-checked by SIPSTACK — the carrier fetches and validates them.

Uploading uses the same authorization, plan gating and metering as the hosted URL path. Uploaded media is stored in your organization’s regional object storage and handed to the carrier as a short-lived signed URL; nothing is stored until the message passes validation, entitlement and quota checks, so a rejected send stores nothing. The media_urls returned here and by GET /api/v2/messages and GET /api/v2/messages/{id} are 24-hour signed URLs for uploaded media, and the URLs exactly as supplied for hosted media.

An MMS bills a flat minimum of 4 SMS segments regardless of how the media arrived.

Send an SMS, or an MMS when media is supplied. Either message or media must be present (an MMS may carry media with no text).

Media can be attached two ways in a JSON body — hosted URLs (media, which the carrier fetches) or uploaded files (mediaFiles, base64). They may be combined, and the total number of media parts is at most 10. To upload files as binary instead of base64, post the same fields as multipart/form-data — see SendMessageMultipartRequest.

object
to
required

Recipient phone number — 10 or 11 digits (a leading 1 is added to 10-digit numbers).

string
message

Message body. Long messages are split into segments which count against your plan allowance. Optional when media is present.

string
from

Sending number — must be one of your organization’s active numbers. Omit to use the organization’s first active number.

string
media

Up to 10 absolute HTTPS URLs to attach as MMS media (the carrier fetches them server-side; non-HTTPS or unparseable URLs are rejected with 400). Also accepted as mediaUrls or a single mediaUrl string. An MMS bills a flat minimum of 4 SMS segments regardless of body length (a longer text body still bills its larger computed segment count).

The limit of 10 is the combined count of hosted URLs and uploaded files. Hosted URLs are not type-checked by SIPSTACK — the carrier fetches and validates them. Each URL is at most 2048 characters.

Array<string>
<= 10 items
mediaFiles
One of:
Array<object>

One uploaded MMS media file, carried as base64 in a JSON request body.

object
data
required

The file’s bytes, base64-encoded. May also be a full data URI (data:image/png;base64,...), in which case contentType is optional and is read from the URI. An empty file, invalid base64, or a malformed entry is rejected with 400 MEDIA_MALFORMED.

string
contentType

Declared MIME type. Required unless data is a data URI that carries one. It must be in the allowlist above (otherwise 400 MEDIA_TYPE_NOT_ALLOWED) and must match the file’s actual magic bytes (otherwise 400 MEDIA_TYPE_MISMATCH) — a mismatched file is never silently relabelled or transcoded. Video and audio MMS, and image/webp, are not currently accepted.

string
Allowed values: image/jpeg image/png image/gif
filename

Optional filename for the stored object. Has no effect on delivery.

string
Examples

Plain SMS

{
"to": "+14165550100",
"from": "+16135550200",
"message": "Hi! Your appointment is confirmed for tomorrow at 2pm."
}

Message accepted and sent to the carrier.

Media type application/json
object
success
boolean
message
string
data
object
messageId
string
to
string
from
string
status
string
type

mms when the message carried media, otherwise sms.

string
Allowed values: sms mms
media_urls

The attached media URLs (empty for a plain SMS). For uploaded media these are time-limited signed URLs, valid for 24 hours; hosted URLs are returned exactly as supplied.

Array<string>
Examples
Example sent

SMS accepted

{
"success": true,
"message": "Message sent successfully",
"data": {
"messageId": "msg_1765432100000_a1b2c3d4e",
"to": "+14165550100",
"from": "+16135550200",
"status": "sent",
"type": "sms",
"media_urls": []
}
}

Validation failure — missing to/message, invalid phone number format, an invalid/inactive from number, or media that fails validation. Media failures carry a machine-readable code.

Media type application/json

Error shape returned by the send endpoint. code is present on media validation failures and omitted on the older inline validation errors.

object
success
boolean
code

Machine-readable media validation code:

  • TOO_MANY_MEDIA — more than 10 media parts (hosted + uploaded).
  • MEDIA_TOO_LARGE — a single file, or the total of all uploaded files, is over 3,500,000 bytes.
  • MEDIA_TYPE_NOT_ALLOWED — the declared type is not image/jpeg, image/png or image/gif.
  • MEDIA_TYPE_MISMATCH — the file’s bytes are not what its declared type claims.
  • MEDIA_MALFORMED — empty file, invalid base64, or a malformed mediaFiles entry.

See Error Codes.

string
Allowed values: TOO_MANY_MEDIA MEDIA_TOO_LARGE MEDIA_TYPE_NOT_ALLOWED MEDIA_TYPE_MISMATCH MEDIA_MALFORMED
error
string
Examples

Missing recipient

{
"success": false,
"error": "Recipient phone number (to) is required"
}

Missing or invalid API key.

Media type application/json

Inline error shape used by the messaging API and management endpoints.

object
success
boolean
error
string
Examples
Example unauthorized

Missing or invalid API key

{
"success": false,
"error": "Invalid API key"
}

Refused — API access is not enabled on your plan, the Flare plan is below Pro or its subscription is not active/trialing, or the from number is not a Flare A2P (team inbox) number. Applies identically to hosted-URL and uploaded media.

Media type application/json

Inline error shape used by the messaging API and management endpoints.

object
success
boolean
error
string
Example
{
"success": false,
"error": "Recipient phone number (to) is required"
}

Rate limit or plan message allowance reached — the messaging quota is exhausted. Nothing is stored for a refused send.

Media type application/json

Inline error shape used by the messaging API and management endpoints.

object
success
boolean
error
string
Examples
Example rate_limited

Rate limit reached

{
"success": false,
"error": "Rate limit exceeded. Try again later."
}

Carrier send failed — the message is recorded with status failed.

Media type application/json

Inline error shape used by the messaging API and management endpoints.

object
success
boolean
error
string
Example
{
"success": false,
"error": "Recipient phone number (to) is required"
}