Send an SMS message

Send an SMS message

POST/api/v1/sms

POST /sms
curl -X POST 'https://www.unitpost.com/api/v1/sms' \
  -H 'Authorization: Bearer YOUR_API_KEY' \
  -H 'User-Agent: my-app/1.0' \
  -H 'Content-Type: application/json' \
  -d '{
    "to": "+15551234567",
    "body": "Your code is 123456"
  }'
Response · 200
{
  "object": "sms",
  "id": "id_123",
  "to": "customer@example.com",
  "from": "you@yourdomain.com",
  "direction": "outbound",
  "status": "queued",
  "type": "transactional",
  "body": "string",
  "segments": 0,
  "country": "string",
  "scheduled_at": "2026-01-01T00:00:00.000Z",
  "last_error": "string",
  "error": {
    "code": "out_of_reach",
    "message": "string"
  },
  "created_at": "2026-01-01T00:00:00.000Z"
}

Send a single SMS — now, or at a future time by passing scheduled_at. The recipient must be a valid E.164 number; marketing sends additionally require the recipient's prior express consent on record and honor recipient-local quiet hours (they are deferred to the next allowed window, never dropped). The sender is chosen by the recipient's country — the active number or Sender ID whose reach covers it, exactly as campaigns route — unless you pin one with from (a snum_… id from List SMS numbers, or the number / Sender ID string). Pass an Idempotency-Key header to make retries safe: the same key with the same body replays the original message instead of sending (and billing) twice. Billing is per segment. Read delivery state back with Retrieve an SMS message. Requires the sms:send capability.

Request body6 fields
FieldTypeDescription
torequiredstringRecipient phone number in E.164 format, e.g. `+15551234567`.
fromstringOptional sender to send from: a number id from `GET /sms/numbers` (`snum_…`), or the E.164 number / Sender ID string itself (e.g. `+18005550100`, `Acme`). Must belong to your workspace, be active, and be able to reach the recipient's country — otherwise `404 not_found`, `403 sender_not_approved`, or `422 sender_cannot_reach`. Omit to route automatically: Unitpost picks the active sender whose reach covers the recipient's country (10DLC before toll-free for US recipients; the matching Sender ID elsewhere), exactly as campaigns do.
bodyrequiredstringMessage text. Billing is per segment (160 GSM-7 chars single-segment, 153 per segment concatenated; 70/67 for Unicode).
typeenumtransactional | marketingMarketing sends require the recipient's prior express consent on record and honor recipient-local quiet hours.
scheduled_atstringISO-8601 time to send at. Omit to send immediately.
create_contactbooleanCreate a contact for this recipient if one doesn't exist yet. Defaults to false. Sends don't modify your contact list. When the recipient is already a contact, the message is attached to them either way. A contact created this way records no consent, so it can't be used for marketing sends.
Response · 200 fields14 fields
FieldTypeDescription
objectrequiredstring—
idrequiredstring—
torequiredstring—
fromrequiredobject—
directionrequiredenumoutbound | inbound—
statusrequiredenumqueued | scheduled | sending | sent | delivered | failed | suppressed | canceled | received—
typerequiredenumtransactional | marketing—
bodyrequiredobject—
segmentsrequiredinteger—
countryrequiredobject—
scheduled_atrequiredobject—
last_errorrequiredobjectLegacy free-text error. Prefer `error.code`.
errorrequiredobjectSet on `suppressed` messages: the stable skip reason and its sentence. Null otherwise.
created_atrequiredstring—
200401403404409422429

Search docs and guides

Search the docs and product guides.