Développeurs

Référence API

Un point d'accès pour l'envoi, un pour lire le statut, des webhooks signés HMAC pour les accusés de réception. Les clés sont délivrées dès que le compte existe — rien à approuver, personne à contacter par e-mail.

v1https://api.worldsms.io/v1

Démarrage

Trois choses séparent un nouveau compte d'un message distribué : un jeton, du crédit et une clé. Aucune n'implique un humain.

  1. Créez un compte — votre navigateur génère le jeton, et ce jeton est le compte.
  2. Alimentez-le. $40 minimum, dans n'importe laquelle des cryptos sur la page des paiements.
  3. Créez une clé API dans le tableau de bord. Elle est affichée une seule fois ; nous ne stockons que son hash, exactement comme le jeton.

Une clé sur un solde vide ne peut pas envoyer

La création de clé est délibérément conditionnée à un compte alimenté. Un identifiant inutilisé qui traîne est un risque sans contrepartie, le tableau de bord n'en génère donc aucun tant qu'il n'y a rien à dépenser.

Authentification

Un jeton porteur à chaque requête. La clé identifie le compte ; il n'y a ni second facteur, ni signature de la requête, ni liste blanche d'IP — la clé est l'identifiant complet, traitez-la comme telle.

Authorization
Authorization: Bearer ws_live_9f2c…
TransportHTTPS uniquement. Une requête en HTTP simple est refusée, pas redirigée — une redirection aurait déjà divulgué la clé.
PortéeUne clé dépense le solde d'un seul compte. Créez une clé par système qui envoie, afin qu'une fuite soit révoquée de façon ciblée.
RévocationImmédiat. Une clé révoquée renvoie 401 à la prochaine requête ; les lots en cours déjà acceptés se terminent quand même.
RécupérationAucune. Nous conservons un hachage. Une clé perdue est remplacée, jamais récupérée.

Envoyer des messages

POST/v1/messages

Un seul appel, un ou plusieurs destinataires, des destinations mixtes. Chaque destinataire est facturé au tarif de sa propre destination, par segment. L'appel est accepté ou refusé dans son ensemble ; il ne vous facture jamais partiellement.

Corps de la requête

ChampTypeNotes
tostring[]Obligatoire. E.164, jusqu'à 5 000 par appel. Les numéros qui ne correspondent à aucune destination tarifée sont rejetés avant facturation.
textstringObligatoire. UTF-8. Le nombre de segments suit la norme GSM 03.38 — voir segments.
fromstringID expéditeur alphanumérique, jusqu'à 11 caractères. Transmis là où la route le permet ; voir ID expéditeur.
varsobject[]Valeurs de fusion facultatives, un objet par destinataire, substituées dans les emplacements {{name}} avant le comptage des segments.
callback_urlstringRemplacement optionnel du webhook de compte, par lot.
referencestringFacultatif. Renvoyé sur chaque accusé de réception afin de le relier à vos propres registres.

Exemple

send.sh
# one call, many recipients, mixed destinations
curl -X POST https://api.worldsms.io/v1/messages \
  -H "Authorization: Bearer $WORLDSMS_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "from": "ACME",
    "to":   ["+447700900123", "+33612345678"],
    "text": "Your code is 480913"
  }'
202 Accepted
{
  "batch_id": "b_7Kq2xR9wLm",
  "accepted": 2,
  "rejected": 0,
  "segments": 1,
  "cost_usd": 0.0353
}

0,0137 $ vers le Royaume-Uni plus 0,0216 $ vers la France — la grille tarifaire appliquée par destination, et non une moyenne mélangée.

Groupement

Un lot est accepté immédiatement et s'écoule à raison de 200 messages par minute et par compte, donc 50 000 destinataires prennent environ 4 h 10 min. Un trafic urgent ne devrait pas attendre derrière un envoi marketing : utilisez une clé distincte pour cela.

Statut du message

GET/v1/messages/{batch_id}

L'interrogation périodique est prise en charge et limitée en débit ; les webhooks sont la voie prévue. La réponse regroupe le lot et liste l'état par destinataire.

200 OK
{
  "batch_id":    "b_7Kq2xR9wLm",
  "status":      "done",
  "sending":     0,
  "delivered":   1,
  "undelivered": 1,
  "refund_usd":  0.0216
}

refund_usd est réglé une seule fois, à la fin du lot. Il est déjà de retour dans votre solde au moment où vous pouvez le lire.

Solde

GET/v1/balance

Vérifiez avant un envoi important. Les soldes sont conservés en interne sous forme de micro-dollars entiers — les tarifs vont jusqu'à quatre décimales, et un flottant n'a rien à faire dans un registre — et sont restitués ici arrondis à six décimales.

