SMS API Reference
Authentication
All API requests require a Bearer token in the Authorization header. Create an API key from the API Keys page in your portal.
Authorization: Bearer YOUR_API_KEY
Base URL
https://didfarm.com/api/v1/sms
Send SMS
POST /messages
Send an outbound SMS message from one of your SMS-enabled numbers.
Request body
| Parameter | Type | Required | Description |
|---|---|---|---|
from | string | Yes* | Your SMS-enabled number in E.164 format (e.g. +16625163513) |
from_number_id | integer | Yes* | Alternatively, the numeric ID of your number (from GET /numbers) |
to | string | Yes | Destination number in E.164 format (e.g. +31612345678) |
body | string | Yes | Message text, max 1,600 characters |
status_callback_url | string | No | URL to receive delivery status webhooks |
* Provide either from or from_number_id, not both.
curl -X POST https://didfarm.com/api/v1/sms/messages \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"from": "+16625163513",
"to": "+31612345678",
"body": "Your order #1234 has shipped!"
}'{
"data": {
"id": 42,
"from": "+16625163513",
"to": "+31612345678",
"body": "Your order #1234 has shipped!",
"direction": "outbound",
"status": "queued",
"segments": 1,
"cost": 0.008,
"currency": "EUR",
"carrier": "didfarm",
"created_at": "2026-04-03T10:15:30+00:00"
}
}List Messages
GET /messages
Retrieve your SMS messages with optional filtering and pagination.
Query parameters
| Parameter | Type | Description |
|---|---|---|
direction | string | Filter by inbound or outbound |
status | string | Filter by status: queued, sent, delivered, failed |
number_id | integer | Filter by DID number ID |
from | string | Filter by sender number |
to | string | Filter by destination number |
since | datetime | Only messages after this timestamp (ISO 8601) |
page | integer | Page number (default: 1) |
per_page | integer | Results per page (default: 25, max: 100) |
curl https://didfarm.com/api/v1/sms/messages?direction=outbound&per_page=10 \ -H "Authorization: Bearer YOUR_API_KEY"
{
"data": [
{
"id": 42,
"from": "+16625163513",
"to": "+31612345678",
"body": "Your order #1234 has shipped!",
"direction": "outbound",
"status": "delivered",
"segments": 1,
"cost": 0.008,
"currency": "EUR",
"carrier": "didfarm",
"created_at": "2026-04-03T10:15:30+00:00"
}
],
"meta": {
"total": 156,
"page": 1,
"per_page": 10,
"total_pages": 16
}
}Get Message
GET /messages/{'{id}'}
Retrieve a single message by ID, including delivery status and cost.
curl https://didfarm.com/api/v1/sms/messages/42 \ -H "Authorization: Bearer YOUR_API_KEY"
List SMS Numbers
GET /numbers
List your active numbers that have SMS enabled. Use the id field as from_number_id when sending.
curl https://didfarm.com/api/v1/sms/numbers \ -H "Authorization: Bearer YOUR_API_KEY"
{
"data": [
{ "id": 11, "number": "+16625163513", "country_code": "US", "number_type": "local", "sms_enabled": true },
{ "id": 6, "number": "+16315950406", "country_code": "US", "number_type": "local", "sms_enabled": true }
]
}Delivery Status Webhooks
Receive real-time delivery updates by providing a status_callback_url when sending a message.
curl -X POST https://didfarm.com/api/v1/sms/messages \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"from": "+16625163513",
"to": "+31612345678",
"body": "Hello!",
"status_callback_url": "https://yourapp.com/webhooks/sms"
}'DIDfarm will POST to your URL when the message status changes:
{
"event": "sms.status_updated",
"data": {
"id": 42,
"from": "+16625163513",
"to": "+31612345678",
"direction": "outbound",
"status": "delivered",
"segments": 1,
"cost": 0.008,
"currency": "EUR",
"created_at": "2026-04-03T10:15:30+00:00",
"updated_at": "2026-04-03T10:15:33+00:00"
},
"timestamp": "2026-04-03T10:15:33+00:00"
}Verifying webhook signatures
Each webhook includes an X-DIDFarm-Signature header containing an HMAC-SHA256 signature of the JSON payload, signed with your application key.
const crypto = require('crypto');
function verifyWebhook(payload, signature, secret) {
const expected = crypto
.createHmac('sha256', secret)
.update(JSON.stringify(payload))
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expected)
);
}Error Handling
All errors return a JSON object with an error key:
{
"error": {
"code": "insufficient_balance",
"message": "Wallet balance too low to send this message"
}
}| HTTP Status | Error Code | Description |
|---|---|---|
| 401 | unauthenticated | Missing or invalid API key |
| 404 | not_found | Message or number not found |
| 422 | number_not_found | From number not found, inactive, or SMS not enabled |
| 422 | validation_error | Missing or invalid request parameters |
| 429 | rate_limited | Too many requests (see Rate Limits) |
| 500 | send_failed | Carrier rejected the message |
Rate Limits
| Limit | Value |
|---|---|
| Requests per minute | 60 |
| Messages per second | 10 (carrier limit) |
Rate limit headers are included in every response:
X-RateLimit-Limit— maximum requests allowedX-RateLimit-Remaining— requests remaining in windowRetry-After— seconds to wait (only on 429 responses)
Code Examples
Node.js
const API_KEY = 'your_api_key_here';
async function sendSms(from, to, body) {
const res = await fetch('https://didfarm.com/api/v1/sms/messages', {
method: 'POST',
headers: {
'Authorization': `Bearer ${API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({ from, to, body }),
});
const data = await res.json();
if (!res.ok) throw new Error(data.error?.message || 'Send failed');
return data.data;
}
// Usage
const msg = await sendSms('+16625163513', '+31612345678', 'Hello!');
console.log(`Sent! ID: ${msg.id}, Status: ${msg.status}`);Python
import requests
API_KEY = 'your_api_key_here'
BASE_URL = 'https://didfarm.com/api/v1/sms'
def send_sms(from_number, to, body):
resp = requests.post(
f'{BASE_URL}/messages',
headers={
'Authorization': f'Bearer {API_KEY}',
'Content-Type': 'application/json',
},
json={'from': from_number, 'to': to, 'body': body},
)
resp.raise_for_status()
return resp.json()['data']
# Usage
msg = send_sms('+16625163513', '+31612345678', 'Hello from Python!')
print(f"Sent! ID: {msg['id']}, Status: {msg['status']}")PHP
$apiKey = 'your_api_key_here';
$ch = curl_init('https://didfarm.com/api/v1/sms/messages');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
"Authorization: Bearer {$apiKey}",
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => json_encode([
'from' => '+16625163513',
'to' => '+31612345678',
'body' => 'Hello from PHP!',
]),
]);
$response = curl_exec($ch);
$data = json_decode($response, true);
echo "Sent! ID: {$data['data']['id']}\n";Webhook receiver (Node.js / Express)
const express = require('express');
const app = express();
app.use(express.json());
app.post('/webhooks/sms', (req, res) => {
const { event, data } = req.body;
if (event === 'sms.status_updated') {
console.log(`Message ${data.id}: ${data.status}`);
if (data.status === 'delivered') {
// Message confirmed delivered
} else if (data.status === 'failed') {
// Handle delivery failure
}
}
res.sendStatus(200);
});
app.listen(3000);Ready to integrate?
Create an API key and send your first SMS in under a minute.