Desarrolladores

Documentación de la API de SMS masivos

La API REST de SendBulkSMS envía SMS a 10,000 números por solicitud, devuelve un ID de campaña de inmediato y reporta cada mensaje a su webhook. Usa JSON sobre HTTPS, requiere una clave API Bearer y cobra las mismas tarifas por mensaje que la consola.

https://sendbulksms.cc/api/v1

Inicio rápido

  1. Crea una cuenta y recarga tu saldo en la consola.
  2. Abre Claves API y crea una clave. Las claves se pueden crear después de que se acredite la primera recarga. La clave se muestra una vez; guárdala como secreto.
  3. Envía una solicitud POST a /sms con los números y el texto. Lee el ID de campaña devuelto, luego sigue la entrega en la consola o a través de webhooks.

Autenticación

Cada solicitud, excepto la lista pública de tarifas, lleva tu clave en el encabezado Authorization. Las claves comienzan con sbk_live_. Una nueva clave reemplaza a la anterior inmediatamente.

Authorization: Bearer sbk_live_YOUR_KEY

Enviar SMS

POST/sms

Crea una campaña, la carga del saldo y pone en cola cada mensaje. Los números se limpian y desduplican; aquellos que no se pueden usar se devuelven en dropped con un motivo y no se cobran.

CampoDescripción
torequeridoUn número o un array de hasta 10,000 números en formato internacional, por ejemplo "+447700900461"
textrequeridoTexto del mensaje, hasta 10 segmentos. El texto GSM-7 cabe en 160 caracteres por segmento, UCS-2 en 70
schedule_atopcionalHora ISO 8601 desde 5 minutos hasta 60 días adelante. Omite para enviar ahora
client_refopcionalTu propia referencia, hasta 64 caracteres de a-z A-Z 0-9 _ . : -, devuelta en informes y webhooks
opt_outopcionaltrue añade la línea de baja configurada en los ajustes de tu cuenta
curl -X POST https://sendbulksms.cc/api/v1/sms \
  -H "Authorization: Bearer sbk_live_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "to": ["+447700900461", "+5511955550123"],
    "text": "Hi, your order 4821 ships today.",
    "client_ref": "orders-4821"
  }'

Respuesta: la campaña con su costo y los primeros 1,000 mensajes. Obtén más con los mensajes de la campaña.

HTTP/1.1 201 Created
{
  "id": "CP-7KQ2-M9XA-4HTD",
  "status": "sending",
  "source": "api",
  "recipients": 2,
  "segments": 1,
  "encoding": "GSM-7",
  "cost": "0.01078",
  "refunded": "0.00000",
  "client_ref": "orders-4821",
  "scheduled_at": null,
  "created_at": "2026-11-07T10:32:04.118Z",
  "done_at": null,
  "counts": { "queued": 2, "sent": 0, "delivered": 0, "failed": 0, "canceled": 0 },
  "dropped": [],
  "balance": "248.30422",
  "messages": [
    { "id": "SM-2RBW-8MZN-QF6K", "campaign_id": "CP-7KQ2-M9XA-4HTD", "to": "+447700900461", "country": "GB", "parts": 1, "price": "0.00819", "status": "queued", "error": null, "created_at": "2026-11-07T10:32:04.118Z", "sent_at": null, "done_at": null }
  ]
}

Estimar un envío

POST/estimate

Toma el mismo cuerpo que /sms y devuelve los destinatarios, segmentos, codificación, costo total y el costo por país sin cargar ni enviar nada.

{ "recipients": 2, "dropped": [], "segments": 1, "encoding": "GSM-7", "cost": "0.01078", "balance": "248.31500",
  "countries": [ { "country": "GB", "recipients": 1, "cost": "0.00819" }, { "country": "BR", "recipients": 1, "cost": "0.00259" } ] }

Estado del mensaje

GET/sms/{message_id}

Devuelve un mensaje: número, país, segmentos, precio, estado, el error para mensajes fallidos y la hora de cada paso.

Campañas

GET/campaigns/{campaign_id}

La campaña con su costo, reembolsos y un conteo de mensajes por estado.

GET/campaigns/{campaign_id}/messages?offset=0&limit=100

Mensajes en el orden en que se pusieron en cola, hasta 1,000 por página.

