Skip to content
HEXSMSDEVELOPERS
HEXSMS API · v1

Bring SMS
into your service.

Start with one API key. Choose a destination and send to up to 1,000 recipients per request. Track each delivery.

REST APIJSONUp to 1,000 recipients / request

Quick start

  1. Create an API key

    After signup, approval, and OTP login, visitAPI key managementto create a key.

  2. Add credits

    The API uses your account balance and pricing. Credits are charged when your request is queued.

  3. Send and track your messages

    Save the campaign ID and use the status endpoint to track results.

Base URL https://hexsms.com

Call the API from your server over HTTPS. Preview mode does not issue real keys or send messages.

Coverage

190+Global network coverage

Selected network destinations

  • United States
  • Canada
  • United Kingdom
  • Germany
  • France
  • Spain
  • Italy
  • Netherlands
  • Sweden
  • Norway
  • Denmark
  • Poland
  • Romania
  • Czechia
  • Austria
  • Switzerland
  • Ireland
  • Portugal
  • Finland
  • Japan
  • South Korea
  • China
  • Taiwan
  • Hong Kong SAR China
  • Singapore
  • Malaysia
  • Indonesia
  • Philippines
  • Thailand
  • Vietnam
  • India
  • Bangladesh
  • Pakistan
  • Australia
  • New Zealand
  • Brazil
  • Mexico
  • South Africa
  • Nigeria
  • United Arab Emirates
  • Saudi Arabia

Destination availability, rates, and sender registration requirements depend on your account and local networks. Check country pricing before sending.

GET/api/v1/messages/countries

Use this endpoint to check enabled destinations and your applied prices. Specify country when sending and use numbers from the same country in each request. Destinations without configured pricing are not accepted.

200 OK
{ "currency": "USDT", "countries": [{ "country": "US", "unitPrice": 0.02 }] }

Authenticate with an API key

Include this header with every API request. Session cookies and OTP codes are not required.

HTTP
Authorization: Bearer YOUR_API_KEY

The secret is shown only once. Store it in a server environment variable, never in frontend code. Revoked keys and suspended accounts cannot use the API. You can have up to five active keys.

POST/api/v1/messages

Send to up to 1,000 recipients

Send the same message to multiple recipients. We validate and queue the request before returning a response. For different message content, send separate requests with unique Idempotency-Key values.

FieldTypeDescription
country *stringISO 3166-1 alpha-2 country code, such as US, GB, JP, or KR. There is no default country.
text *string1–1,600 characters after trimming. All recipients in a request receive the same content.
recipients *string[]1–1,000 mobile numbers. E.164 format with + and the calling code is recommended. All numbers must match country.
Idempotency-Key *header8–100 ASCII letters, digits, hyphens, or underscores. Choose a unique value for each operation.

Any invalid or duplicate number rejects the entire request without sending or charging. Duplicates are checked after normalization to international format.

cURL · Send bulk SMS
curl -X POST 'https://hexsms.com/api/v1/messages' \
  -H 'Authorization: Bearer YOUR_API_KEY' \
  -H 'Content-Type: application/json' \
  -H 'Idempotency-Key: notice-20261024-001' \
  -d '{
    "country": "US",
    "text": "Your verification code is 482913.",
    "recipients": ["+12025550123", "+12025550124"]
  }'
202 Accepted · Queued
{
  "id": "35bed356-b84a-452a-8e94-98b538972ecd",
  "country": "US",
  "state": "RUNNING",
  "total": 2,
  "segments": 1,
  "unitPrice": 0.025,
  "cost": 0.05,
  "createdAt": 1792800000000,
  "note": null,
  "replayed": false
}
If the response is lost, retry with the same request key.

Retrying with the same account, Idempotency-Key, content, and recipient order returns the original campaign without another send or charge (200, replayed: true). Different content returns 409. Idempotency survives API key rotation. Request keys do not expire.

How pricing works

Recipients × segments × account unit priceUCS-2 supports 70 characters in one segment, then 67 per segment. Basic GSM-7 supports 160, then 153 per segment. Extension characters count twice; emoji use UTF-16 length. unitPrice and cost are in USDT. The response contains the applied price; 0.025 above is only an example.

GET/api/v1/messages/{id}

Track each recipient

Use the id returned by the send endpoint. Only API campaigns owned by the same account are accessible. This endpoint returns stored results. Call refresh first if you need the latest carrier results.

cURL · Get delivery status
curl 'https://hexsms.com/api/v1/messages/35bed356-b84a-452a-8e94-98b538972ecd?limit=1&offset=0' \
  -H 'Authorization: Bearer YOUR_API_KEY'
