Send an SMS

POST
/v1/sms

Queues a text message from the API key's environment and returns it with status: "queued"; it is handed to the carrier moments later. Follow it with GET /v1/sms/{id} or the sms.sent, sms.delivered, sms.undelivered and sms.failed webhooks. Live (coss_live_…) keys send from one of the organization's numbers whose carrier registration is approved, to the countries the organization allows (US and Canada unless changed in the dashboard). Sandbox (coss_test_…) keys accept any from, deliver nothing and answer the SMS simulator's numbers (+15005550006 delivered, +15005550001 invalid, +15005550004 filtered by the carrier, +15005550009 opted out, +15005550008 replies). A number on the environment's SMS suppression list (it replied STOP, or it can't receive SMS) is skipped: the message is failed with suppressed. Segments count against the organization's send quota, and each is billed by the destination country.

Authorization

bearerAuth
headerAuthorizationBearer <token>

A secret API key from the dashboard: coss_live_… for production environments, coss_test_… for sandbox environments.

Header Parameters

Idempotency-Key?string

Makes retries safe: a repeated request with the same key and body returns the original message (with its current status) instead of sending again, for 24 hours. 1-256 characters.

Length1 <= length <= 256
Coss-Version?"2026-10-10"

The API version (a date) to use for this request. Defaults to your organization's version, pinned to the latest one when it first used the API and upgraded from the dashboard. The SDK always sends the version it was built for.

Value in"2026-10-10"

Request Body

application/json
  1. body
from*string

One of your organization's phone numbers, in E.164 form. Sandbox environments accept any number.

Match^\+[1-9]\d{6,14}$
to*string

The recipient's mobile number, in E.164 form.

Match^\+[1-9]\d{6,14}$
body*string

The text. Messages are split into segments of 153 GSM-7 or 67 Unicode characters (152 or 66 from a toll-free number; 160 or 70 for a single one), each billed; at most 10 (1,520 GSM-7 or 660 Unicode characters).

Length1 <= length <= 1600
tags?array<>

Up to 10 tags.

Itemsitems <= 10
scheduled_at?string

Send at this time instead of now (ISO 8601 with an offset, at most 30 days ahead). A time that is not in the future sends immediately.

Formatdate-time

Response Body

The message, accepted (queued or scheduled; failed when its number is suppressed). A replay returns the original message with its current status.

application/json
  1. response
object*"sms"
Value in"sms"
id*string
from*string
to*string
body*string
status*string

queued until handed to the carrier (sent), then delivered or undelivered once the carrier reports. failed: never sent. scheduled and canceled: scheduled sends.

Value in"queued""scheduled""sent""delivered""undelivered""failed""canceled"
segments*integer

Segments the body takes (what is billed).

encoding*string
Value in"gsm7""ucs2"
country*string

ISO 3166 country of to.

tags*array<>
failure*|

Why the message failed or wasn't delivered.

sandbox*boolean

Sent from a sandbox environment: simulated.

scheduled_at*|
Formatdate-time
sent_at*|
Formatdate-time
delivered_at*|
Formatdate-time
created_at*string
Formatdate-time
import { Coss } from "coss";const coss = new Coss({  apiKey: process.env.COSS_API_KEY,  baseUrl: "https://api.coss.com",});const { data, error } = await coss.sms.send({  from: "+14155550123",  to: "+14155550199",  body: "Your Acme code is 482913",  tags: [    {      name: "flow",      value: "sign_in",    },  ],});
{  "object": "sms",  "id": "sms_01k7c8m4q2f3e9v6t5r1n0p8yz",  "from": "+14155550123",  "to": "+14155550199",  "body": "Your Acme code is 482913",  "status": "delivered",  "segments": 1,  "encoding": "gsm7",  "country": "US",  "tags": [    {      "name": "flow",      "value": "sign_in"    }  ],  "failure": null,  "sandbox": false,  "scheduled_at": null,  "sent_at": "2026-11-10T12:00:01.000Z",  "delivered_at": "2026-11-10T12:00:04.000Z",  "created_at": "2026-11-10T12:00:00.000Z"}