Send SMS with the API
With the Callr REST API, sending an SMS is quick and easy — just a simple POST
request to the /sms
endpoint. You can set the destination number, message content, sender ID, traffic type, and encoding.
Reference
📲 Example: Send an SMS
const baseUrl = 'https://api.callr.com/v2.0/sms'
const apiKey = '<callr-api-key>' // Get your API key from https://app.callr.com/api/keys
const number = '+33639981020' // E.164 formatted phone number
const params = new URLSearchParams({
to: number,
trafficType: 'marketing'
})
const url = `${baseUrl}?${params.toString()}`
const options = {
method: 'POST',
headers: {
accept: 'application/json',
'content-type': 'application/json',
'x-api-key': apiKey
},
body: JSON.stringify({ text: 'Hello world!' })
}
try {
const res = await fetch(url, options)
const json = await res.json()
console.log(json)
} catch (err) {
console.error(err)
}
import requests
api_key = '<callr-api-key>' # Replace with your Callr API key
number = '+33639981020' # Destination number (E.164 format)
text = 'Hello world!'
url = f'https://api.callr.com/v2.0/sms?to={number}&trafficType=marketing'
headers = {
'accept': 'application/json',
'content-type': 'application/json',
'x-api-key': api_key
}
payload = {
'text': text
}
try:
response = requests.post(url, headers=headers, json=payload)
response.raise_for_status()
print(response.json())
except requests.exceptions.RequestException as e:
print(f"Error sending SMS: {e}")
<?php
$apiKey = '<callr-api-key>'; // Replace with your Callr API key
$number = '+33639981020'; // Destination number
$text = 'Hello world!';
$url = 'https://api.callr.com/v2.0/sms?to=' . urlencode($number) . '&trafficType=marketing';
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'accept: application/json',
'content-type: application/json',
'x-api-key: ' . $apiKey
]);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode(['text' => $text]));
$response = curl_exec($ch);
$err = curl_error($ch);
curl_close($ch);
if ($err) {
echo "cURL Error: $err";
} else {
echo $response;
}
package main
import (
"bytes"
"encoding/json"
"fmt"
"net/http"
)
func main() {
apiKey := "<callr-api-key>" // Replace with your Callr API key
number := "+33639981020"
text := "Hello world!"
url := fmt.Sprintf("https://api.callr.com/v2.0/sms?to=%s&trafficType=marketing", number)
payload := map[string]string{
"text": text,
}
body, _ := json.Marshal(payload)
req, _ := http.NewRequest("POST", url, bytes.NewBuffer(body))
req.Header.Set("accept", "application/json")
req.Header.Set("content-type", "application/json")
req.Header.Set("x-api-key", apiKey)
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
fmt.Println("Error sending SMS:", err)
return
}
defer resp.Body.Close()
var result map[string]interface{}
json.NewDecoder(resp.Body).Decode(&result)
fmt.Println(result)
}
using System;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;
class Program
{
static async Task Main()
{
var apiKey = "<callr-api-key>"; // Replace with your Callr API key
var number = "+33639981020"; // Destination number
var text = "Hello world!";
var client = new HttpClient();
var url = $"https://api.callr.com/v2.0/sms?to={Uri.EscapeDataString(number)}&trafficType=marketing";
var requestBody = new StringContent(
"{\"text\":\"" + text + "\"}",
Encoding.UTF8,
"application/json"
);
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
client.DefaultRequestHeaders.Add("x-api-key", apiKey);
try
{
var response = await client.PostAsync(url, requestBody);
var responseContent = await response.Content.ReadAsStringAsync();
Console.WriteLine(responseContent);
}
catch (Exception ex)
{
Console.WriteLine($"Error sending SMS: {ex.Message}");
}
}
}
📋 Request Parameters
Parameter | Type | Required | Description |
---|---|---|---|
to | string | ✅ Yes | Destination phone number in E.164 format (e.g., +33639981020 ) |
text | string | ✅ Yes | The SMS body text (1 to 3200 characters) |
from | string | No | Sender ID (phone number or alphanumeric, max 11 characters). Requires prior approval. |
trafficType | string | No | "marketing" (default) or "alerting" . Required by some carriers. |
encoding | string | No | Force "gsm" or "unicode" encoding. Defaults to automatic detection. |
Note
If you leave
from
empty, Callr automatically sets an appropriate sender based on destination rules.
🔥 Status Lifecycle
Once the SMS is accepted, it will go through these statuses:
Status | Meaning |
---|---|
created | SMS has been created in the system |
pending | SMS is waiting to be sent |
sent | SMS has been sent by Callr |
remote-queued | SMS is queued on the carrier network |
delivered | SMS was successfully delivered to the recipient |
At any time, it may also move to:
Status | Meaning |
---|---|
error | SMS was rejected at creation |
failed | SMS was rejected by the carrier |
expired | SMS expired before delivery |
🧾 Response Fields
On a successful send (HTTP 202 Accepted), you will receive:
Field | Type | Description |
---|---|---|
sid | string | Short ID identifying the SMS |
direction | string | outbound |
from | string | Sender phone number or alphanumeric sender |
to | string | Destination number |
body.text | string | Body text of the SMS |
trafficType | string | "marketing" or "alerting" |
status | string | Current status of the SMS |
error | string | Error message if applicable |
created | datetime | When the SMS was created (RFC 3339 format) |
sent | datetime | When the SMS was sent (if applicable) |
delivered | datetime | When the SMS was delivered (if applicable) |
updated | datetime | Last status update time |
parts | integer | Number of SMS parts used |
network | string | MCC MNC network code (e.g., 20801 for Orange France) |
encoding | string | gsm or unicode |
cost | string | Cost of the SMS in cents |
paymentType | string | prepaid or postpaid |
statusHistory | array | List of all status transitions with timestamps |
📦 Example Response
{
"sid": "smsabcdef12345678",
"direction": "outbound",
"from": "TOPIMMO",
"to": "+33639981020",
"body": {
"text": "Hello world!"
},
"trafficType": "marketing",
"status": "sent",
"cost": "4.50",
"paymentType": "prepaid",
"created": "2025-04-24T17:42:28Z",
"updated": "2025-04-24T17:42:30Z",
"sent": "2025-04-24T17:42:29Z",
"delivered": null,
"encoding": "gsm",
"parts": 1,
"network": "20801",
"statusHistory": [
{
"before": "created",
"after": "pending",
"at": "2025-04-24T17:42:28Z"
},
{
"before": "pending",
"after": "sent",
"at": "2025-04-24T17:42:29Z"
}
]
}
🌐 Receive status updates with Webhooks
For webhook setup, go to the Webhooks section in the Callr Portal.
- Create a new webhook
- Select the event:
v2.sms.outbound.updated
- Provide your HTTPS endpoint URL
Example payload
{
"id": "a033174403257076580mk8v4KiGgZA32",
"at": "2025-04-07T13:29:30.765Z",
"sid": "pdszbxss",
"type": "v2.sms.outbound.updated",
"try": 0,
"payload": {
"direction": "outbound",
"sid": "callrsid",
"from": "SMS",
"to": "+33639980010",
"body": {
"text": "Hello world!"
},
"trafficType": "marketing",
"status": "delivered",
"error": "",
"created": "2024-04-24T17:42:28Z",
"delivered": "2024-04-24T17:42:28Z",
"updated": "2024-04-24T17:42:28Z",
"sent": "2024-04-24T17:42:28Z",
"parts": 1,
"network": "20801",
"encoding": "gsm",
"cost": "2.0",
"paymentType": "prepaid",
"statusHistory": [
{
"after": "delivered",
"before": "sent",
"at": "2024-04-24T17:42:28Z"
}
]
}
}
⚡ Good to Know
- GSM encoding supports 153 characters per SMS part (160 if there is only one part).
- Unicode encoding supports 67 characters per SMS part (70 if there is only one part).
- Multipart SMS are automatically handled by Callr and reassembled by carriers.
- Some countries/carriers require
"alerting"
traffic type for critical messages (OTP, security alerts).
Updated 8 days ago