Envoyer un SMS par API : exemples Python, Node.js, PHP et cURL
Envoyer des SMS par API en Python, Node.js, PHP et cURL : envois unitaires et en masse, Unicode et arabe, segments, webhooks de statut et gestion d'erreurs.
Par OmniChannels.ai Editorial Team · Relu par BroadNet Messaging Solutions Team
Intégration
Réponse courte
Pour envoyer un SMS avec l'API OmniChannels.ai, effectuez un POST authentifié vers https://api.broadnet.me/sms/sendSms avec un corps JSON contenant senderId, destinationNumber, message et messageType. Utilisez TEXT pour du texte GSM-7 et UNICODE pour l'arabe ou les emojis. Une réponse 200 renvoie l'identifiant du message en texte brut, et le statut de livraison final arrive plus tard sur votre webhook.
Sur cette page
- Comment envoyer un SMS avec l'API ?
- Comment formater les numéros de téléphone ?
- Comment envoyer de l'arabe, des emojis ou d'autres textes Unicode ?
- Comment compter les segments avant l'envoi ?
- Comment envoyer à de nombreux numéros ?
- Comment recevoir le statut de livraison ?
- Comment gérer les erreurs et éviter les doublons ?
- Exemple concret : des codes de connexion pour une application régionale
- Quelles sont les erreurs courantes ?
- Comment OmniChannels.ai vous aide
Points clés
- POST /sms/sendSms exige quatre champs : senderId, destinationNumber, message et messageType ; le corps de la réponse est l'identifiant du message en texte brut, pas du JSON.
- Réglez messageType sur UNICODE pour l'arabe, les emojis ou tout caractère hors GSM-7 ; un seul de ces caractères fait passer tout le message en Unicode et raccourcit chaque segment.
- POST /sms/identify compte les caractères et les segments avant l'envoi, ce qui permet de prévoir le nombre de segments d'un message.
- La livraison est asynchrone : un 200 signifie « accepté », et DELIVERED, FAILED ou REJECTED arrive plus tard sur votre webhook.
- L'API n'a pas de clé d'idempotence : enregistrez chaque envoi avant de l'effectuer et vérifiez le statut après un délai d'attente dépassé plutôt que de renvoyer.
Ce guide s'adresse aux développeurs qui doivent envoyer des SMS depuis une application et veulent du code fonctionnel en Python, Node.js, PHP ou cURL. Il couvre un envoi unitaire, l'Unicode et l'arabe, le comptage des segments, l'envoi en masse par fichier, les webhooks de statut de livraison et la gestion des erreurs, en n'utilisant que les points de terminaison et champs de notre référence de l'API SMS et de la spécification OpenAPI.
Comment envoyer un SMS avec l'API ?
Effectuez un POST authentifié vers /sms/sendSms avec un corps JSON. La réponse est 200 OK avec l'identifiant du message en texte brut.
| Élément | Valeur |
|---|---|
| URL de base | https://api.broadnet.me (sans préfixe /v1) |
| Point de terminaison | POST /sms/sendSms |
| Authentification | Authorization: Bearer $BROADNET_TOKEN |
| Type de contenu | application/json |
| Champs obligatoires | senderId, destinationNumber, message, messageType |
Les identifiants de test sont délivrés après une brève demande d'accès, et les envois de test partent vers vos propres numéros vérifiés. Il n'existe pas d'inscription instantanée en libre-service. Voir le démarrage rapide.
curl -X POST https://api.broadnet.me/sms/sendSms \
-H "Authorization: Bearer $BROADNET_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"senderId": "OmniDemo",
"destinationNumber": "447700900123",
"message": "Your OmniDemo code is 482913",
"messageType": "TEXT"
}'
// Node.js 18+ (fetch intégré)
const res = await fetch("https://api.broadnet.me/sms/sendSms", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.BROADNET_TOKEN}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
senderId: "OmniDemo",
destinationNumber: "447700900123",
message: "Your OmniDemo code is 482913",
messageType: "TEXT",
}),
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
const messageId = await res.text(); // identifiant du message en texte brut
import os
import requests
r = requests.post(
"https://api.broadnet.me/sms/sendSms",
headers={"Authorization": f"Bearer {os.environ['BROADNET_TOKEN']}"},
json={
"senderId": "OmniDemo",
"destinationNumber": "447700900123",
"message": "Your OmniDemo code is 482913",
"messageType": "TEXT",
},
timeout=15,
)
r.raise_for_status()
message_id = r.text # identifiant du message en texte brut, pas du JSON
<?php
$payload = json_encode([
"senderId" => "OmniDemo",
"destinationNumber" => "447700900123",
"message" => "Your OmniDemo code is 482913",
"messageType" => "TEXT",
]);
$ch = curl_init("https://api.broadnet.me/sms/sendSms");
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 15,
CURLOPT_HTTPHEADER => [
"Authorization: Bearer " . getenv("BROADNET_TOKEN"),
"Content-Type: application/json",
],
CURLOPT_POSTFIELDS => $payload,
]);
$messageId = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
curl_close($ch);
echo $status . " " . $messageId . PHP_EOL;
Le corps d'une réponse réussie ressemble à ceci :
2603121407537573731
Conservez cet identifiant avec votre propre enregistrement, par exemple une commande ou une tentative de connexion. C'est lui qui permet de rapprocher les statuts de livraison par la suite.
Comment formater les numéros de téléphone ?
Utilisez l'indicatif pays suivi du numéro national, uniquement des chiffres. Le format suit le plan de numérotation international de l'ITU-T E.164, sans le signe plus.
| Saisie | Valide ? | Pourquoi |
|---|---|---|
447700900123 |
Oui | Indicatif 44 plus numéro national |
+44 7700 900123 |
Non | Retirez le signe plus et les espaces |
07700900123 |
Non | Remplacez le 0 initial par l'indicatif pays |
Stockez les numéros au format E.164 (+447700900123) dans votre base de données et retirez le + au moment de construire la requête. Notre outil gratuit de formatage de numéros permet une vérification rapide.
Comment envoyer de l'arabe, des emojis ou d'autres textes Unicode ?
Réglez messageType sur UNICODE. Tout caractère hors de l'alphabet GSM-7, comme une lettre arabe, un emoji, un guillemet typographique ou un tiret cadratin, fait basculer tout le message en Unicode.
r = requests.post(
"https://api.broadnet.me/sms/sendSms",
headers={"Authorization": f"Bearer {os.environ['BROADNET_TOKEN']}"},
json={
"senderId": "OmniDemo",
"destinationNumber": "971500000000",
"message": "رمز التحقق الخاص بك هو 482913",
"messageType": "UNICODE",
"campaignName": "login-otp",
},
timeout=15,
)
En PHP, utilisez JSON_UNESCAPED_UNICODE lorsque vous appelez json_encode. L'encodage détermine la taille des segments, telle que définie pour le SMS dans la norme 3GPP TS 23.040 :
messageType |
SMS unique | Par segment en cas de découpage | À utiliser pour |
|---|---|---|---|
TEXT |
160 caractères | 153 caractères | Texte n'utilisant que l'alphabet GSM-7 |
UNICODE |
70 caractères | 67 caractères | Arabe, cyrillique, chinois, emojis |
La plupart des opérateurs facturent au segment : un long message en arabe coûte donc plus cher que le même texte en écriture latine. Lisez notre guide du SMS Unicode et arabe et essayez le compteur de caractères SMS.
Comment compter les segments avant l'envoi ?
Appelez POST /sms/identify avec le message. Il renvoie l'encodage détecté, le nombre de caractères, le nombre de segments et la limite par segment.
curl -X POST https://api.broadnet.me/sms/identify \
-H "Authorization: Bearer $BROADNET_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "message": "Your OmniDemo code is 482913" }'
{
"message": "Your OmniDemo code is 482913",
"messageType": "TEXT",
"smscount": 1,
"charCount": 28,
"charLimit": 160
}
Vous pouvez transmettre smsParts (issu de smscount), charCount et charLimit dans une requête d'envoi. Le texte GSM-7 peut être étiqueté GSM-7 dans la réponse ; envoyez-le en TEXT.
Comment envoyer à de nombreux numéros ?
Utilisez POST /sms/sendbulk, une requête multipart/form-data avec un fichier de destinataires et une chaîne JSON de paramètres.
curl -X POST https://api.broadnet.me/sms/sendbulk \
-H "Authorization: Bearer $BROADNET_TOKEN" \
-F destinationNumberFile=@recipients.csv \
-F 'bulkRequest={"senderId":"OmniDemo","message":"Your statement is ready in the app.","messageType":"TEXT","campaignName":"oct-statements","allowDuplicate":false}'
import json
import os
import requests
bulk_request = {
"senderId": "OmniDemo",
"message": "Your statement is ready in the app.",
"messageType": "TEXT",
"campaignName": "oct-statements",
"allowDuplicate": False,
}
with open("recipients.csv", "rb") as f:
r = requests.post(
"https://api.broadnet.me/sms/sendbulk",
headers={"Authorization": f"Bearer {os.environ['BROADNET_TOKEN']}"},
files={"destinationNumberFile": ("recipients.csv", f, "text/csv")},
data={"bulkRequest": json.dumps(bulk_request)},
timeout=60,
)
print(r.json())
La réponse comprend bulkSessionId et un objet bulkListInfo avec total, validCount, invalidCount et duplicate. Stockez bulkSessionId avec la campagne. Les tâches peuvent être listées, mises en pause, reprises et abandonnées via les points de terminaison de la référence. Vous pouvez aussi vérifier les numéros avant un gros envoi avec POST /sms/lookup ; voir notre guide du HLR lookup.
Comment recevoir le statut de livraison ?
Les statuts de livraison sont poussés vers l'URL de webhook configurée sur votre compte. Un message passe par SUBMITTED et SENT jusqu'à DELIVERED, ou se termine en FAILED ou REJECTED. Vous communiquez à notre équipe l'URL HTTPS publique, et les revendeurs peuvent avoir un webhook par sous-compte.
Les champs de la charge utile varient selon le canal et la spécification de l'API ne définit pas de schéma de webhook unique : journalisez d'abord le corps brut et associez les champs à partir d'un événement réel de votre compte. Un récepteur minimal stocke l'événement et accuse réception rapidement :
import express from "express";
const app = express();
app.post("/webhooks/omnichannels", express.json(), async (req, res) => {
await saveStatusEvent(req.body); // votre stockage ; traitement asynchrone
res.sendStatus(200); // accuser réception rapidement
});
app.listen(3000);
Rendez le traitement idempotent, car le même statut peut arriver deux fois, et ne laissez jamais un SENT tardif écraser un DELIVERED déjà stocké. Si votre point de terminaison était indisponible, POST /sms/resendDlr renvoie les accusés pour une plage de dates :
curl -X POST https://api.broadnet.me/sms/resendDlr \
-H "Authorization: Bearer $BROADNET_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"startDate": "2026-10-09",
"endDate": "2026-10-10",
"senderId": "OmniDemo",
"messageStatus": "DELIVERED"
}'
Pour en savoir plus, consultez le guide des webhooks et les statuts de livraison des messages expliqués.
Comment gérer les erreurs et éviter les doublons ?
Traitez d'abord le statut HTTP, puis le corps de l'erreur. Ne réessayez que sur les erreurs réseau, 429 et 5xx.
| Code | Signification | Action |
|---|---|---|
200 |
Accepté | Stocker l'identifiant |
400 |
Erreur de validation ou champ manquant | Corriger la requête |
401 / 403 |
Jeton invalide ou opération non autorisée | Corriger ; ne pas réessayer |
429 |
Limite de débit dépassée | Attendre Retry-After |
500, 503, 504 |
Problème de serveur ou en amont | Réessayer avec backoff et jitter |
Les erreurs levées par l'API utilisent un corps JSON à cinq champs : status, error, message, errorCode et requestUri. La limite REST documentée par défaut est de 200 requêtes par seconde en continu ; les limites de votre compte sont confirmées avec vos identifiants.
L'API n'accepte aucune clé d'idempotence. Une requête peut aboutir alors que sa réponse est perdue, et un nouvel essai à l'aveugle envoie alors deux fois. Écrivez une ligne « en attente » portant votre propre identifiant d'opération avant l'appel, stockez l'identifiant de message renvoyé et, après un délai d'attente dépassé, cherchez un statut de webhook avant de renvoyer. Pour les envois en masse, réglez allowDuplicate sur false. Les détails figurent dans Erreurs et limites.
Exemple concret : des codes de connexion pour une application régionale
« Souq Rafiq » (société fictive), enseigne de distribution aux Émirats arabes unis, envoie des codes de connexion par SMS.
- Le service d'authentification génère un code à six chiffres, stocke un hash avec une expiration de cinq minutes et écrit une ligne d'envoi
pending. - Il appelle
/sms/sendSmsavecmessageType=UNICODEpour les utilisateurs arabophones etTEXTpour les anglophones. - Sur un
200, il stocke l'identifiant du message. - Le gestionnaire de webhook marque la ligne
DELIVERED,FAILEDouREJECTED. - Si le statut n'est pas
DELIVEREDaprès une courte attente, l'application propose un renvoi et, si c'est configuré, un autre canal. Voir le repli entre canaux. - Des limites sur les demandes de code par numéro et par IP protègent contre les abus ; voir prévention du SMS pumping.
Quelles sont les erreurs courantes ?
- Appeler
r.json()sur la réponse d'envoi. C'est du texte brut. - Mauvais noms de champs. Utilisez
senderId,destinationNumberetmessage; des champs commeto,fromoutextne font pas partie de ce point de terminaison. - Signes plus et zéros initiaux dans les numéros.
- Oublier
UNICODEpour l'arabe, ce qui déforme le texte. - Sender ID non enregistrés. Certains pays les bloquent ou les remplacent ; consultez les règles de sender ID de votre destination et demandez-nous de gérer l'enregistrement.
- Considérer
200comme « délivré ». - Jeton dans une application mobile ou un navigateur, où n'importe qui peut l'extraire.
- Limites : ce guide présente la requête courante. Les champs facultatifs comme les formats de planification doivent être confirmés avec notre équipe.
Comment OmniChannels.ai vous aide
OmniChannels.ai envoie du SMS A2P via la connectivité opérateur directe de BroadNet, avec SMS bidirectionnel, sender ID, Unicode et arabe, HLR lookup et SMPP 3.4 pour les volumes élevés. L'API REST disponible sur https://api.broadnet.me utilise un jeton Bearer et couvre aussi WhatsApp, RCS et d'autres canaux, avec des statuts de livraison normalisés dans un format de webhook unique. Notre équipe prépare avec vous les enregistrements de sender ID. Consultez la référence de l'API SMS ou le canal SMS.
Questions fréquentes
Comment envoyer un SMS avec Python ?
Utilisez la bibliothèque requests pour envoyer en POST du JSON vers https://api.broadnet.me/sms/sendSms avec un en-tête Authorization: Bearer et les champs senderId, destinationNumber, message et messageType. Lisez le jeton dans une variable d'environnement. Le corps d'une réponse 200 est l'identifiant du message en texte brut : utilisez donc r.text plutôt que r.json().
Quel format de numéro de téléphone l'API SMS attend-elle ?
L'indicatif pays suivi du numéro national, uniquement des chiffres, sans signe plus, sans préfixe 00, sans espaces ni zéro initial. Par exemple, 447700900123 est valide, alors que +44 7700 900123 et 07700900123 ne le sont pas. Stockez les numéros au format E.164 dans votre base de données et retirez le signe plus au moment de construire la requête.
Comment envoyer un SMS en arabe via l'API ?
Réglez messageType sur UNICODE et envoyez le texte arabe dans le champ message en UTF-8. Les messages Unicode contiennent 70 caractères dans un segment unique et 67 par segment lorsqu'ils sont découpés, contre 160 et 153 en GSM-7. Testez sur de vrais téléphones et appelez d'abord /sms/identify pour connaître le nombre de segments.
Comment obtenir les accusés de livraison ?
Les statuts sont poussés vers l'URL de webhook configurée sur votre compte. Les messages passent par SUBMITTED et SENT avant d'arriver à DELIVERED, FAILED ou REJECTED. Votre point de terminaison doit stocker l'événement brut, répondre rapidement en 2xx et traiter de façon asynchrone. Si des événements ont été manqués, POST /sms/resendDlr peut renvoyer les accusés pour une plage de dates.
Comment envoyer un SMS à de nombreux numéros à la fois ?
Utilisez POST /sms/sendbulk, une requête multipart avec un destinationNumberFile (CSV ou TXT) et une chaîne JSON bulkRequest contenant senderId, message et messageType. La réponse indique combien de numéros étaient valides, invalides ou en doublon, et renvoie un bulkSessionId que vous pouvez stocker avec votre campagne.
Faut-il enregistrer un sender ID ?
Dans de nombreux pays, oui. Certains exigent un sender ID alphanumérique approuvé, d'autres des identifiants de régulateur ou de modèle, que l'API accepte dans des champs facultatifs comme peId et templateId. Les exigences dépendent du pays : consultez la page sender ID de votre destination, et notre équipe peut s'occuper de l'enregistrement avec vous.
Sources
À lire aussi
Autres guidesIntégration
Envoyer un message WhatsApp par API : cURL, Node, Python, PHP
Comment envoyer un message WhatsApp par API : exemples cURL, Node.js, Python et PHP pour les modèles et les messages de session, suivi des statuts et erreurs.
10 min de lecture
Intégration
Choisir une API de messagerie : la checklist du CTO
Choisir une API de messagerie : checklist CTO sur les canaux, la qualité des routes, les webhooks, la sécurité, les limites, SMPP, MCP, la conformité et les prix.
13 min de lecture
SMS et OTP
Choisir un fournisseur de SMS en masse : checklist en 12 points
Choisir un fournisseur de SMS en masse : 12 contrôles sur routes, accusés de livraison, sender ID, tarifs, support et conformité, et un plan de test.
10 min de lecture
