Send Transactional Single SMS

Prev Next

The Transactional Single SMS API, also known as the single-send or one-off SMS API, lets you send targeted transactional SMS messages to your users. You can trigger these SMS messages once a user takes a specific action on your platform.

Use Cases

You can send transactional SMS messages for:

  • System notifications

  • Order confirmation/information

    • Thank you for your purchase! Your order number is {orderNumber}. View more information about your order here: {Link}

    • Hey, {firstName}! Thanks for your purchase! View more information about your order ({orderNumber}) here: {Link}

  • Shipping Confirmation

    • Great news, {firstName}! Your order ({orderNumber}) has shipped and will arrive soon. Click here to view your order details: {Link}

    • Get excited! Your order ({orderNumber}) has shipped and is on its way to you. Click here to view your order details: {Link}

  • Ticket booking confirmation or cancellation

    • Hey {firstName}, your order #{orderNumber} has been successfully canceled. You can check the status of your order here {Link}

  • Information about shipping and delivery updates

  • Recurring billing/payment updates

  • Appointment confirmations

  • Welcome Messages

  • Helping your users reset their passwords if they forget them

Endpoint and Headers

POSThttps://sms.useinsider.com/v1/send

Visit our Postman collection to test this request.

Header

Sample Value

Description

X-INS-AUTH-KEY

1a2b3c4d5e6f

This key is required to authorize your request. Refer to API Authentication Tokens to generate your token. If needed to test Transactional SMS, please request an API key from the Insider One team.

Content-Type

application/json

This header specifies the media type of the resource.

Body Parameters

Parameter

Description

Data Type

Required

to

Phone Number

String

Yes

content

Content of the SMS

String

Yes

uniqueArgs

Unique arguments of transactional SMS used for tracking purposes

Object

No

callback

The endpoint that you define to receive the webhook events. If the response does not return a 200 (Success) code, the Insider One system will respond with "Callback URL value is not valid".

URL

No

settings.UrlShorteningStatus

To use the URL shortening for status in your messages.

Boolean

No

settings.UrlShorteningDomain

To use the URL shortening for your domain in your messages. e.g. insdr.io

String

No

settings.UrlTrackingStatus

For using the URL click tracking in your messages. If you do not add this parameter to the payload, the default version will not provide usage. If you do not open urlTracking and if you do not have Insider Tag integration on the related link’s webpage, you will see the clickthrough metric under the analytics page as zero.

Boolean

No

settings.smartEncoding

This smart encoding will automatically convert special characters from UCS-2 to GSM-7.

Boolean

No

settings.UrlExcludeProtocol

For excluding URL protocol (e.g., 'http://' or 'https://')

Boolean

No

sendAt

Specifies the desired date and time at which the SMS message should be sent. For example: datetime=2006-01-02T15:04:05Z
This parameter is valid only for Twilio and Sinch partners.

String

No

You can enhance your transactional messages with emojis and special characters. Add them to the content field when sending a request to the endpoint, and they will be seamlessly delivered to the end user.

Please note that using emojis in your content changes the encoding system to UCS-2. Refer to the Smart Encoding and SMS Part articles for more details.

SMS Status Callback

The current status of your SMS messages while they are being sent is provided to you through the API URL you specify in the callback parameter. If you don't respond to code between 200 and 300, the system retries the request 10 times. The retry policy process is as follows; 

  • The first request is tried again 1 minute later.

  • The second request is tried again 2 minutes after the first attempt.

  • The third request is retried 3 minutes after the first attempt.

  • The fourth request is tried again 8 minutes later, after the first attempt.

  • The fifth request is tried again 13 minutes later, after the first attempt.

  • The sixth request is tried again 18 minutes later, after the first attempt.

  • The seventh request is tried again 28 minutes later, after the first attempt.

  • The eighth request is tried again 38 minutes later, after the first attempt.

  • The ninth request is tried again 48 minutes later, after the first attempt.

  • The tenth request is tried again an hour later, after the first attempt.

Sample Request

Every request to the request endpoint must include a JSON-formatted request body containing your SMS content.

Before sending your request, replace the sample values in the request header(s) and body where required.

Below is a sample request to send an SMS message with optional scheduling, URL shortening, and tracking settings.

curl --location 'https://sms.useinsider.com/v1/send' \
--header 'x-ins-auth-key: INS.Abcd1234' \
--header 'Content-Type: application/json' \
--data '{
    "content": "This is SMS body.",
    "to": "+105555555555",
    "callback": "http://callback.url",
    "sendAt" : "2024-03-30T11:30:27Z",
    "uniqueArgs": {
        "additionalProp1": "string",
        "additionalProp2": "string",
        "additionalProp3": "string"
    },
    "settings": {
        "urlExcludeProtocol": true,
        "urlShorteningDomain": "insdr.io",
        "urlShorteningStatus": true,
        "urlTrackingStatus": true,
        "smartEncoding": true
    }
}'