200 OK · Per-recipient results
{
  "id": "35bed356-b84a-452a-8e94-98b538972ecd",
  "country": "US",
  "state": "DONE",
  "total": 2, "segments": 1,
  "unitPrice": 0.025, "cost": 0.05,
  "createdAt": 1792800000000, "note": null,
  "summary": { "DELIVERED": 1, "PENDING": 1 },
  "messages": [
    {
      "id": "d2787184-d8b8-49c6-9c15-1db90a6d5516",
      "to": "12025550123",
      "status": "DELIVERED",
      "statusName": "DELIVERED_TO_HANDSET",
      "description": "Message delivered to handset",
      "error": null,
      "updatedAt": 1792800005000
    }
  ],
  "pagination": { "limit": 1, "offset": 0, "nextOffset": 1 }
}

limit is 1–1,000 (default 100); offset is 0–1,000 (default 0). A null nextOffset means the last page. summary counts all recipients by status. to uses international digits without +. Timestamps are Unix milliseconds. Results may differ from input order; identify each message by its id.

DONE does not mean delivered.

It means queue processing is complete. Check each message for status DELIVERED to confirm delivery.

POST/api/v1/messages/{id}/refresh

Fetch the latest delivery results

Refresh stored results from carrier logs. No request body is needed. Read results with GET afterward. Refresh a campaign at most once every 30 seconds. Carrier logs are available for 48 hours after sending. Configured delivery webhooks may update results automatically.

cURL · Refresh delivery results
curl -X POST 'https://hexsms.com/api/v1/messages/35bed356-b84a-452a-8e94-98b538972ecd/refresh' \
  -H 'Authorization: Bearer YOUR_API_KEY'
200 OK
{ "id": "35bed356-b84a-452a-8e94-98b538972ecd", "updated": 2 }

updated is the number of rows updated. It can be zero while messages are queued or no new results exist. Poll GET at intervals of at least 10 seconds and call refresh only when needed.

Understand status codes

Campaign state

PREPARING: preparing · RUNNING: processing · PAUSED: paused · DONE: queue processed · CANCELED: canceled

Per-recipient statusMeaning
QUEUEDWaiting in the queue.
SENDINGSubmitting to the carrier.
PENDINGAccepted by the carrier; awaiting the final result.
DELIVEREDDelivered to the recipient device.
UNDELIVERABLECould not be delivered.
EXPIREDThe delivery validity period expired.
REJECTEDRejected or a processing error occurred.
CANCELEDCanceled before sending.
UNKNOWNThe result is not yet known.

Handle unknown status values, as carriers may add new codes. Check statusName, description, and error for failure details.

Handling errors

Error response format
{ "error": "Insufficient credits. Please top up and retry.", "code": "INSUFFICIENT_CREDITS" }
HTTPcodeWhat to check
403COUNTRY_NOT_ENABLEDCheck country pricing and activation.
400INVALID_COUNTRYSet country to an ISO country code.
400INVALID_BODY / INVALID_JSON / INVALID_TEXTCheck the JSON object and message content.
400INVALID_RECIPIENTS / INVALID_PHONE / DUPLICATE_PHONECheck recipient count, format, and duplicates.
400INVALID_IDEMPOTENCY_KEY / INVALID_PAGINATIONCheck the idempotency key or pagination values.
401UNAUTHORIZEDThe Bearer API key is missing or invalid.
402INSUFFICIENT_CREDITSTop up your credits.
403ACCOUNT_INACTIVEMake sure the account is approved and active.
404NOT_FOUNDCheck the campaign ID and ownership.
409IDEMPOTENCY_CONFLICTThe request key was reused with different content.
413 / 415BODY_TOO_LARGE / UNSUPPORTED_MEDIA_TYPESend a JSON body no larger than 128KiB.
429RATE_LIMITED / REFRESH_TOO_SOONWait the seconds specified in Retry-After before retrying.
500 / 502INTERNAL_ERROR / PROVIDER_UNAVAILABLETry again later. For send retries, use the same request key.
503PREVIEW_ONLYReal API calls are disabled in preview mode.

Each API key allows 120 requests per minute across sending, status, and refresh. Check Retry-After when limited. This API is for server-to-server use; browser CORS calls are not supported.

Connect with Node.js

Node.js · Run on your server
const response = await fetch('https://hexsms.com/api/v1/messages', {
  method: 'POST',
  headers: {
    Authorization: 'Bearer ' + process.env.HEXSMS_API_KEY,
    'Content-Type': 'application/json',
    'Idempotency-Key': 'notice-20261024-001'
  },
  body: JSON.stringify({
    country: 'US',
    text: 'Your order is on its way.',
    recipients: ['+12025550123', '+12025550124']
  })
});
const result = await response.json();
if (!response.ok) throw new Error(result.code + ': ' + result.error);
console.log(result.id); // Use this ID to check delivery status.

Create a request key once per operation and reuse it for retries. Resending a successful operation with a new key creates another send and charge.