Salta al contenuto
smsbulk

API SMS bulk v1

Una piccola API REST per l'invio di SMS in blocco dal tuo software: JSON in entrata e in uscita, chiavi Bearer, gli stessi prezzi e controlli della console e webhook firmati per i report di consegna. URL di base https://smsbulk.cc/rest/v1

Panoramica

Invia fino a 8,000 numeri per richiesta, ciascuno con i propri valori di unione, e l'API calcola il prezzo per ogni destinatario con il proprio testo unito, esattamente come nella console. Richiedi prima un preventivo con lo stesso corpo per conoscere il costo; nulla viene inviato o addebitato con un preventivo. Gli orari sono in formato ISO 8601 in UTC, il denaro è una stringa in dollari statunitensi con cinque decimali.

curl https://smsbulk.cc/rest/v1/send \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "recipients": [
      { "to": "+14155550142", "fields": { "name": "Maria" } },
      { "to": "+447400123456", "fields": { "name": "Tom" } }
    ],
    "text": "Hi {{name}}, your order ships today.",
    "client_ref": "order-batch-17"
  }'

Autenticazione

Crea una chiave nella console sotto API e webhook; le chiavi si attivano dopo il primo accredito. Inviarla in ogni richiesta come token Bearer. Una chiave viene mostrata una sola volta; puoi conservare fino a 5 chiavi e revocarne qualsiasi in qualsiasi momento.

Authorization: Bearer smsb_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

Tariffe

Pubblico, nessuna chiave necessaria. Il prezzo per segmento SMS per ogni destinazione, o per un codice ISO.

GEThttps://smsbulk.cc/rest/v1/rates

GEThttps://smsbulk.cc/rest/v1/rates/{ISO}

{
  "country": "US",
  "name": "United States",
  "dial_code": "+1",
  "rate": "0.00485",
  "currency": "USD",
  "per": "message segment"
}

Credito

GEThttps://smsbulk.cc/rest/v1/credit

{ "credit": "125.40000", "currency": "USD", "account": "A418820037715" }

Preventivo

Calcola il costo di un invio senza inviarlo. Accetta lo stesso corpo di Send.

POSThttps://smsbulk.cc/rest/v1/quote

CampoSignificato
toUn numero o una lista. La forma internazionale con + è la più sicura; i numeri locali necessitano di default_country.
recipientsInvece di to: una lista di { to, fields } dove fields riempie i campi di unione come {{name}}.
textIl messaggio, fino a 2,000 caratteri e 10 segmenti dopo l'unione.
default_countryCodice ISO utilizzato per i numeri scritti senza +, come GB. Ripiega sul valore predefinito salvato nelle Impostazioni.
opt_outAggiunge la tua frase di opt-out salvata come ultima riga (salvala prima nelle Impostazioni).
{
  "recipients": 2,
  "messages": 2,
  "segments": { "min": 1, "max": 1 },
  "encoding": "GSM-7",
  "total": "0.01240",
  "currency": "USD",
  "credit": "125.40000",
  "credit_after": "125.38760",
  "countries": [
    { "country": "US", "recipients": 1, "rate": "0.00485", "segments": 1, "subtotal": "0.00485" },
    { "country": "GB", "recipients": 1, "rate": "0.00755", "segments": 1, "subtotal": "0.00755" }
  ],
  "left_out": []
}

Invia

Crea una campagna, prende il totale dal tuo credito e mette in coda i messaggi. Risponde con 201 e la campagna. I numeri che non possono essere inviati sono elencati in left_out e non vengono mai addebitati.

POSThttps://smsbulk.cc/rest/v1/send

CampoSignificato
to / recipients / text / default_country / opt_outCome in Quote.
send_atOra ISO 8601 per iniziare, da 5 minuti a 90 giorni in anticipo. Ometti per inviare ora.
nameLa tua etichetta per la campagna, fino a 80 caratteri.
client_refIl tuo riferimento personale, fino a 64 caratteri, restituito in ogni messaggio e webhook.
HTTP/1.1 201 Created
{
  "campaign": {
    "id": "C507318264409",
    "name": null,
    "status": "sending",
    "source": "api",
    "test": false,
    "recipients": 2,
    "cost": "0.01240",
    "refunded": "0.00000",
    "net_cost": "0.01240",
    "currency": "USD",
    "send_at": null,
    "created_at": "2026-11-07T14:02:11.000Z",
    "started_at": "2026-11-07T14:02:11.000Z",
    "finished_at": null,
    "client_ref": "order-batch-17"
  },
  "messages": 2,
  "left_out": []
}

Campagne

GEThttps://smsbulk.cc/rest/v1/campaigns?limit=25&before={id}

GEThttps://smsbulk.cc/rest/v1/campaigns/{id}

GEThttps://smsbulk.cc/rest/v1/campaigns/{id}/messages?status=failed&limit=100&after={message id}

Una singola campagna include i conteggi per stato: in coda, inviato, consegnato, fallito e annullato. Elenco messaggi con paginazione dopo e has_more; fino a 1.000 per pagina.

Messaggi

GEThttps://smsbulk.cc/rest/v1/messages/{id}

GEThttps://smsbulk.cc/rest/v1/messages?to=%2B14155550142&status=delivered&client_ref=order-batch-17&limit=50

{
  "id": "M220947781305",
  "campaign": "C507318264409",
  "to": "+14155550142",
  "country": "US",
  "segments": 1,
  "encoding": "GSM-7",
  "price": "0.00485",
  "status": "delivered",
  "reason": null,
  "reason_text": null,
  "refunded": false,
  "client_ref": "order-batch-17",
  "created_at": "2026-11-07T14:02:11.000Z",
  "sent_at": "2026-11-07T14:02:12.000Z",
  "finished_at": "2026-11-07T14:02:16.000Z"
}