Sample Responses

SMS Accepted

{
    "message": "Accepted",
    "messageId": "sms-a1234567-b123-c123-d123-e123f123456"
}

SMS Sent

{
  "id": "sms-a1234567-b123-c123-d123-e123f123456",
  "uniqueArgs": {
    "additionalProp1": "string",
    "additionalProp2": "string",
    "additionalProp3": "string"
  },
  "event": "sent",
  "partCount": 1
}

SMS Delivered

This response indicates that your request was successfully completed.

{
  "id": "sms-a1234567-b123-c123-d123-e123f123456",
  "uniqueArgs": {
    "additionalProp1": "string",
    "additionalProp2": "string",
    "additionalProp3": "string"
  },
  "event": "delivered",
  "phoneNumber": "+901234567890",
  "timestamp": 1234567890
}

SMS Undelivered

{
  "id": "sms-a1234567-b123-c123-d123-e123f123456",
  "uniqueArgs": {
    "additionalProp1": "string",
    "additionalProp2": "string",
    "additionalProp3": "string"
  },
  "event": "undelivered",
  "reason": {
    "message": "Soft Bounce",
    "code": 1404
  },
  "phoneNumber": "+901234567890",
  "timestamp": 1234567890
}

SMS Dropped

{
  "id": "sms-a1234567-b123-c123-d123-e123f123456",
  "uniqueArgs": {
    "additionalProp1": "string",
    "additionalProp2": "string",
    "additionalProp3": "string"
  },
  "event": "failed",
  "reason": {
    "message": "Invalid Phone Number",
    "code": 1500
  },
  "partCount": 1,
  "phoneNumber": "+901234567890",
  "timestamp": 1234567890
}

SMS Scheduled

{
  "id": "sms-a1234567-b123-c123-d123-e123f123456",
  "uniqueArgs": {
    "additionalProp1": "string",
    "additionalProp2": "string",
    "additionalProp3": "string"
  },
  "event": "scheduled",
  "sendAt": "2006-01-02T15:04:05Z",
  "partCount": 1,
  "phoneNumber": "+901234567890",
  "timestamp": 1234567890
}

SMS Sent

{
  "id": "sms-a1234567-b123-c123-d123-e123f123456",
  "uniqueArgs": {
    "additionalProp1": "string",
    "additionalProp2": "string",
    "additionalProp3": "string"
  },
  "event": "sent",
  "sendAt": "2006-01-02T15:04:05Z",
  "partCount": 1,
  "phoneNumber": "+901234567890",
  "timestamp": 1234567890
}

Transactional SMS Events now logged in UCD by default

You can track your transactional SMS delivery performance directly in UCD automatically and without any setup required.

Transactional SMS events (delivered, undelivered, and dropped) are now written to UCD by default. Previously, these events had to be manually enabled through a support request.

With this update, you’ll benefit from:

  • Consistent data tracking across all transactional SMS use cases

  • No need for manual enablement or configuration

Error responses

Error response shape

All errors raised by the endpoint itself share one envelope. Read errorCode first; the HTTP status alone does not identify the failure, because several distinct causes share a status.

{
  "message": "Failed to validate request",
  "errorCode": "1001",
  "errors": [ { "field": "to", "error": "This field is required" } ]
}
  • message: Human-readable summary.

  • errorCode: The stable identifier to branch on and to quote in support requests.

  • errors: Present only on field-validation failures (errorCode 1001 and 1028). Each entry has a field and an error. There is no "message" key inside this array.

Three responses do not use this envelope because they are produced before the handler runs:

401 and 429 return a flat { "message": ... } with no errorCode, and a missing auth header or an oversized body returns an empty body with no JSON at all. The rows below state this per case.

202 Accepted — { "message": "Accepted", "messageId": "sms-a1234567-b123-c123" }. The message id is the literal prefix "sms-" followed by 18 characters, not a full UUID.

Error responses table

Use this table to identify and resolve the errors this endpoint returns. Each row shows the status code and errorCode, the response body you receive, what causes it, and how to fix it.

Status

JSON response

Cause

Fix

400 Bad Request — errorCode 1000

{ "message": "Invalid JSON content supplied", "errorCode": "1000" }

The request body could not be parsed as JSON, or a field's type does not match the schema (for example, a number where a string is expected).

Validate the body as JSON, using double quotes for keys and string values. Confirm Content-Type is application/json.

400 Bad Request — errorCode 1001

{ "message": "Failed to validate request", "errorCode": "1001", "errors": [ { "field": "to", "error": "This field is required" } ] }

