Single messages
POST /v1/messages sends one text to one number and answers with a message id at once. Login codes, password resets and payment alerts go out the moment your code calls it.
Send a messageBulk SMS API
BulkSMSAPI is a bulk SMS API for developers: send one text or a batch of up to 10,000 numbers per request to 227 countries over REST, follow every message with signed webhooks, and pay per message from a prepaid balance.
One SMS to the United States costs $0.00507 per segment.
Building blocks
POST /v1/messages sends one text to one number and answers with a message id at once. Login codes, password resets and payment alerts go out the moment your code calls it.
Send a messagePOST /v1/batches takes up to 10,000 numbers in one request, with one text for everyone or a personal text per number. Duplicates and bad numbers are set aside and listed in the answer.
Send a batchEvery delivered or failed message calls your endpoint with a signed JSON event. Each event gets 10 attempts over about 24 hours, so a deploy never costs you a status.
Set up webhooksGET /v1/pricing returns the price per segment for every country, without a key. Show costs in your own product, or check a route before a large send.
Read prices by APIAdd send_at to any request and the batch waits until that minute, from 2 minutes up to 45 days ahead. Cancel it before it starts and the full cost returns to the balance.
Schedule a batchPaste or upload a list, write the text, preview it per recipient and send without code. Every batch from the API shows up in the same console with live counts.
See the consoleOne event in your system, one text to one person, sent within seconds.
One text, or one text per person, to a list of thousands in a single request.
Send a one-time code from your auth service with POST /v1/messages and read the delivery event before the user asks for a new one.
Your order system calls the API when a parcel leaves the depot, with the time window and the tracking code in one short text.
A nightly job builds tomorrow's list and sends one batch with a personal text per patient or client, scheduled for the evening before.
Card payments, transfers and new device sign-ins trigger a text in the same second, priced per segment and logged with its status.
Send 50,000 numbers from the console or batches of 10,000 from your CRM, with an opt-out line added to every text.
Tell every affected customer at once when a service, a flight or a delivery route changes, and follow up when it is fixed.
curl https://bulksmsapi.cc/v1/batches \
-H "Authorization: Bearer $BULKSMSAPI_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: spring-sale-0412" \
-d '{
"name": "Spring sale",
"text": "Spring sale at Northwind: 20% off until Sunday. Opt out: northwind.example/sms",
"to": [
"+14155550123",
"+447400123456",
"+4915123456789"
]
}'const res = await fetch("https://bulksmsapi.cc/v1/batches", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.BULKSMSAPI_KEY}`,
"Content-Type": "application/json",
"Idempotency-Key": "spring-sale-0412",
},
body: JSON.stringify({
name: "Spring sale",
text: "Spring sale at Northwind: 20% off until Sunday. Opt out: northwind.example/sms",
to: ["+14155550123", "+447400123456", "+4915123456789"],
}),
});
const batch = await res.json();
console.log(res.status, batch.id, batch.recipients, batch.cost);import json, os, urllib.request
req = urllib.request.Request(
"https://bulksmsapi.cc/v1/batches",
data=json.dumps({
"name": "Spring sale",
"text": "Spring sale at Northwind: 20% off until Sunday. Opt out: northwind.example/sms",
"to": ["+14155550123", "+447400123456", "+4915123456789"],
}).encode(),
headers={
"Authorization": "Bearer " + os.environ["BULKSMSAPI_KEY"],
"Content-Type": "application/json",
"Idempotency-Key": "spring-sale-0412",
"User-Agent": "northwind-app/1.0",
},
method="POST",
)
with urllib.request.urlopen(req) as res:
batch = json.load(res)
print(res.status, batch["id"], batch["recipients"], batch["cost"])<?php
$ch = curl_init("https://bulksmsapi.cc/v1/batches");
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
"Authorization: Bearer " . getenv("BULKSMSAPI_KEY"),
"Content-Type: application/json",
"Idempotency-Key: spring-sale-0412",
],
CURLOPT_POSTFIELDS => json_encode([
"name" => "Spring sale",
"text" => "Spring sale at Northwind: 20% off until Sunday. Opt out: northwind.example/sms",
"to" => ["+14155550123", "+447400123456", "+4915123456789"],
]),
]);
$batch = json_decode(curl_exec($ch), true);
echo $batch["id"], " ", $batch["recipients"], " ", $batch["cost"], "\n";package main
import (
"bytes"
"encoding/json"
"fmt"
"net/http"
"os"
)
func main() {
body, _ := json.Marshal(map[string]any{
"name": "Spring sale",
"text": "Spring sale at Northwind: 20% off until Sunday. Opt out: northwind.example/sms",
"to": []string{"+14155550123", "+447400123456", "+4915123456789"},
})
req, _ := http.NewRequest("POST", "https://bulksmsapi.cc/v1/batches", bytes.NewReader(body))
req.Header.Set("Authorization", "Bearer "+os.Getenv("BULKSMSAPI_KEY"))
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Idempotency-Key", "spring-sale-0412")
res, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer res.Body.Close()
var batch map[string]any
json.NewDecoder(res.Body).Decode(&batch)
fmt.Println(res.StatusCode, batch["id"], batch["recipients"], batch["cost"])
}Pricing
GET /v1/pricing, so your own product can show the same numbers.227 of 227 countries
Balance $44 on the first top-up
About 8,678 one-segment messages to the United States
Balance $120 on the first top-up
About 23,668 one-segment messages to the United States
Balance $250 on the first top-up
About 49,309 one-segment messages to the United States
Balance $390 on the first top-up
About 76,923 one-segment messages to the United States
Balance $675 on the first top-up
About 133,136 one-segment messages to the United States
Balance $1,400 on the first top-up
About 276,134 one-segment messages to the United States
Message counts are for the United States at $0.00507 per segment. How payments work
10,000
numbers per batch request
Send a list in one call, split by country and priced per recipient.
600
requests per minute per key
Rate limit headers on every answer show what is left in the window.
1,200
messages per minute per account
The queue hands messages to the route in order, every two seconds.
Step 1
Your browser makes an account key. Save it once; it is the only login, with no email or password to manage.
Step 2
Add from $40 through the hosted checkout. The balance shows in the console and through GET /v1/balance.
Step 3
Name a key per app or environment, copy it once, and revoke it any time without touching the others.
Step 4
Call /v1/messages or /v1/batches and add a webhook URL: delivered and failed events arrive signed.
Create an account in seconds, top up from $40 and call the API from any language that speaks HTTPS. Prices start at $0.00247 per message.