Comienza
Referencia de la API de Bulk SMS
BulkSMSAPI es una API de SMS masivos para desarrolladores: envía un mensaje o un lote de hasta 10,000 números por solicitud a 227 países mediante REST, sigue cada mensaje con webhooks firmados y paga por mensaje desde un saldo prepago. Esta referencia cubre cada endpoint, campo, evento y error de la API. Cada página también está disponible en Markdown: añade .md a su dirección.
URL base y formato
Todas las solicitudes van a https://bulksmsapi.cc/v1 sobre HTTPS. Los cuerpos son JSON (Content-Type: application/json, UTF-8) y cada respuesta es JSON, incluidos los errores. Los tiempos son ISO 8601 en UTC. El dinero es una cadena en dólares estadounidenses con cinco decimales ("0.00507"), por lo que los precios inferiores a un centavo son exactos.
Endpoints
| Método y ruta | Qué hace | Key |
|---|---|---|
| POST /v1/messages | Enviar un mensaje a un número | Yes |
| POST /v1/batches | Enviar hasta 10,000 números, un mensaje o uno por número | Yes |
| GET /v1/messages/{id} | Un mensaje con su estado y precio | Yes |
| GET /v1/messages | Mensajes, los más nuevos primero, filtrar por lote o estado | Yes |
| GET /v1/batches/{id} | Un lote con conteos por estado | Yes |
| GET /v1/batches | Lotes, los más nuevos primero | Yes |
| POST /v1/batches/{id}/cancel | Cancelar un lote programado, reembolso completo | Yes |
| POST /v1/estimates | Cotizar una solicitud sin enviarla | Yes |
| GET /v1/balance | Saldo en USD | Yes |
| GET /v1/pricing | Precio por segmento para cada país | No |
| GET /v1/pricing/{country} | Precio para un país (código ISO) | No |
Primera solicitud
Crea una clave API en la consola, expórtala y envía un mensaje. La respuesta es 202 con el objeto del mensaje: el costo se deduce del saldo y el mensaje se pone en cola.
curl https://bulksmsapi.cc/v1/messages \
-H "Authorization: Bearer $BULKSMSAPI_KEY" \
-H "Content-Type: application/json" \
-d '{
"to": "+14155550123",
"text": "Your Northwind code is 482913. It expires in 10 minutes.",
"reference": "login-7781"
}'// Node.js 18 or newer (built-in fetch)
const res = await fetch("https://bulksmsapi.cc/v1/messages", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.BULKSMSAPI_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
to: "+14155550123",
text: "Your Northwind code is 482913. It expires in 10 minutes.",
reference: "login-7781",
}),
});
const message = await res.json();
console.log(res.status, message.id, message.status, message.price);# Python 3, standard library only
import json, os, urllib.request
req = urllib.request.Request(
"https://bulksmsapi.cc/v1/messages",
data=json.dumps({
"to": "+14155550123",
"text": "Your Northwind code is 482913. It expires in 10 minutes.",
"reference": "login-7781",
}).encode(),
headers={
"Authorization": "Bearer " + os.environ["BULKSMSAPI_KEY"],
"Content-Type": "application/json",
"User-Agent": "northwind-app/1.0",
},
method="POST",
)
with urllib.request.urlopen(req) as res:
message = json.load(res)
print(res.status, message["id"], message["status"], message["price"])<?php
// PHP 7.4 or newer with the curl extension
$ch = curl_init("https://bulksmsapi.cc/v1/messages");
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
"Authorization: Bearer " . getenv("BULKSMSAPI_KEY"),
"Content-Type: application/json",
],
CURLOPT_POSTFIELDS => json_encode([
"to" => "+14155550123",
"text" => "Your Northwind code is 482913. It expires in 10 minutes.",
"reference" => "login-7781",
]),
]);
$message = json_decode(curl_exec($ch), true);
echo curl_getinfo($ch, CURLINFO_HTTP_CODE), " ", $message["id"], " ", $message["status"], "\n";// Go 1.20 or newer, standard library only
package main
import (
"bytes"
"encoding/json"
"fmt"
"net/http"
"os"
)
func main() {
body, _ := json.Marshal(map[string]any{
"to": "+14155550123",
"text": "Your Northwind code is 482913. It expires in 10 minutes.",
"reference": "login-7781",
})
req, _ := http.NewRequest("POST", "https://bulksmsapi.cc/v1/messages", bytes.NewReader(body))
req.Header.Set("Authorization", "Bearer "+os.Getenv("BULKSMSAPI_KEY"))
req.Header.Set("Content-Type", "application/json")
res, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer res.Body.Close()
var message map[string]any
json.NewDecoder(res.Body).Decode(&message)
fmt.Println(res.StatusCode, message["id"], message["status"], message["price"])
}{
"id": "msg_8F3K2Q9TZ1MX",
"object": "message",
"batch_id": "bat_4M7Q1X0PK2RS",
"to": "+14155550123",
"country": "US",
"text": "Your Northwind code is 482913. It expires in 10 minutes.",
"segments": 1,
"price": "0.00507",
"currency": "USD",
"status": "queued",
"error": null,
"reference": "login-7781",
"created_at": "2026-11-07T09:30:12.418Z",
"sent_at": null,
"done_at": null
}Cómo se mueve un mensaje
Los mensajes aceptados quedan queued (o scheduled si la solicitud tiene send_at). La cola los entrega a la red cada dos segundos, hasta 1,200 por minuto por cuenta, y pasan a sent. El estado final es delivered o failed; un mensaje fallido se reembolsa al saldo de inmediato. Cada estado final activa tu webhook con un evento firmado.
Límites a simple vista
| Límite | Valor |
|---|---|
| Destinatarios por solicitud API | 10,000 |
| Destinatarios por campaña en consola | 50,000 |
| Solicitudes por minuto por clave | 600 |
| Mensajes entregados a la red por minuto por cuenta | 1,200 |
| Texto más largo | 10 segmentos (1,530 caracteres GSM-7 o 670 UCS-2) |
| Ventana de programación | Desde 2 minutos hasta 45 días adelante |
| Intentos de webhook por evento | 10 |
| Memoria de Idempotency-Key | 24 horas |
| Claves API por cuenta | 10 |
Archivos legibles por máquina
- Especificación OpenAPI 3.1 para generadores de código y clientes API.
- llms-full.txt: esta referencia completa en un archivo de texto plano.
- Cada página de documentación en Markdown, por ejemplo /en/docs/webhooks.md.