A required body field is missing. The "field" key names which one.

Add the field named in the response. For this endpoint, "to" and "content" are both required; every other parameter is optional.

400 Bad Request — errorCode 1001

{ "message": "Failed to validate request", "errorCode": "1001", "errors": [ { "field": "to", "error": "This field must be a valid phone number." } ] }

The recipient value in "to" does not match the accepted phone-number pattern.

Send the number in E.164 format: a plus sign, a non-zero first digit, then 7 to 14 more digits, with no spaces or separators — for example +905551234567.

400 Bad Request — errorCode 1001

{ "message": "Failed to validate request", "errorCode": "1001", "errors": [ { "field": "content", "error": "This field must be less than or equal to 670" } ] }

The "content" value is empty or longer than 670 characters.

Keep the body between 1 and 670 characters. Emojis and special characters switch the encoding to UCS-2 and consume the budget faster — see SMS Part.

400 Bad Request — errorCode 1001

{ "message": "Failed to validate request", "errorCode": "1001", "errors": [ { "field": "sendAt", "error": "This field must be between 30 minutes (1800 seconds) and 3 days (259200 seconds) from now." } ] }

A scheduled send time was supplied outside the accepted window, or not in RFC3339 format.

Send "sendAt" as 2006-01-02T15:04:05Z, at least 30 minutes and at most 3 days ahead. Omit the field entirely to send immediately.

400 Bad Request — errorCode 1001

{ "message": "Failed to validate request", "errorCode": "1001", "errors": [ { "field": "content", "error": "Content contains domains not in the allowlist: example.com" } ] }

Your account has domain allowlisting enabled and the message body contains a link whose domain is not allowed.

Add the domain to your allowlist in the panel, or remove the link. Allowlist changes are cached for up to 10 minutes before they take effect.

400 Bad Request — errorCode 1028

{ "message": "callback url host "10.0.0.5" points to a non-public address", "errorCode": "1028", "errors": [ { "field": "callback", "error": "callback url host "10.0.0.5" points to a non-public address" } ] }

The "callback" URL was rejected, or a "callbackHeaders" key is reserved. Callback URLs must be http or https and must not point to localhost or to a private, link-local, CGNAT, or multicast address. Header keys beginning with x-ins- are reserved, as are HTTP framing, proxy, IP-forwarding, and cookie headers.

Use a publicly reachable https URL. Rename any rejected header; the "field" key tells you whether the URL or the headers were at fault.

400 Bad Request — no errorCode

{ "message": "expected content type application/json" }

The Content-Type header is missing or does not contain application/json. This check runs before the handler, so no errorCode is assigned.

Set Content-Type: application/json. A charset suffix such as application/json; charset=utf-8 is accepted; a proxy rewriting or stripping the header is the usual cause.

401 Unauthorized — no body

(empty response body)

The x-ins-auth-key header is absent or empty. The request is rejected before any JSON response is built.

Always send x-ins-auth-key. Do not assume a JSON body on 401 — parse defensively, or check the status code before decoding.

401 Unauthorized

{ "message": "unauthorized" }

The key in x-ins-auth-key is invalid, revoked, or not authorized for transactional SMS.

Send a current key in x-ins-auth-key. See API Authentication Tokens. To test Transactional SMS, request a key from the Insider One team. Note that authorization results are cached for one minute, so a newly revoked key can keep working for up to 60 seconds.

403 Forbidden

{ "message": "ip-restricted" }

The key is IP-restricted and the calling address is not on its allowlist.

Ask your Insider One contact to add the outbound addresses you call from. Note this is 403, not 401 — the key itself is valid.

403 Forbidden — errorCode 1024

{ "message": "Panel is deactivated", "errorCode": "1024" }

The InOne account behind the key is deactivated.

Contact your Insider One account team. Retrying will not clear this.

403 Forbidden — errorCode 1025

{ "message": "Transactional messaging is disabled", "errorCode": "1025" }

Transactional SMS is switched off for the account.

Ask your Insider One contact to enable transactional SMS for the account.

403 Forbidden — errorCode 1022

{ "message": "Panel is suspended", "errorCode": "1022" }

The account is suspended, typically for a billing or compliance reason.

Contact your Insider One account team to resolve the suspension.

403 Forbidden — errorCode 1016

{ "message": "Sender not found", "errorCode": "1016" }

The sender you named has no active, non-deleted transactional SMS sender configured for the account. The variant "Partner has no provider" means no sender is configured at all.

Check the sender name against Settings, or omit "sender" to use the account default. An explicitly named sender fails hard; only the default lookup falls back.

403 Forbidden — errorCode 1018

{ "message": "Invalid Provider Settings", "errorCode": "1018" }

The resolved sender is missing credential fields its provider requires.

