Send SMS Batch
curl --request POST \
--url https://api.bland.ai/v1/sms/batch \
--header 'Content-Type: application/json' \
--header 'authorization: <authorization>' \
--data '
{
"file_id": "<string>",
"global": {
"agent_number": "<string>",
"agent_message": "<string>",
"request_data": {},
"metadata": {},
"disposition_ids": [
"<string>"
],
"citation_schema_ids": [
"<string>"
]
},
"column_mapping": {}
}
'import requests
url = "https://api.bland.ai/v1/sms/batch"
payload = {
"file_id": "<string>",
"global": {
"agent_number": "<string>",
"agent_message": "<string>",
"request_data": {},
"metadata": {},
"disposition_ids": ["<string>"],
"citation_schema_ids": ["<string>"]
},
"column_mapping": {}
}
headers = {
"authorization": "<authorization>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {authorization: '<authorization>', 'Content-Type': 'application/json'},
body: JSON.stringify({
file_id: '<string>',
global: {
agent_number: '<string>',
agent_message: '<string>',
request_data: {},
metadata: {},
disposition_ids: ['<string>'],
citation_schema_ids: ['<string>']
},
column_mapping: {}
})
};
fetch('https://api.bland.ai/v1/sms/batch', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.bland.ai/v1/sms/batch",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'file_id' => '<string>',
'global' => [
'agent_number' => '<string>',
'agent_message' => '<string>',
'request_data' => [
],
'metadata' => [
],
'disposition_ids' => [
'<string>'
],
'citation_schema_ids' => [
'<string>'
]
],
'column_mapping' => [
]
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"authorization: <authorization>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.bland.ai/v1/sms/batch"
payload := strings.NewReader("{\n \"file_id\": \"<string>\",\n \"global\": {\n \"agent_number\": \"<string>\",\n \"agent_message\": \"<string>\",\n \"request_data\": {},\n \"metadata\": {},\n \"disposition_ids\": [\n \"<string>\"\n ],\n \"citation_schema_ids\": [\n \"<string>\"\n ]\n },\n \"column_mapping\": {}\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("authorization", "<authorization>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.bland.ai/v1/sms/batch")
.header("authorization", "<authorization>")
.header("Content-Type", "application/json")
.body("{\n \"file_id\": \"<string>\",\n \"global\": {\n \"agent_number\": \"<string>\",\n \"agent_message\": \"<string>\",\n \"request_data\": {},\n \"metadata\": {},\n \"disposition_ids\": [\n \"<string>\"\n ],\n \"citation_schema_ids\": [\n \"<string>\"\n ]\n },\n \"column_mapping\": {}\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.bland.ai/v1/sms/batch")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["authorization"] = '<authorization>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"file_id\": \"<string>\",\n \"global\": {\n \"agent_number\": \"<string>\",\n \"agent_message\": \"<string>\",\n \"request_data\": {},\n \"metadata\": {},\n \"disposition_ids\": [\n \"<string>\"\n ],\n \"citation_schema_ids\": [\n \"<string>\"\n ]\n },\n \"column_mapping\": {}\n}"
response = http.request(request)
puts response.read_body{
"file_id": "file_abc123",
"global": {
"agent_number": "+14155551234",
"pathway_id": "pathway_xyz789",
"channel": "sms"
},
"column_mapping": {
"customer_name": "request_data"
}
}
{
"data": {
"message": "SMS batch processing initiated via Temporal workflow",
"batch_id": "file_abc123",
"workflow_id": "workflow_def456"
},
"errors": null
}
{
"data": null,
"errors": [
{
"error": "MISSING_FILE_ID",
"message": "file_id is required"
}
]
}
{
"data": null,
"errors": [
{
"error": "FILE_NOT_FOUND",
"message": "File not found or invalid file type for SMS batches"
}
]
}
{
"data": null,
"errors": [
{
"error": "AGENT_NUMBER_NOT_FOUND",
"message": "Agent number not found or not configured for SMS"
}
]
}
Messaging
Send SMS Batch
Send SMS messages to a large list of recipients from a pre-uploaded CSV file. Processing is handled asynchronously via a background workflow.
POST
/
v1
/
sms
/
batch
Send SMS Batch
curl --request POST \
--url https://api.bland.ai/v1/sms/batch \
--header 'Content-Type: application/json' \
--header 'authorization: <authorization>' \
--data '
{
"file_id": "<string>",
"global": {
"agent_number": "<string>",
"agent_message": "<string>",
"request_data": {},
"metadata": {},
"disposition_ids": [
"<string>"
],
"citation_schema_ids": [
"<string>"
]
},
"column_mapping": {}
}
'import requests
url = "https://api.bland.ai/v1/sms/batch"
payload = {
"file_id": "<string>",
"global": {
"agent_number": "<string>",
"agent_message": "<string>",
"request_data": {},
"metadata": {},
"disposition_ids": ["<string>"],
"citation_schema_ids": ["<string>"]
},
"column_mapping": {}
}
headers = {
"authorization": "<authorization>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {authorization: '<authorization>', 'Content-Type': 'application/json'},
body: JSON.stringify({
file_id: '<string>',
global: {
agent_number: '<string>',
agent_message: '<string>',
request_data: {},
metadata: {},
disposition_ids: ['<string>'],
citation_schema_ids: ['<string>']
},
column_mapping: {}
})
};
fetch('https://api.bland.ai/v1/sms/batch', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.bland.ai/v1/sms/batch",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'file_id' => '<string>',
'global' => [
'agent_number' => '<string>',
'agent_message' => '<string>',
'request_data' => [
],
'metadata' => [
],
'disposition_ids' => [
'<string>'
],
'citation_schema_ids' => [
'<string>'
]
],
'column_mapping' => [
]
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"authorization: <authorization>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.bland.ai/v1/sms/batch"
payload := strings.NewReader("{\n \"file_id\": \"<string>\",\n \"global\": {\n \"agent_number\": \"<string>\",\n \"agent_message\": \"<string>\",\n \"request_data\": {},\n \"metadata\": {},\n \"disposition_ids\": [\n \"<string>\"\n ],\n \"citation_schema_ids\": [\n \"<string>\"\n ]\n },\n \"column_mapping\": {}\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("authorization", "<authorization>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.bland.ai/v1/sms/batch")
.header("authorization", "<authorization>")
.header("Content-Type", "application/json")
.body("{\n \"file_id\": \"<string>\",\n \"global\": {\n \"agent_number\": \"<string>\",\n \"agent_message\": \"<string>\",\n \"request_data\": {},\n \"metadata\": {},\n \"disposition_ids\": [\n \"<string>\"\n ],\n \"citation_schema_ids\": [\n \"<string>\"\n ]\n },\n \"column_mapping\": {}\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.bland.ai/v1/sms/batch")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["authorization"] = '<authorization>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"file_id\": \"<string>\",\n \"global\": {\n \"agent_number\": \"<string>\",\n \"agent_message\": \"<string>\",\n \"request_data\": {},\n \"metadata\": {},\n \"disposition_ids\": [\n \"<string>\"\n ],\n \"citation_schema_ids\": [\n \"<string>\"\n ]\n },\n \"column_mapping\": {}\n}"
response = http.request(request)
puts response.read_body{
"file_id": "file_abc123",
"global": {
"agent_number": "+14155551234",
"pathway_id": "pathway_xyz789",
"channel": "sms"
},
"column_mapping": {
"customer_name": "request_data"
}
}
{
"data": {
"message": "SMS batch processing initiated via Temporal workflow",
"batch_id": "file_abc123",
"workflow_id": "workflow_def456"
},
"errors": null
}
{
"data": null,
"errors": [
{
"error": "MISSING_FILE_ID",
"message": "file_id is required"
}
]
}
{
"data": null,
"errors": [
{
"error": "FILE_NOT_FOUND",
"message": "File not found or invalid file type for SMS batches"
}
]
}
{
"data": null,
"errors": [
{
"error": "AGENT_NUMBER_NOT_FOUND",
"message": "Agent number not found or not configured for SMS"
}
]
}
Enterprise Feature - SMS batch sending is only available on Enterprise plans. Contact your Bland representative for access.
Before You Begin: Upload Your CSV
Before calling this endpoint, you must upload your recipient CSV file and get afile_id.
Upload your CSV via POST https://api.bland.ai/v1/files/attach with file_type: "batches". The response will include a file_id (UUID) that you pass to this endpoint.
CSV format requirements:
- Must include a column named exactly
phone_numbercontaining E.164-formatted numbers (e.g.+14155551234). Numbers without a leading+are automatically prefixed. - The
phone_numbercolumn cannot be remapped viacolumn_mapping— the column must be namedphone_numberin the CSV itself. - Additional columns become dynamic variables available in your pathway via
{{column_name}}syntax. - Columns named
request_data.fieldname(dot notation) are automatically parsed into the recipient’srequest_dataobject. - JSON arrays of objects are also accepted as an alternative to CSV.
phone_number,first_name,request_data.account_id
+14155551234,Alice,acc_001
+10987654321,Bob,acc_002
Headers
string
required
Your API key for authentication.
Body Parameters
string
required
The ID of a previously uploaded CSV file containing recipient phone numbers. The file must have been uploaded with
file_type: "batches". See Before You Begin above.object
required
Default SMS parameters applied to every message in the batch.
Show global object
Show global object
string
required
The E.164 formatted phone number to send messages from. Must be an SMS-enabled inbound number configured on your account.
string
The initial outbound message to send to each recipient. If omitted, the pathway configured on the number will handle the opening message.
object
Default request data to associate with each conversation. Per-recipient
request_data from the CSV is merged on top of this, with recipient values taking precedence.object
Custom metadata to attach to each conversation. Returned in all webhook payloads for correlating conversations with your internal systems.
string[]
An array of outcome IDs to run when each conversation ends. If omitted, the outcomes configured on the SMS number are used. See Outcomes.
object
Maps column names in your CSV to SMS send parameter names. Use this when your CSV column names don’t match the expected field names.Use this to map non-phone columns to Only
request_data or other SMS parameters. Note: phone_number cannot be used as a target — the phone number column in your CSV must be named phone_number exactly.Map columns to request_data to make them available as pathway variables:{
"customer_name": "request_data",
"preferred_lang": "request_data"
}
request_data is supported as a target — per-recipient fields like pathway_id or persona_id cannot be overridden from the CSV. Alternatively, use dot notation column names in your CSV directly (e.g. request_data.customer_name) to avoid needing column_mapping at all.Response
object
null|array
null on success, or a list of error objects if the request failed.{
"file_id": "file_abc123",
"global": {
"agent_number": "+14155551234",
"pathway_id": "pathway_xyz789",
"channel": "sms"
},
"column_mapping": {
"customer_name": "request_data"
}
}
{
"data": {
"message": "SMS batch processing initiated via Temporal workflow",
"batch_id": "file_abc123",
"workflow_id": "workflow_def456"
},
"errors": null
}
{
"data": null,
"errors": [
{
"error": "MISSING_FILE_ID",
"message": "file_id is required"
}
]
}
{
"data": null,
"errors": [
{
"error": "FILE_NOT_FOUND",
"message": "File not found or invalid file type for SMS batches"
}
]
}
{
"data": null,
"errors": [
{
"error": "AGENT_NUMBER_NOT_FOUND",
"message": "Agent number not found or not configured for SMS"
}
]
}
Docs for agents: llms.txt
Was this page helpful?