Développeurs

Documentation de l'API SMS en masse

L'API REST de SendBulkSMS envoie des SMS à 10,000 numéros par requête, renvoie immédiatement un ID de campagne et rapporte chaque message à votre webhook. Elle utilise JSON via HTTPS, une clé API Bearer et applique les mêmes tarifs par message que la console.

https://sendbulksms.cc/api/v1

Démarrage rapide

  1. Créez un compte et rechargez votre solde dans la console.
  2. Ouvrez Clés API et créez une clé. Les clés peuvent être créées après le premier rechargement crédité. La clé n'est affichée qu'une fois ; conservez-la comme un secret.
  3. Envoyez une requête POST à /sms avec les numéros et le texte. Lisez l'ID de campagne retourné, puis suivez la livraison dans la console ou via les webhooks.

Authentification

Chaque requête, sauf la liste publique des tarifs, contient votre clé dans l'en-tête Authorization. Les clés commencent par sbk_live_. Une nouvelle clé remplace immédiatement l'ancienne.

Authorization: Bearer sbk_live_YOUR_KEY

Envoyer un SMS

POST/sms

Crée une campagne, la facture depuis le solde et met chaque message en file d'attente. Les numéros sont nettoyés et dédoublonnés ; ceux qui ne peuvent pas être utilisés sont retournés dans dropped avec une raison et ne sont pas facturés.

ChampDescription
toobligatoireUn numéro ou un tableau de jusqu'à 10,000 numéros au format international, par exemple "+447700900461"
textobligatoireTexte du message, jusqu'à 10 segments. Le texte GSM-7 tient dans 160 caractères par segment, UCS-2 dans 70
schedule_atoptionnelHeure ISO 8601 de 5 minutes à 60 jours à l'avance. Omettez pour envoyer maintenant
client_refoptionnelVotre propre référence, jusqu'à 64 caractères parmi a-z A-Z 0-9 _ . : -, retournée dans les rapports et webhooks
opt_outoptionneltrue ajoute la mention de désinscription définie dans vos paramètres de compte
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"
  }'

Réponse : la campagne avec son coût et les 1 000 premiers messages. Récupérez plus avec les messages de campagne.

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 }
  ]
}

Estimer un envoi

POST/estimate

Prend le même corps que /sms et retourne les destinataires, segments, encodage, coût total et le coût par pays sans facturer ni envoyer quoi que ce soit.

{ "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" } ] }

Statut du message

GET/sms/{message_id}

Retourne un message : numéro, pays, segments, prix, statut, l'erreur pour les messages échoués et l'heure de chaque étape.

Campagnes

GET/campaigns/{campaign_id}

La campagne avec son coût, remboursements et un décompte des messages par statut.

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

Messages dans l'ordre où ils ont été mis en file d'attente, jusqu'à 1 000 par page.

POST/campaigns/{campaign_id}/cancel

Annule une campagne programmée qui n'a pas commencé et rembourse son coût intégral au solde.

Solde et tarifs

GET/balance

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

GET/rates

Public, aucune clé nécessaire. Chaque pays avec son indicatif et prix par segment. /rates/GB retourne un pays.

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

Webhooks de livraison

Définissez une URL de webhook dans la console sous Clés API. Quand un message atteint un statut final (livré ou échoué), nous POSTons un rapport dessus. Répondez avec n'importe quel statut 2xx dans les 8 secondes ; sinon l'appel est réessayé jusqu'à 8 fois sur environ 11 heures. Utilisez id pour ignorer un rapport déjà traité.

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"
  }
}

Vérifiez la signature avant de faire confiance à un rapport : HMAC-SHA256 de t + "." + raw body avec votre secret de webhook, comparé en temps constant, et rejetez les temps de plus de 5 minutes.

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);
}

Statuts

StatutSignification
queuedAccepté et facturé, en attente dans la file
sentTransmis à la route, en attente du rapport de remise
deliveredLe réseau a confirmé la livraison au terminal
failedNon livré ; le montant est remboursé et error contient la raison
canceledPartie d'une campagne planifiée annulée avant son début ; remboursé

Erreurs

Les erreurs utilisent des codes de statut HTTP et un corps JSON : { "error": { "code": "insufficient_balance", "message": "..." } }. Une requête renvoyant une erreur ne facture jamais le solde.

HTTPCode
400bad_requestUn champ est manquant ou invalide ; le message indique lequel
400no_valid_numbersAucun numéro dans "to" n'a pu être utilisé
401unauthorizedLa clé API est manquante ou invalide
402insufficient_balanceLe solde ne couvre pas l'envoi ; rien n'a été facturé
404not_foundLa campagne, le message ou le point de terminaison n'existe pas dans votre compte
409not_scheduledSeule une campagne planifiée non démarrée peut être annulée
413too_many_recipientsPlus de 10,000 numéros dans une requête
429rate_limitedPlus de 300 requêtes par minute pour cette clé
500server_errorRéessayez ; aucune facturation n'est effectuée pour une requête échouée

Limites

  • 300 requêtes par minute par clé API.
  • 10,000 numéros par requête d'envoi ; 10 segments par message.
  • Les messages partent à raison de 200 par minute maximum par file, dans l'ordre d'acceptation.
  • Planification de 5 minutes à 60 jours à l'avance.
  • Les numéros de votre liste d'exclusion sont ignorés et renvoyés dans dropped avec le code suppressed ; ils ne sont pas facturés.
Documentation de l'API SMS en masse : Envoyer des SMS avec une API REST | SendBulkSMS