Riferimento API SMS Bulk

L'API REST di BulkSMSOnline invia messaggi di testo in 227 paesi dal tuo software, con gli stessi prezzi, regole dei segmenti, pianificazione e rimborsi della console. Richieste e risposte sono in JSON su HTTPS, e ogni stato di consegna finale può essere inviato al tuo server come webhook firmato.

URL basehttps://bulksmsonline.cc/api/v1

Panoramica

Usa l'API quando i messaggi sono attivati dai tuoi sistemi: aggiornamenti ordini da un negozio, codici da un modulo di accesso, promemoria da uno strumento di prenotazione. Una richiesta a POST /v1/messages con fino a 10,000 numeri crea una campagna, addebita il saldo e accoda ogni messaggio. Le campagne create tramite API appaiono anche nella console con i loro rapporti di consegna.

  • Tutti gli importi sono in dollari USA come stringhe con cinque decimali, ad esempio "0.00534".
  • I numeri di telefono sono internazionali, con o senza il prefisso +; spazi e trattini vengono rimossi.
  • Gli orari sono in formato ISO 8601 in UTC, ad esempio 2026-12-01T09:00:00Z.
  • Gli ID messaggio e campagna hanno un aspetto simile a MSG-XXXX-XXXX-XXXX e CMP-XXXX-XXXX-XXXX.

Autenticazione

Crea una chiave API nella sezione API della console (le chiavi si sbloccano dopo il primo ricarico). Inviarla nell'header Authorization di ogni richiesta. Una chiave ha un aspetto simile a bso_api_ seguito da 36 caratteri; viene mostrata una sola volta, quindi conservala come segreto sul tuo server. Creare una nuova chiave sostituisce immediatamente la precedente.

Authorization: Bearer bso_api_0123456789abcdef0123456789abcdef0123
Content-Type: application/json

Limiti

Richieste300 al minuto per chiave; di più risponde 429 rate_limited
Numeri per richiesta10,000
Testo messaggio2,000 caratteri così come scritti, fino a 10 segmenti
Pianificazionesend_at da 5 minuti a 60 giorni nel futuro
Velocità di invio400 messaggi al minuto per coda
Tentativi webhook9 tentativi in circa 22 ore

Invia messaggi

POST/v1/messages

Invia un testo a uno o più numeri. Il costo totale viene prelevato dal saldo quando la richiesta è accettata; ogni messaggio non consegnabile viene rimborsato successivamente. La risposta ha stato 201 e la campagna con ogni messaggio.

CampoDescrizione
toobbligatorioUn numero o un array fino a 10,000 numeri in formato internazionale. I numeri ripetuti vengono inviati una volta; quelli illeggibili sono elencati in skipped.
textobbligatorioIl messaggio, fino a 2,000 caratteri e 10 segmenti. Il testo GSM-7 contiene 160 caratteri per SMS, Unicode 70.
send_atopzionaleOra ISO 8601 per programmare l'invio, da 5 minuti a 60 giorni nel futuro. Ometti per inviare ora.
opt_outopzionaletrue aggiunge la tua riga di opt-out dalle impostazioni della console su una nuova riga alla fine.
client_refopzionaleIl tuo riferimento personale, fino a 64 lettere, cifre e _ . : -. Viene restituito nei report e nei webhook.
curl -X POST https://bulksmsonline.cc/api/v1/messages \
  -H "Authorization: Bearer $BSO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"to":["+447700900412","+33612345678"],"text":"Order 4521 has shipped. Track it at shop.example/t/4521","client_ref":"order-4521"}'
HTTP/1.1 201 Created
{
  "id": "CMP-7KQ2-M9XA-4HTD",
  "status": "sending",
  "channel": "api",
  "recipients": 2,
  "segments": 1,
  "encoding": "GSM-7",
  "cost": "0.02158",
  "refunded": "0.00000",
  "client_ref": "order-4521",
  "send_at": null,
  "counts": { "queued": 2, "submitted": 0, "delivered": 0, "failed": 0, "canceled": 0 },
  "skipped": [],
  "balance": "118.43120",
  "messages": [
    { "id": "MSG-3RTW-81KD-ZQ0P", "to": "+447700900412", "country": "GB", "segments": 1, "price": "0.00834", "status": "queued" },
    { "id": "MSG-5HNA-4C2E-7YVB", "to": "+33612345678", "country": "FR", "segments": 1, "price": "0.01324", "status": "queued" }
  ]
}

Preventivo invio

POST/v1/quote

Prende lo stesso corpo di /v1/messages e restituisce il costo esatto, i segmenti e la codifica senza inviare o addebitare nulla. Usalo per mostrare un prezzo ai tuoi utenti prima che confermino.

{
  "recipients": 2,
  "skipped": [],
  "segments": 1,
  "encoding": "GSM-7",
  "cost": "0.02158",
  "balance": "118.45278",
  "countries": [ { "country": "GB", "recipients": 1, "cost": "0.00834" }, { "country": "FR", "recipients": 1, "cost": "0.01324" } ]
}

