Skip to main content

Send SMS

Send a single SMS message to a phone number.

Request Parameters

ParameterRequiredTypeDescription
FromMandatoryStringExoPhone or approved Sender ID. If your account has no valid Sender ID matching the SMS body, the API returns HTTP 400
ToMandatoryStringRecipient mobile number, preferably E.164 format
BodyMandatoryStringMessage content, max 2000 characters
EncodingTypeOptionalStringplain (default, auto-detected if not set) or unicode
ShortenUrlOptionalBooleantrue to shorten URLs in the SMS body. Chargeable feature — must be enabled for your account. See URL Shortening
StatusCallbackOptionalStringURL to receive delivery status notifications (form-encoded POST). Callback fields: SmsSid, To, Status, SmsUnits, DetailedStatus, DetailedStatusCode, DateSent, CustomField
DltEntityIdMandatory (India)StringDLT entity registration ID
DltTemplateIdOptionalStringDLT-approved template ID
SmsTypeOptionalStringtransactional (OTP/Service Implicit), transactional_opt_in (Service Explicit), or promotional. If not set, Exotel looks up the matching template on the dashboard
CustomFieldOptionalStringCustom reference field (e.g., Order ID, Payment ID)
PriorityOptionalStringnormal (default) or high. Use high only for OTP/bank/delivery SMS — misuse may impact delivery
BindingChainDetailsOptionalStringFor Telemarketer Aggregators in India only. Comma-separated PE and TM details: <PE_ID>,<YOUR_TM_ID>
DLT Compliance (Required for India)

DLT (Distributed Ledger Technology) is a regulatory requirement by TRAI for all SMS sent to Indian phone numbers. You must:

  1. Register as a business entity on a DLT portal (Jio, Airtel, Vodafone-Idea, or BSNL)
  2. Get your DLT Entity ID — pass this as DltEntityId in every SMS request
  3. Register message templates — get approved template IDs to pass as DltTemplateId
  4. Register your Sender ID (header) — e.g., "EXOTEL", used in the From parameter

Without DLT registration, SMS to Indian numbers will be blocked by telecom operators. See the SMS Overview for more details.

Code Examples

curl -u '<api_key>:<api_token>' -X POST https://api.exotel.com/v1/Accounts/<your_sid>/Sms/send \
-d "From=EXOTEL" \
-d "To=+919876543210" \
-d "Body=Your OTP is 123456" \
-d "DltEntityId=1234567890" \
-d "DltTemplateId=9876543210"

Response

{
"SMSMessage": {
"Sid": "sms_sid_value",
"AccountSid": "your_sid",
"From": "EXOTEL",
"To": "+919876543210",
"Body": "Your OTP is 123456",
"Status": "queued",
"DateCreated": "2024-01-15 10:30:00",
"DateUpdated": "2024-01-15 10:30:00",
"DateSent": null,
"Price": null,
"Uri": "/v1/Accounts/your_sid/SMS/Messages/sms_sid_value"
}
}

Response Fields

FieldTypeDescription
SidStringUnique SMS identifier
AccountSidStringYour Exotel account SID
FromStringFormat: <ExoPhone>/<SenderID>
ToStringRecipient number
BodyStringMessage content
StatusStringHigh-level status: queued, sending, submitted, sent, failed-dnd, failed
DetailedStatusCodeStringExotel's numeric status code — use for decision logic. See Status Codes
DetailedStatusStringHuman-readable status string — log this for debugging
DirectionStringoutbound-api (REST API), outbound-call (during call), outbound-reply (reply to incoming), incoming
SmsUnitsIntegerNumber of SMS units consumed (null until final state)
DateCreatedDateTimeWhen the request was received (YYYY-MM-DD HH:mm:ss)
DateUpdatedDateTimeLast status update timestamp
DateSentDateTimeWhen the SMS was delivered to the recipient
PriceDoubleAmount charged in INR or USD (if applicable)
UriStringPath to the SMS resource

HTTP Status Codes

CodeDescription
200Request accepted successfully
400Bad request — missing or invalid parameters
401Authentication failed
403Forbidden — insufficient permissions
429Rate limit exceeded
500Internal server error
note

A 200 response means the SMS request was accepted, not that it was delivered. Use the StatusCallback webhook or the SMS Details endpoint to confirm delivery.

Error Responses

When a request fails, the API returns an error JSON with details:

400 — Missing required parameter:

{
"RestException": {
"Status": 400,
"Message": "The 'From' parameter is required."
}
}

401 — Authentication failed:

{
"RestException": {
"Status": 401,
"Message": "Authentication failed. Verify your API key and token."
}
}

429 — Rate limit exceeded:

{
"RestException": {
"Status": 429,
"Message": "Rate limit exceeded. Max 200 requests per minute."
}
}

For a complete list of error codes and troubleshooting steps, see the Error Code Dictionary.

Try It