Annulla una campagna programmata

POSThttps://smsbulk.cc/rest/v1/campaigns/{id}/cancel

Funziona fino all'orario di inizio. L'intero costo viene restituito al tuo credito in una riga del registro e lo stato della campagna diventa annullato.

Webhook

Imposta un URL endpoint nella console. Inviamo JSON per message.delivered, message.failed e campaign.done, più un test quando premi Invia evento di test. Ogni evento porta quattro intestazioni e qualsiasi risposta 2xx entro 10 secondi viene considerata ricevuta.

CampoSignificato
Smsbulk-EventNome dell'evento, come message.delivered.
Smsbulk-DeliveryID di consegna, lo stesso per ogni tentativo di un evento.
Smsbulk-TimestampSecondi Unix quando questo tentativo è stato firmato.
Smsbulk-Signaturesha256= seguito dal base64 HMAC-SHA256 di timestamp, una nuova riga e il corpo grezzo, chiavato con il tuo segreto sbw_.

La consegna viene tentata 8 volte: subito, poi dopo 1 minuto, 5 minuti, 15 minuti, 1 ora, 3 ore, 6 ore e 12 ore. Ogni tentativo viene mostrato nel registro di consegna della console con il suo stato HTTP e l'inizio della tua risposta.

{
  "id": "dlv_3f9a1c07b2e44d58a6c1",
  "event": "message.failed",
  "created": "2026-11-07T14:02:16.000Z",
  "data": {
    "message": "M220947781305",
    "campaign": "C507318264409",
    "to": "+447400123456",
    "country": "GB",
    "status": "failed",
    "reason": "not_in_service",
    "segments": 1,
    "price": "0.00755",
    "client_ref": "order-batch-17"
  }
}

Verifica la firma

import crypto from "node:crypto";

// raw = the request body exactly as received (string), secret = your sbw_ signing secret
export function verify(raw, headers, secret) {
  const ts = headers["smsbulk-timestamp"];
  const want = "sha256=" + crypto.createHmac("sha256", secret).update(ts + "\n" + raw).digest("base64");
  const got = headers["smsbulk-signature"] || "";
  const fresh = Math.abs(Date.now() / 1000 - Number(ts)) < 300;
  return fresh && got.length === want.length && crypto.timingSafeEqual(Buffer.from(got), Buffer.from(want));
}

Errori e limiti

Gli errori utilizzano lo stato HTTP e un corpo JSON: {"error":{"code":"insufficient_credit","message":"..."}}. Non viene addebitato nulla quando una richiesta fallisce.

CampoSignificato
400 bad_jsonIl corpo non è JSON.
401 unauthorizedChiave mancante, malformata o revocata.
402 insufficient_creditL'importo totale supera il tuo credito. Aggiungi fondi nella console.
404 not_foundNessun endpoint, campagna, messaggio o codice ISO trovato su questo account.
409 not_scheduledÈ stata richiesta la cancellazione di una campagna già avviata.
422 text_missing, text_too_long, too_many_segmentsMessaggio vuoto, supera 2,000 caratteri o supera 10 segmenti per un destinatario.
422 no_recipients, too_many, recipients_missingNessun numero inviabile, più di 8,000 numeri, o nessun destinatario specificato.
422 schedule_range, bad_send_atsend_at fuori dall'intervallo di 5 minuti a 90 giorni, o non è un orario valido.
422 opt_out_unsetopt_out è vero ma non è stata salvata alcuna dicitura nelle Impostazioni.
429 rate_limitedPiù di 300 richieste in un minuto per questa chiave.

Ogni risposta include X-RateLimit-Limit, X-RateLimit-Remaining e X-RateLimit-Reset.

Codici esclusi

I numeri rimossi prima della determinazione del prezzo vengono restituiti in left_out con la loro posizione nella tua lista, il valore inviato, un codice e la ragione chiara.

CampoSignificato
no_country_codeNessun prefisso + e nessun paese predefinito.
too_short / too_longMeno di 8 o più di 15 cifre.
not_a_numberLettere o simboli che non fanno parte di un numero.
nanp_lengthUn numero +1 senza undici cifre.
not_coveredUna destinazione fuori dalla nostra lista.
duplicateLo stesso numero è apparso precedentemente nella richiesta.
suppressedIl numero è nella tua lista di non invio.

Stati e motivi

CampoSignificato
queuedIn attesa di lasciare la nostra coda.
sentConsegnato alla rete, in attesa del rapporto di consegna. La maggior parte dei rapporti arriva entro pochi minuti; alcune reti richiedono fino a 24 ore.
deliveredLa rete ha confermato che il telefono lo ha ricevuto.
failedNon consegnato. Il prezzo è stato rimborsato sul tuo credito.
canceledNon inviato perché hai annullato. Rimborsato.
CampoSignificato
network_errorErrore di rete
switched_offTelefono spento o fuori copertura
not_in_serviceNumero non in servizio
blockedBloccato dalla rete o dal destinatario
landlineNumero fisso o numero che non può ricevere SMS
content_filterRespinto dal filtro contenuti della rete
expiredScaduto: nessun report prima del limite di tempo della rete
unknownRisposta della rete sconosciuta
canceledAnnullato prima dell'invio

Domande sull'API? Apri un ticket nella console o leggi le FAQ.

Documentazione API Bulk SMS v1: Invia, Preventivo, Webhooks | SMSBulk