Overview
The bulk SMS endpoint allows you to send the same message to multiple recipients in a single API call. Each message is tracked individually with its own message ID.Send Bulk Messages
Use the/messages/bulk endpoint to send SMS to multiple recipients.
curl -X POST https://api-message.nativehub.live/api/v1/messages/bulk \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"recipients": [
"+8801712345678",
"+8801798765432",
"+8801611122233"
],
"from": "BRAND",
"body": "Hello! This is a bulk message from NativeMessage."
}'
const axios = require('axios');
const response = await axios.post(
'https://api-message.nativehub.live/api/v1/messages/bulk',
{
recipients: [
'+8801712345678',
'+8801798765432',
'+8801611122233'
],
from: 'BRAND',
body: 'Hello! This is a bulk message from NativeMessage.'
},
{
headers: {
'Authorization': `Bearer ${access_token}`,
'Content-Type': 'application/json'
}
}
);
const { batch_id, queued, failed, messages } = response.data;
console.log(`Batch ID: ${batch_id}`);
console.log(`Queued: ${queued}, Failed: ${failed}`);
import requests
response = requests.post(
'https://api-message.nativehub.live/api/v1/messages/bulk',
headers={
'Authorization': f'Bearer {access_token}',
'Content-Type': 'application/json'
},
json={
'recipients': [
'+8801712345678',
'+8801798765432',
'+8801611122233'
],
'from': 'BRAND',
'body': 'Hello! This is a bulk message from NativeMessage.'
}
)
data = response.json()
print(f"Batch ID: {data['batch_id']}")
print(f"Queued: {data['queued']}, Failed: {data['failed']}")
<?php
$ch = curl_init('https://api-message.nativehub.live/api/v1/messages/bulk');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode([
'recipients' => [
'+8801712345678',
'+8801798765432',
'+8801611122233'
],
'from' => 'BRAND',
'body' => 'Hello! This is a bulk message from NativeMessage.'
]));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Content-Type: application/json',
'Authorization: Bearer ' . $access_token
]);
$response = curl_exec($ch);
$data = json_decode($response, true);
echo "Batch ID: " . $data['batch_id'] . "\n";
echo "Queued: " . $data['queued'] . ", Failed: " . $data['failed'];
package main
import (
"bytes"
"encoding/json"
"net/http"
)
type BulkMessage struct {
Recipients []string `json:"recipients"`
From string `json:"from"`
Body string `json:"body"`
}
type BulkResponse struct {
BatchID string `json:"batch_id"`
Queued int `json:"queued"`
Failed int `json:"failed"`
Rejected int `json:"rejected"`
Messages []MessageResponse `json:"messages"`
}
func sendBulkSMS(accessToken string) {
msg, _ := json.Marshal(BulkMessage{
Recipients: []string{
"+8801712345678",
"+8801798765432",
"+8801611122233",
},
From: "BRAND",
Body: "Hello! This is a bulk message from NativeMessage.",
})
req, _ := http.NewRequest(
"POST",
"https://api-message.nativehub.live/api/v1/messages/bulk",
bytes.NewBuffer(msg),
)
req.Header.Set("Authorization", "Bearer "+accessToken)
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, _ := client.Do(req)
var bulkResp BulkResponse
json.NewDecoder(resp.Body).Decode(&bulkResp)
}
import java.net.http.*;
import java.net.URI;
import java.util.List;
import com.google.gson.Gson;
public class SendBulkSMS {
public static void main(String[] args) throws Exception {
HttpClient client = HttpClient.newHttpClient();
String requestBody = new Gson().toJson(Map.of(
"recipients", List.of(
"+8801712345678",
"+8801798765432",
"+8801611122233"
),
"from", "BRAND",
"body", "Hello! This is a bulk message from NativeMessage."
));
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://api-message.nativehub.live/api/v1/messages/bulk"))
.header("Authorization", "Bearer " + accessToken)
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(requestBody))
.build();
HttpResponse<String> response = client.send(request,
HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
}
}
using System.Net.Http;
using System.Text;
using System.Text.Json;
var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", $"Bearer {accessToken}");
var content = new StringContent(
JsonSerializer.Serialize(new {
recipients = new[] {
"+8801712345678",
"+8801798765432",
"+8801611122233"
},
from = "BRAND",
body = "Hello! This is a bulk message from NativeMessage."
}),
Encoding.UTF8,
"application/json"
);
var response = await client.PostAsync(
"https://api-message.nativehub.live/api/v1/messages/bulk",
content
);
var data = await response.Content.ReadFromJsonAsync<dynamic>();
Console.WriteLine($"Batch ID: {data.batch_id}");
Console.WriteLine($"Queued: {data.queued}, Failed: {data.failed}");
require 'net/http'
require 'json'
uri = URI('https://api-message.nativehub.live/api/v1/messages/bulk')
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
request = Net::HTTP::Post.new(uri.path)
request['Authorization'] = "Bearer #{access_token}"
request['Content-Type'] = 'application/json'
request.body = {
recipients: [
'+8801712345678',
'+8801798765432',
'+8801611122233'
],
from: 'BRAND',
body: 'Hello! This is a bulk message from NativeMessage.'
}.to_json
response = http.request(request)
data = JSON.parse(response.body)
puts "Batch ID: #{data['batch_id']}"
puts "Queued: #{data['queued']}, Failed: #{data['failed']}"
{
"batch_id": "batch_9x8y7z6w5v4u",
"queued": 3,
"failed": 0,
"rejected": 0,
"messages": [
{
"id": "msg_1a2b3c4d5e6f",
"to": "+8801712345678",
"status": "queued",
"part_count": 1
},
{
"id": "msg_2b3c4d5e6f7g",
"to": "+8801798765432",
"status": "queued",
"part_count": 1
},
{
"id": "msg_3c4d5e6f7g8h",
"to": "+8801611122233",
"status": "queued",
"part_count": 1
}
]
}
Understanding Batch ID
Thebatch_id is a unique identifier for your bulk send operation. Use it to:
- Track all messages from a single bulk request
- Filter delivery reports by batch
- Monitor campaign performance
Track Bulk Delivery
You can track individual messages using their message IDs or query all messages from a batch.curl -X GET "https://api-message.nativehub.live/api/v1/messages?batch_id=batch_9x8y7z6w5v4u" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN"
const axios = require('axios');
const response = await axios.get(
'https://api-message.nativehub.live/api/v1/messages',
{
params: {
batch_id: 'batch_9x8y7z6w5v4u'
},
headers: {
'Authorization': `Bearer ${access_token}`
}
}
);
const messages = response.data.messages;
const delivered = messages.filter(m => m.status === 'delivered').length;
console.log(`Delivered: ${delivered}/${messages.length}`);
import requests
response = requests.get(
'https://api-message.nativehub.live/api/v1/messages',
params={
'batch_id': 'batch_9x8y7z6w5v4u'
},
headers={
'Authorization': f'Bearer {access_token}'
}
)
messages = response.json()['messages']
delivered = sum(1 for m in messages if m['status'] == 'delivered')
print(f"Delivered: {delivered}/{len(messages)}")
<?php
$ch = curl_init('https://api-message.nativehub.live/api/v1/messages?batch_id=batch_9x8y7z6w5v4u');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Authorization: Bearer ' . $access_token
]);
$response = curl_exec($ch);
$data = json_decode($response, true);
$messages = $data['messages'];
$delivered = count(array_filter($messages, fn($m) => $m['status'] === 'delivered'));
echo "Delivered: $delivered/" . count($messages);
package main
import (
"encoding/json"
"net/http"
"net/url"
)
type MessagesResponse struct {
Messages []MessageResponse `json:"messages"`
}
func trackBatch(accessToken, batchID string) {
params := url.Values{}
params.Add("batch_id", batchID)
req, _ := http.NewRequest(
"GET",
"https://api-message.nativehub.live/api/v1/messages?"+params.Encode(),
nil,
)
req.Header.Set("Authorization", "Bearer "+accessToken)
client := &http.Client{}
resp, _ := client.Do(req)
var msgResp MessagesResponse
json.NewDecoder(resp.Body).Decode(&msgResp)
}
import java.net.http.*;
import java.net.URI;
public class TrackBatch {
public static void main(String[] args) throws Exception {
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://api-message.nativehub.live/api/v1/messages?batch_id=batch_9x8y7z6w5v4u"))
.header("Authorization", "Bearer " + accessToken)
.GET()
.build();
HttpResponse<String> response = client.send(request,
HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
}
}
using System.Net.Http;
var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", $"Bearer {accessToken}");
var response = await client.GetAsync(
"https://api-message.nativehub.live/api/v1/messages?batch_id=batch_9x8y7z6w5v4u"
);
var data = await response.Content.ReadFromJsonAsync<dynamic>();
var messages = data.messages;
Console.WriteLine($"Total messages: {messages.Count}");
require 'net/http'
require 'json'
uri = URI('https://api-message.nativehub.live/api/v1/messages')
uri.query = URI.encode_www_form({ batch_id: 'batch_9x8y7z6w5v4u' })
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
request = Net::HTTP::Get.new(uri)
request['Authorization'] = "Bearer #{access_token}"
response = http.request(request)
data = JSON.parse(response.body)
messages = data['messages']
delivered = messages.count { |m| m['status'] == 'delivered' }
puts "Delivered: #{delivered}/#{messages.length}"
Handling Failures
Some messages may fail due to invalid phone numbers or other issues. The response includes details for each failed message.{
"batch_id": "batch_9x8y7z6w5v4u",
"queued": 2,
"failed": 1,
"rejected": 0,
"messages": [
{
"id": "msg_1a2b3c4d5e6f",
"to": "+8801712345678",
"status": "queued",
"part_count": 1
},
{
"id": "msg_2b3c4d5e6f7g",
"to": "+8801798765432",
"status": "queued",
"part_count": 1
},
{
"to": "+880INVALID",
"status": "failed",
"error": "Invalid phone number format"
}
]
}
Always validate phone numbers before sending to reduce failure rates and optimize your messaging costs.
Best Practices
Optimal Batch Sizes
Optimal Batch Sizes
- Keep batches under 10,000 recipients per request
- For larger campaigns, split into multiple batches
- Process batches sequentially to avoid rate limits
Error Handling
Error Handling
- Check the
failedandrejectedcounts in the response - Log message IDs for successful sends
- Retry failed messages with corrected data
- Don’t retry messages with invalid phone numbers
Performance Tips
Performance Tips
- Send during off-peak hours for better delivery rates
- Use webhooks instead of polling for status updates
- Store batch_id for reporting and analytics
- Monitor delivery rates per batch to identify issues
Rate Limits
Rate Limits
- Default: 100 requests per minute
- Bulk endpoint: 50 requests per minute
- Contact support for higher limits on enterprise plans
Next Steps
Receive Delivery Reports
Set up webhooks to track message delivery in real-time
API Reference
Explore all bulk messaging parameters and options