{
"success": true,
"message": "<string>",
"message_id": "<string>",
"provider": "<string>",
"status": "<string>"
}{
"detail": [
{
"loc": [
"<string>"
],
"msg": "<string>",
"type": "<string>"
}
]
}Send SMS
Send an SMS message through an assistant.
This endpoint allows sending SMS messages using the telephony provider associated with the assistant that owns the from_phone_number.
The system will automatically:
- Find the assistant associated with the from_phone_number
- Use the assistant’s configured telephony provider (Twilio, Telnyx, or Vonage)
- Queue the SMS for delivery with per-provider rate limiting (default) or send immediately if queue=False
- Persist the outbound message to the SMS conversation (ChatMessage) for UI display
Idempotency: Pass an Idempotency-Key header (or idempotency_key in body) to dedupe sends from retried requests. Format: e.g., “chat:123:msg:456:outbound”
Args: sms_data: SMS request containing from/to numbers, message, and queue option
Returns: SendSMSResponse: Success status, message ID, status, and provider info
{
"success": true,
"message": "<string>",
"message_id": "<string>",
"provider": "<string>",
"status": "<string>"
}{
"detail": [
{
"loc": [
"<string>"
],
"msg": "<string>",
"type": "<string>"
}
]
}from_phone_number.
How It Works
- Assistant Lookup: The system identifies the assistant based on the
from_phone_number - Provider Selection: Automatically uses the assistant’s configured telephony provider
- Queue or Send: Either queues the message (with rate limiting) or sends immediately
- Response: Returns success status with message ID, provider, and delivery status
Request Body
| Parameter | Type | Required | Description |
|---|---|---|---|
from_phone_number | string | Yes | Sender phone number (must be assigned to an assistant) |
to_phone_number | string | Yes | Recipient phone number in E.164 format |
message | string | Yes | SMS message content (max 1600 characters) |
media_urls | array | No | List of media URLs for MMS messages |
queue | boolean | No | If true (default), queue with rate limiting. If false, send immediately |
idempotency_key | string | No | Unique key to prevent duplicate sends on retries (max 256 chars) |
Basic Request
{
"from_phone_number": "+1234567890",
"to_phone_number": "+1555123456",
"message": "Hello! This is a follow-up message from your AI assistant."
}
With All Options
{
"from_phone_number": "+1234567890",
"to_phone_number": "+1555123456",
"message": "Hello! This is a follow-up message from your AI assistant.",
"media_urls": ["https://example.com/image.jpg"],
"queue": false,
"idempotency_key": "order:12345:confirmation"
}
Queue vs Immediate Send
- Queued (Default)
- Immediate
queue: true (default):- Messages are queued and sent with rate limiting
- Helps avoid carrier throttling
- Better for bulk sends
- Returns
status: "queued"
{
"queue": true
}
queue: false:- Message is sent immediately
- Better for time-sensitive messages
- May hit rate limits if sending many messages
- Returns
status: "sent"on success; provider failures return an error response instead of a successfulfailedresponse
{
"queue": false
}
Idempotency
Theidempotency_key parameter prevents duplicate messages when retrying failed requests:
{
"from_phone_number": "+1234567890",
"to_phone_number": "+1555123456",
"message": "Your order #12345 has shipped!",
"idempotency_key": "order:12345:shipped:notification"
}
Idempotency-Key header. If both are provided, the header takes precedence.Response
A successful request returns a200 OK status with details about the message.
{
"success": true,
"message_id": "8ad70ee5-3d47-4fa4-a6ab-c9f2238d5f54",
"message": "SMS queued successfully via telnyx",
"provider": "telnyx",
"status": "queued"
}
Response Fields
| Field | Type | Description |
|---|---|---|
success | boolean | Whether the operation was successful |
message_id | string | Unique identifier for the message |
message | string | Human-readable status message |
provider | string | Telephony provider used (twilio, telnyx, or vonage) |
status | string | Delivery status: queued, sent, or failed |
message_id is Burki’s queue UUID. After delivery, use the status endpoint to inspect the provider’s message ID when available.
Error Responses
400 Bad Request
Returned when the request is malformed or contains invalid data.{
"detail": "Invalid to_phone_number format. Use E.164 format (e.g., +1234567890)"
}
- Missing required fields (
from_phone_number,to_phone_number,message) - Invalid phone number format (must be E.164)
- Empty message content
- Message exceeds 1600 characters
403 Forbidden
Returned when the authenticated user does not own the assistant or phone number used asfrom_phone_number.
{
"detail": "Unauthorized: phone number belongs to different organization"
}
404 Not Found
Returned when no assistant is found for the specifiedfrom_phone_number.
{
"detail": "No assistant found for phone number +1234567890"
}
500 Internal Server Error
Returned when the telephony provider fails to send the message.{
"detail": "Failed to send SMS via telnyx"
}
Use Cases
Customer Service Follow-up
Send follow-up messages after customer service calls:{
"from_phone_number": "+1234567890",
"to_phone_number": "+1555123456",
"message": "Thanks for calling! Here's the link we discussed: https://support.example.com/article/123",
"queue": false
}
Appointment Reminders
Send automated appointment reminders with idempotency:{
"from_phone_number": "+1234567890",
"to_phone_number": "+1555123456",
"message": "Reminder: Your appointment is tomorrow at 2:00 PM. Reply CONFIRM to confirm or RESCHEDULE to change the time.",
"idempotency_key": "appointment:456:reminder:24h"
}
Bulk Notifications (Queued)
For sending many messages, use the queue to avoid rate limits:{
"from_phone_number": "+1234567890",
"to_phone_number": "+1555123456",
"message": "Flash sale! 50% off all items today only. Shop now: example.com/sale",
"queue": true
}
Document Sharing (MMS)
Send documents or images via MMS:{
"from_phone_number": "+1234567890",
"to_phone_number": "+1555123456",
"message": "Here are the documents you requested:",
"media_urls": [
"https://yourdomain.com/documents/contract.pdf",
"https://yourdomain.com/images/diagram.png"
]
}
Authentication
This endpoint requires authentication. Include your API key in the request headers:curl -X POST "https://api.burki.dev/sms/send" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"from_phone_number": "+1234567890",
"to_phone_number": "+1555123456",
"message": "Hello from your AI assistant!"
}'
Related Endpoints
| Method | Path | Purpose |
|---|---|---|
GET | /sms/{message_id}/status | Check queued, sent, failed, or cancelled status |
DELETE | /sms/{message_id} | Cancel a queued message before delivery |
GET | /sms/queue/stats | Inspect queue statistics by provider |
Rate Limits
SMS sending is subject to rate limits imposed by the underlying telephony providers:- Twilio: Varies by account type and message volume
- Telnyx: Varies by account configuration
- Vonage: Varies by account type
queue: true option (default) to let Burki handle rate limiting automatically.Best Practices
Phone Number Format
Always use E.164 format for phone numbers:- Correct:
+1234567890 - Incorrect:
(123) 456-7890,123-456-7890,1234567890
Idempotency Keys
Use meaningful idempotency keys that include:- The type of message (e.g.,
order,appointment,alert) - A unique identifier (e.g., order ID, appointment ID)
- The specific action (e.g.,
confirmation,reminder)
order:12345:confirmationappointment:789:reminder:24hchat:session123:msg:456:outbound
Message Content
- Keep messages concise and clear
- Include clear call-to-action when needed
- Respect opt-out requests and regulatory requirements
- Consider character limits for international SMS
Error Handling
Always handle potential errors in your code:import requests
response = requests.post(
"https://api.burki.dev/sms/send",
headers={"Authorization": "Bearer YOUR_API_KEY"},
json={
"from_phone_number": "+1234567890",
"to_phone_number": "+1555123456",
"message": "Hello from your AI assistant!",
"idempotency_key": "test:123:hello"
}
)
if response.status_code == 200:
data = response.json()
print(f"SMS {data['status']} via {data['provider']}")
print(f"Message ID: {data['message_id']}")
else:
print(f"Error: {response.status_code} - {response.json()['detail']}")
Integration Examples
Node.js
const axios = require('axios');
async function sendSMS(fromPhone, toPhone, message, options = {}) {
try {
const response = await axios.post('https://api.burki.dev/sms/send', {
from_phone_number: fromPhone,
to_phone_number: toPhone,
message: message,
queue: options.queue ?? true,
idempotency_key: options.idempotencyKey
}, {
headers: {
'Authorization': 'Bearer YOUR_API_KEY',
'Content-Type': 'application/json'
}
});
console.log(`SMS ${response.data.status}:`, response.data);
return response.data;
} catch (error) {
console.error('Failed to send SMS:', error.response.data);
throw error;
}
}
// Usage
sendSMS('+1234567890', '+1555123456', 'Hello!', {
queue: false,
idempotencyKey: 'test:123'
});
Python
import requests
def send_sms(from_phone, to_phone, message, media_urls=None, queue=True, idempotency_key=None):
url = "https://api.burki.dev/sms/send"
headers = {
"Authorization": "Bearer YOUR_API_KEY",
"Content-Type": "application/json"
}
payload = {
"from_phone_number": from_phone,
"to_phone_number": to_phone,
"message": message,
"queue": queue
}
if media_urls:
payload["media_urls"] = media_urls
if idempotency_key:
payload["idempotency_key"] = idempotency_key
response = requests.post(url, json=payload, headers=headers)
if response.status_code == 200:
return response.json()
else:
raise Exception(f"SMS failed: {response.json()['detail']}")
# Usage
result = send_sms(
"+1234567890",
"+1555123456",
"Your order has shipped!",
idempotency_key="order:789:shipped"
)
print(f"Status: {result['status']}")
PHP
<?php
function sendSMS($fromPhone, $toPhone, $message, $options = []) {
$url = 'https://api.burki.dev/sms/send';
$headers = [
'Authorization: Bearer YOUR_API_KEY',
'Content-Type: application/json'
];
$data = [
'from_phone_number' => $fromPhone,
'to_phone_number' => $toPhone,
'message' => $message,
'queue' => $options['queue'] ?? true
];
if (isset($options['media_urls'])) {
$data['media_urls'] = $options['media_urls'];
}
if (isset($options['idempotency_key'])) {
$data['idempotency_key'] = $options['idempotency_key'];
}
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($httpCode === 200) {
return json_decode($response, true);
} else {
throw new Exception("SMS failed: " . $response);
}
}
?>
Authorizations
Bearer authentication header of the form Bearer <token>, where <token> is your auth token.
Body
Request model for sending SMS through an assistant.
Sender phone number (must be assigned to an assistant)
Recipient phone number in E.164 format (e.g., +1234567890)
SMS message content
1600Optional list of media URLs for MMS
If True (default), queue the SMS with rate limiting. If False, send immediately.
Optional idempotency key (e.g., 'chat:123:msg:456:outbound'). If provided, Burki will dedupe based on this key to prevent duplicate sends/persistence on retries. Can also be provided via Idempotency-Key header (header takes precedence).
256