POST/campaigns/{campaign_id}/cancel

Cancela una campaña programada que no ha comenzado y reembolsa su costo completo al saldo.

Saldo y tarifas

GET/balance

{ "balance": "248.31500", "currency": "USD" }

GET/rates

Público, no se necesita clave. Cada país con su código de llamada y precio por segmento. /rates/GB devuelve un país.

{ "updated": "2026-11-07", "rates": [ { "country": "GB", "name": "United Kingdom", "calling_code": "+44", "price": "0.00819", "currency": "USD", "unit": "SMS segment" } ] }

Webhooks de entrega

Configura una URL de webhook en la consola bajo Claves API. Cuando un mensaje alcanza un estado final (entregado o fallido) hacemos un POST del informe a ella. Responde con cualquier estado 2xx en 8 segundos; de lo contrario, la llamada se reintenta hasta 8 veces en unas 11 horas. Usa id para ignorar un informe que ya hayas procesado.

POST https://your-server.example/sms-status
Content-Type: application/json
X-SendBulkSMS-Signature: t=1794047524,v1=5f0c3b9e...

{
  "event": "message.status",
  "id": "evt_8c1d2e4f6a7b9c0d1e2f",
  "created_at": "2026-11-07T10:32:09.004Z",
  "data": {
    "message_id": "SM-2RBW-8MZN-QF6K",
    "campaign_id": "CP-7KQ2-M9XA-4HTD",
    "to": "+447700900461",
    "country": "GB",
    "status": "delivered",
    "error": null,
    "parts": 1,
    "price": "0.00819",
    "client_ref": "orders-4821",
    "done_at": "2026-11-07T10:32:08.912Z"
  }
}

Verifica la firma antes de confiar en un informe: HMAC-SHA256 de t + "." + raw body con tu secreto de webhook, comparado en tiempo constante, y rechaza tiempos mayores de 5 minutos.

import { createHmac, timingSafeEqual } from "node:crypto";

// raw = the request body exactly as received (string), header = X-SendBulkSMS-Signature
export function verify(raw, header, secret) {
  const m = /^t=(\d+),v1=([0-9a-f]{64})$/.exec(header || "");
  if (!m || Math.abs(Date.now() / 1000 - Number(m[1])) > 300) return false;
  const want = Buffer.from(createHmac("sha256", secret).update(m[1] + "." + raw).digest("hex"));
  const got = Buffer.from(m[2]);
  return want.length === got.length && timingSafeEqual(want, got);
}

Estados

EstadoSignificado
queuedAceptado y cobrado, esperando su turno en la cola
sentEntregado a la ruta, esperando el informe de entrega
deliveredLa red confirmó la entrega al dispositivo
failedNo entregado; el precio es reembolsado y el error contiene la razón
canceledParte de una campaña programada cancelada antes de comenzar; reembolsado

Errores

Los errores usan códigos de estado HTTP y un cuerpo JSON: { "error": { "code": "insufficient_balance", "message": "..." } }. Una solicitud que devuelve un error nunca carga el saldo.

HTTPCódigo
400bad_requestFalta un campo o no es válido; el mensaje explica cuál
400no_valid_numbersNinguno de los números en "to" pudo ser utilizado
401unauthorizedFalta la clave API o no es válida
402insufficient_balanceEl saldo no cubre el envío; no se cobró nada
404not_foundLa campaña, mensaje o endpoint no existe en tu cuenta
409not_scheduledSolo se puede cancelar una campaña programada que no haya comenzado
413too_many_recipientsMás de 10,000 números en una solicitud
429rate_limitedMás de 300 solicitudes en un minuto para esta clave
500server_errorInténtalo de nuevo; no se cobra por una solicitud que falla

Límites

  • 300 solicitudes por minuto por clave API.
  • 10,000 números por solicitud de envío; 10 segmentos por mensaje.
  • Los mensajes se envían a un máximo de 200 por minuto por cola, en el orden en que fueron aceptados.
  • Programación desde 5 minutos hasta 60 días en adelante.
  • Los números en tu lista de no enviar se omiten y se devuelven en dropped con el código suppressed; no se cobran.
Documentación de la API de SMS Masivos: Envía SMS con una API REST | SendBulkSMS