Saldo

GET/v1/balance

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

Tariffe

GET/v1/rates

GET/v1/rates/{country}

Il prezzo di un segmento SMS per ogni destinazione, o per un codice paese ISO di due lettere. Questi due endpoint sono pubblici e non richiedono una chiave.

{ "country": "DE", "name": "Germany", "calling_code": "+49", "price": "0.01544", "currency": "USD", "per": "segment" }

Stato messaggio

GET/v1/messages/{id}

{
  "id": "MSG-3RTW-81KD-ZQ0P",
  "campaign_id": "CMP-7KQ2-M9XA-4HTD",
  "to": "+447700900412",
  "country": "GB",
  "segments": 1,
  "price": "0.00834",
  "status": "delivered",
  "error": null,
  "created_at": "2026-11-07T09:00:02Z",
  "submitted_at": "2026-11-07T09:00:03Z",
  "final_at": "2026-11-07T09:00:08Z"
}

Campagne

GET/v1/campaigns/{id}

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

Il primo restituisce la campagna con i suoi conteggi per stato; il secondo sfoglia i suoi messaggi, fino a 1.000 per pagina. Le campagne inviate dalla console possono essere lette allo stesso modo con l'id mostrato sulla loro pagina.

Annulla invio programmato

POST/v1/campaigns/{id}/cancel

Interrompe una campagna creata con send_at e non ancora iniziata. Ogni messaggio viene annullato e il costo totale torna al saldo. Una campagna già in invio risponde 409 not_scheduled.

Webhook di consegna

Aggiungi un URL HTTPS sotto API nella console per ricevere ogni stato finale (consegnato o fallito) come richiesta POST. Rispondi con qualsiasi stato 2xx entro 8 secondi. Altre risposte e timeout vengono ritentati dopo 20 secondi, 1, 5 e 15 minuti, poi 1, 3, 6 e 12 ore, 9 tentativi in totale. Lo stesso evento può arrivare due volte, quindi usa event_id per elaborarlo una sola volta.

POST https://your-server.example/sms-status
Content-Type: application/json
X-BulkSMSOnline-Signature: t=1794042008,v1=5f0c2a...e91b

{
  "type": "message.status",
  "event_id": "ev_8f1c22d0a4b97e63c1f0",
  "sent_at": "2026-11-07T09:00:09Z",
  "data": {
    "message_id": "MSG-3RTW-81KD-ZQ0P",
    "campaign_id": "CMP-7KQ2-M9XA-4HTD",
    "to": "+447700900412",
    "country": "GB",
    "status": "delivered",
    "error": null,
    "segments": 1,
    "price": "0.00834",
    "currency": "USD",
    "client_ref": "order-4521",
    "final_at": "2026-11-07T09:00:08Z"
  }
}

Verifica la firma

L'header contiene il tempo Unix t e la firma v1 = HMAC-SHA256 della stringa "t.raw_body" con il tuo segreto webhook, in esadecimale. Calcolalo sul corpo grezzo prima di analizzare il JSON, confronta in tempo costante e rifiuta eventi più vecchi di cinque minuti.

import crypto from "node:crypto";

export function verify(rawBody, 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 = crypto.createHmac("sha256", secret).update(m[1] + "." + rawBody).digest("hex");
  return crypto.timingSafeEqual(Buffer.from(want), Buffer.from(m[2]));
}

Stati

queuedAccettato e in attesa di uscire dalla coda
submittedConsegnato alla rete di destinazione
deliveredConfermato dal dispositivo (finale)
failedImpossibile consegnare; il prezzo viene rimborsato (finale)
canceledParte di una campagna programmata annullata prima dell'invio (finale)

Lo stato della campagna è scheduled, sending, complete o canceled.

Errori

Gli errori rispondono con uno stato HTTP e un corpo JSON: { "error": { "code": "insufficient_balance", "message": "..." } }. Niente viene addebitato quando una richiesta risponde con un errore.

HTTPCodiceSignificato
400invalid_requestUn campo è mancante o non valido; il messaggio indica quale.
400invalid_jsonIl corpo non è JSON.
400no_valid_numbersNessuno dei numeri può essere letto.
401unauthorizedLa chiave è mancante, malformata o sostituita.
402insufficient_balanceIl saldo non copre il costo; ricarica e invia di nuovo.
404not_foundID o endpoint sconosciuto.
409not_scheduledSolo una campagna programmata che non è ancora iniziata può essere annullata.
413too_many_recipientsPiù di 10,000 numeri in una richiesta.
429rate_limitedPiù di 300 richieste in un minuto.
500server_errorRiprova la richiesta; non è stato addebitato nulla.

Ottieni una chiave API nella console

Crea un account, aggiungi la prima ricarica e genera una chiave in API. La tua prima richiesta può essere inviata un minuto dopo.

Crea account
Riferimento API SMS di massa: Endpoint REST e Webhook | BulkSMSOnline