SMS.
Send a transactional SMS from your wallet and read its delivery status. Every request needs an API key in the Authorization header; the reference overview covers keys, errors and rate limits.
Send an SMS
POST/v1/smsSending or full access key
Send one transactional SMS. The message is charged to your wallet when it is queued and delivered by the route Notix has configured for the destination country. Delivery status arrives through the sms.sent, sms.delivered and sms.failed webhooks, or by reading the message back.
Pricing
One GSM-7 message is up to 160 characters; longer text is billed per 153 character segment. Text with characters outside GSM-7 is billed per 70 characters (67 when concatenated). SMS needs no paid plan: it is prepaid from your wallet.
Sender ID
senderId is optional. It defaults to your team's own approved sender ID for the destination country, or to the shared Notix sender ID when you have none. Only a sender ID approved for your team is accepted. See SMS and sender IDs.
Idempotency
Pass an Idempotency-Key header to make a retry safe. The same key and body returns the original message. The same key with a different body answers 409.
Errors
| Status | Code | Meaning |
|---|---|---|
| 400 | BAD_REQUEST | The number is not valid E.164, the text is empty or over 1,600 characters, or the sender ID is not one you may use. |
| 402 | INSUFFICIENT_BALANCE | Your wallet cannot cover the message. Nothing was sent. |
| 403 | FORBIDDEN | SMS is not enabled for your team. |
| 409 | NOT_UNIQUE | The idempotency key was used with a different body. |
| 422 | RISK_REFUSED | Risk scoring refused the request. |
| Field | Type | About |
|---|---|---|
Idempotency-Key | string | Makes the request safe to retry. Same key and same body returns the original message. Same key and a different body answers 409 NOT_UNIQUE. |
| Field | Type | About |
|---|---|---|
torequired | string | The recipient phone number with its country code. |
textrequired | string | The message. Up to 1600 characters. GSM-7 text is billed in 160 character segments (153 when concatenated); text with other characters in 70 (67). At most 1,600 characters. |
senderId | string | A sender ID approved for this team. Defaults to the team's own approved sender ID for the country, or to the shared Notix sender ID when it has none. At most 11 characters. |
clientIp | string (ip) | The IPv4 or IPv6 address the end user made the request from. Used by risk scoring. Notix stores only a keyed hash of it. |
curl -X POST "https://app.usenotix.dev/api/v1/sms" \
-H "Authorization: Bearer $NOTIX_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"to": "+2348012345678",
"text": "Your order 4471 has shipped."
}'
import { Notix } from "notix-js";
const notix = new Notix(process.env.NOTIX_API_KEY);
const { data, error } = await notix.sms.send(
{ to: "+2348012345678", text: "Your order 4471 has shipped." },
{ idempotencyKey: "order-4471-shipped" },
);
from notix import Notix
notix = Notix() # reads NOTIX_API_KEY
message, _ = notix.sms.send(
{"to": "+2348012345678", "text": "Your order 4471 has shipped."},
idempotency_key="order-4471-shipped",
)
use Notix\Notix;
$notix = new Notix(getenv('NOTIX_API_KEY'));
$message = $notix->sms->send(['to' => '+2348012345678', 'text' => 'Your order 4471 has shipped.'], 'order-4471-shipped');
Responses
201The message was charged to the wallet and queued for delivery.
| Field | Type | About |
|---|---|---|
idrequired | string | |
torequired | string | Masked to the last four digits. |
statusrequired | string | One of |
segmentsrequired | integer | |
chargerequired | object | |
charge.currencyrequired | string | One of |
charge.amountrequired | string | Decimal string in the team's wallet currency. |
reasonrequired | object | Set when the status is failed or rejected. Plain language, never a provider code. Can be null. |
reason.coderequired | string | |
reason.messagerequired | string | |
createdAtrequired | string | |
updatedAtrequired | string |
400Invalid input: the number, the text length or the sender ID.
402The team wallet cannot cover the message. Nothing was sent.
| Field | Type | About |
|---|---|---|
errorrequired | object | |
error.coderequired | string | One of |
error.messagerequired | string |
403SMS is not enabled for this team, or the environment refuses this destination.
409The Idempotency-Key was used with a different body, or a request with it is in progress.
422Risk scoring refused the request. Nothing was sent.
| Field | Type | About |
|---|---|---|
errorrequired | object | |
error.coderequired | string | One of |
error.messagerequired | string | |
riskrequired | object | |
risk.scorerequired | number | |
risk.levelrequired | string | One of |
risk.reasonsrequired | object[] | |
risk.reasons[].coderequired | string | |
risk.reasons[].detailrequired | string |
List SMS messages
GET/v1/smsFull access key
List the team's SMS messages, newest first, with a cursor for the next page. Filter by status and page with cursor and limit (default 50, max 100). Needs a full access key.
| Status | Meaning |
|---|---|
queued | Charged, waiting for the provider. |
sent | Accepted by the network. |
delivered | Confirmed delivered by the provider's delivery report. |
failed | Not delivered after being sent. The charge stands. |
rejected | Refused before delivery. The charge was returned. |
| Field | Type | About |
|---|---|---|
cursor | string | |
limit | integer | Default |
status | string | One of |
curl -X GET "https://app.usenotix.dev/api/v1/sms" \
-H "Authorization: Bearer $NOTIX_API_KEY"
import { Notix } from "notix-js";
const notix = new Notix(process.env.NOTIX_API_KEY);
const { data, error } = await notix.sms.list({ limit: 20, status: "failed" });
from notix import Notix
notix = Notix() # reads NOTIX_API_KEY
page, _ = notix.sms.list(limit=20, status="failed")
use Notix\Notix;
$notix = new Notix(getenv('NOTIX_API_KEY'));
$page = $notix->sms->list(['limit' => 20, 'status' => 'failed']);
Responses
200The team's messages, newest first, with a cursor for the next page.
| Field | Type | About |
|---|---|---|
datarequired | object[] | |
data[].idrequired | string | |
data[].torequired | string | Masked to the last four digits. |
data[].statusrequired | string | One of |
data[].segmentsrequired | integer | |
data[].chargerequired | object | |
data[].charge.currencyrequired | string | One of |
data[].charge.amountrequired | string | Decimal string in the team's wallet currency. |
data[].reasonrequired | object | Set when the status is failed or rejected. Plain language, never a provider code. Can be null. |
data[].reason.coderequired | string | |
data[].reason.messagerequired | string | |
data[].createdAtrequired | string | |
data[].updatedAtrequired | string | |
nextCursorrequired | string | Can be null. |
400Invalid cursor, limit or status.
Get an SMS message
GET/v1/sms/{id}Full access key
Retrieve one SMS message by id, with its current delivery status and reason. Needs a full access key.
| Status | Meaning |
|---|---|
queued | Charged, waiting for the provider. |
sent | Accepted by the network. |
delivered | Confirmed delivered by the provider's delivery report. |
failed | Not delivered after being sent. The charge stands. |
rejected | Refused before delivery. The charge was returned. |
| Field | Type | About |
|---|---|---|
idrequired | string |
curl -X GET "https://app.usenotix.dev/api/v1/sms/<id>" \
-H "Authorization: Bearer $NOTIX_API_KEY"
import { Notix } from "notix-js";
const notix = new Notix(process.env.NOTIX_API_KEY);
const { data, error } = await notix.sms.get("sms_123");
from notix import Notix
notix = Notix() # reads NOTIX_API_KEY
message, _ = notix.sms.get("sms_123")
use Notix\Notix;
$notix = new Notix(getenv('NOTIX_API_KEY'));
$message = $notix->sms->get('sms_123');
Responses
200The message with its delivery status and reason.
| Field | Type | About |
|---|---|---|
idrequired | string | |
torequired | string | Masked to the last four digits. |
statusrequired | string | One of |
segmentsrequired | integer | |
chargerequired | object | |
charge.currencyrequired | string | One of |
charge.amountrequired | string | Decimal string in the team's wallet currency. |
reasonrequired | object | Set when the status is failed or rejected. Plain language, never a provider code. Can be null. |
reason.coderequired | string | |
reason.messagerequired | string | |
createdAtrequired | string | |
updatedAtrequired | string |