Ask your Insider One contact to complete the sender's provider configuration. Note errorCode 1021 carries the same message but returns 500 — it means the stored settings could not be parsed, which is an internal fault rather than a configuration gap.

403 Forbidden — errorCode 1023

{ "message": "Transactional messaging is disabled", "errorCode": "1023" }

The resolved sender itself is disabled. Same message as 1025 but a different scope — 1025 is the account, 1023 is the sender.

Re-enable the sender in the panel, or send with a different sender. Branch on errorCode, not on the message text.

413 Payload Too Large — no body

(empty response body)

The request body reaches 19,900,000 bytes. The limit is exclusive, so a body of exactly that size is rejected.

Keep the body under 19,900,000 bytes. A single SMS never approaches this; hitting it points at an unintended payload, such as a whole batch sent to the single-send endpoint.

429 Too Many Requests

{ "message": "rate limited" }

You exceeded 200 requests per second. The counter is a fixed one-second window keyed on the x-ins-auth-key value, so the 201st request within the same second is rejected.

Throttle your client to stay under 200 requests per second and retry with exponential backoff. Splitting traffic across several API keys gives each key its own budget. The Send Transactional Bulk SMS endpoint has a separate budget and accepts up to 50 messages per request — see the Open item below before sizing against it.

429 Too Many Requests

{ "message": "POC quota reached", "errorCode": "" }

The account is on a proof-of-concept plan and has consumed its message allowance. This is a volume cap, not a rate limit. The errorCode is returned empty.

Do not retry — backoff will not clear this. Contact your Insider One account team to raise the allowance or move off the POC plan. Distinguish it from ordinary throttling by the message text, since both are 429.

500 Internal Server Error — errorCode 1003

{ "message": "Server error", "errorCode": "1003" }

An account-state or credential lookup failed on the Insider One side.

Retry with exponential backoff. If it persists for more than 15 minutes, contact the Insider One team with sample requests and the time window.

500 Internal Server Error — errorCode 1005

{ "message": "Failed to publish SMS", "errorCode": "1005" }

The message passed every check but could not be queued for delivery after three attempts. The message was not sent.

Retry the request. This code means the send definitively did not happen, so a retry cannot produce a duplicate.

500 Internal Server Error — errorCode 1015

{ "message": "Maintenance mode active", "errorCode": "1015" }

Maintenance mode is active for the platform, your account, or the provider your sender uses.

Pause sending and retry after the maintenance window. Rapid retries will not succeed; check with your Insider One contact for the expected duration.

500 Internal Server Error — errorCode 1032

{ "message": "Failed to secure callback credentials", "errorCode": "1032" }

An Authorization value supplied in "callbackHeaders" could not be encrypted for storage. The request is rejected rather than storing the credential in plaintext, so the message was not sent.

Retry once. If it persists, remove the Authorization callback header to unblock sending and report the error code to the Insider One team.

500 Internal Server Error — errorCode 1099

{ "message": "Internal server error", "errorCode": "1099" }

An unhandled error occurred while processing the request. Every occurrence is reported to Insider One's error tracking with a stack trace.

Retry with exponential backoff. If the response persists for more than 15 minutes, contact the Insider One team with sample requests.

500 Internal Server Error — errorCodes 1002, 1004, 1020, 1021

{ "message": "...", "errorCode": "1004" }

Less common internal faults: 1002 the authenticated account could not be read from the request context, 1004 a URL-shortening domain or country quota lookup failed, 1020 a branded short-URL status lookup failed, 1021 stored sender settings could not be parsed.

Retry with exponential backoff. For 1004 and 1020, sending with settings.urlShorteningStatus set to false avoids the failing path. Report the errorCode when contacting the Insider One team.

503 Service Unavailable

{ "message": "auth unavailable" }

The authentication service is unreachable and the circuit breaker is open. This is not a verdict on your key.

Retry with exponential backoff. Do not rotate or re-issue your API key in response to this status — the key is not the problem.

Limitations

  • All functions must be executed with a simple HTTPS POST request.

  • The API Key should be provided as the authorization key in the request header. If the key is incorrect, the operation will not execute, and the response will return an authorization error.

  • The transactional API cannot be used to send promotional SMS. It is designed to send transactional SMS only.

  • The phone number must be in E.164 format.

  • Content can’t be empty. The maximum limit is 670 characters.

  • The rate limit is 200 requests per second.

  • The maximum speed will be determined based on the Provider Setup.

  • Insider One will send a sample request to the callback URL you provide. If the response does not return a 200 (Success) code, the Insider One system will respond with "Callback URL value is not valid".

The default limit shown here is a standard baseline. If your use case requires higher capacity, feel free to reach out to the Insider One team. We can adjust it to fit your needs.