200 OK
{ "balance_usd": 412.905400, "currency": "USD" }

Accusés de réception

Un accusé est émis par destinataire au fur et à mesure que l'opérateur le signale. Ce sont les quatre seuls états ; il n'existe pas de catégorie « inconnu » qui signifierait discrètement « nous l'avons perdu ».

ÉtatSignificationFacturé
queuedAccepté et en attente de son tour dans le lot.Oui
sentRemis à l'opérateur, pas encore de confirmation.Oui
deliveredLe téléphone l'a confirmé.Oui
undeliveredHors service, barré, ou l'expéditeur a été refusé.Remboursé

Les numéros qui ne correspondent à aucune destination tarifée sont rejetés dès la soumission et n'entrent jamais dans ce cycle de vie — ils ne sont pas facturés puis remboursés, ils ne sont simplement jamais facturés.

Webhooks

Définissez un point de terminaison dans le tableau de bord ou par lot avec callback_url. Nous envoyons du JSON en POST et attendons un 2xx sous 5 secondes. Toute réponse hors 2xx est retentée six fois avec un backoff exponentiel sur environ une heure, puis abandonnée.

Charge utile

POST vers votre endpoint
{
  "event":     "message.delivered",
  "batch_id":  "b_7Kq2xR9wLm",
  "to":        "+447700900123",
  "destination": "gb",
  "segments":  1,
  "cost_usd":  0.0137,
  "reference": "order-4471",
  "ts":        1785312041
}

Vérification de la signature

Chaque distribution transporte X-WorldSMS-Signature et X-WorldSMS-Timestamp. La signature est HMAC-SHA256(timestamp + "." + body) en utilisant votre secret de webhook. Comparez en temps constant, et rejetez un horodatage vieux de plus de cinq minutes afin qu'une distribution interceptée ne puisse pas vous être rejouée plus tard.

verify.php
// $secret is the webhook secret from the dashboard
$raw  = file_get_contents('php://input');
$ts   = $_SERVER['HTTP_X_WORLDSMS_TIMESTAMP'] ?? '';
$sig  = $_SERVER['HTTP_X_WORLDSMS_SIGNATURE'] ?? '';

// A stale timestamp is a replay, however well it is signed.
if (abs(time() - (int) $ts) > 300) { http_response_code(408); exit; }

$mine = hash_hmac('sha256', $ts . '.' . $raw, $secret);
if (!hash_equals($mine, $sig)) { http_response_code(401); exit; }

http_response_code(204);

Être idempotent

Une nouvelle tentative après un délai d'expiration de votre point de terminaison est identique à une première distribution. Utilisez batch_id + to + event comme clé et traitez une répétition comme un no-op.

Erreurs

Chaque échec renvoie un corps JSON avec un identifiant error stable. Faites correspondre sur cet identifiant, jamais sur le texte — le texte est libre de s'améliorer.

HTTPSlugQue faire
400invalid_bodyJSON malformé ou champ requis manquant.
401key_rejectedClé absente, révoquée ou mal saisie. Non réessayable.
402insufficient_creditLe lot coûte plus que le solde. Rien n'a été envoyé ; rechargez et soumettez à nouveau.
422no_valid_recipientsAucun numéro n'a pu être résolu vers une destination tarifée.
422sender_id_invalidfrom comporte plus de 11 caractères ou contient une chaîne uniquement numérique qui serait lue comme un nombre.
429rate_limitedRalentissez. Retry-After indique le nombre de secondes.
503route_unavailableUne destination est temporairement inaccessible. Réessayable.
402 Payment Required
{
  "error":       "insufficient_credit",
  "message":     "Batch costs $84.20, balance is $12.05.",
  "required_usd": 84.20,
  "balance_usd":  12.05
}

Limites

Requêtes60 par minute et par clé, rafale de 20. 429 avec Retry-After au-delà.
Destinataires par appel5 000. Répartissez les listes plus longues sur plusieurs appels, ou importez le fichier dans le tableau de bord.
Taille du corps2 MB.
Débit200 messages par minute et par compte, quel que soit le nombre de clés qui envoient.
ClésAucune limite. Une par système d'envoi est le modèle prévu.

Les limites de débit s'appliquent aux appels API, pas aux messages : un appel transportant 5 000 destinataires compte pour une seule requête au regard de la limite.

Les clés sont délivrées instantanément. Aucune étape d'approbation.

Financez un compte et le tableau de bord en crée un sur-le-champ.

Poser une question précise

Créez votre compte

Un seul bouton. Votre navigateur génère un jeton de 160 bits, et ce jeton est le compte. Il n'y a rien d'autre à renseigner et personne à attendre.

FrançaisFR · Changer de langue

Langue