Dépréciée

Référence API · v1

Documentation de l'API v1

Le contrat historique de FasterMessage, maintenu à l'identique pour les intégrations en place. Il ne reçoit plus d'évolution : tout nouveau développement se fait sur l'API v2.

Guide de migration V1 → V2

La v2 n'est pas une réécriture de surface : elle corrige trois défauts structurels de la v1 — l'enveloppe de succès, l'authentification par la barre d'adresse et l'absence d'identifiant de requête. La migration est mécanique, mais elle n'est pas transparente.

Correspondance des points d’entrée

API v1API v2Ce qui change
POST /v1/sms/sendPOST /v2/sms/sendtext devient content ; messageId devient client_reference ; la réponse n’est plus enveloppée.
GET /v1/sms/sendSupprimé. L’envoi en GET faisait transiter les identifiants par la barre d’adresse. Passer en POST.
GET /v1/sms/balanceGET /v2/balanceRenvoie désormais tous les canaux et la devise, au lieu d’un solde SMS nu.
GET /v2/messages/{id}Nouveau. Le suivi ne dépend plus du seul webhook.
POST /v2/sms/batchNouveau. 500 envois par appel, avec bilan par ligne.
POST /v2/messagesNouveau. Envoi unifié : WhatsApp, e-mail et voix par le même contrat.
GET /v1/pingGET /v2/pingInchangé — ouvert, sans identifiants.

Authentification

v1v2
Nombre d’identifiantsUn seul (au choix parmi cinq transports).Deux, tous deux exigés : Basic + X-Api-Key.
TransportEn-tête, query string ou corps.En-têtes uniquement.
EnvironnementAucune notion dans le contrat — mais une clé fm_test_ y simule comme en v2 : rien n’est remis ni débité.Déduit du préfixe de clé (fm_test_ / fm_live_).
Refus401 AUTHENTICATION_FAILED dans l’enveloppe.401 authentication_error, corps d’erreur normalisé.

Format de réponse

v1 — succès enveloppé
{
  "status": true,
  "code": "SUBMITTED",
  "description": "202: The request has been submitted and is being processed",
  "messageId": "cmd-42",
  "smsCount": 1
}
v2 — la ressource, nue
{
  "id": "msg_2f1c9d4e8a6b",
  "channel": "sms",
  "status": "queued",
  "to": "22960000000",
  "from": "FASTERMSG",
  "units": 1,
  "client_reference": "cmd-42",
  "created_at": "2026-09-07T10:00:00.000Z"
}
  • Le succès n'est plus enveloppé : c'est le code HTTP qui porte l'issue.
  • Les champs passent en snake_case — la v1 mélangeait camelCase et minuscules collées.
  • status change de nature : booléen d'enveloppe en v1, état du message en v2 (queued, delivered…).
  • smsCount devient units, et vaut pour les quatre canaux.
  • Toute réponse porte un X-Request-Id, à citer au support.

Ruptures de compatibilité

RuptureEffet si non traitéeÀ faire
status n’est plus un booléenUn test if (res.status) passe désormais sur une chaîne — donc toujours vrai.Tester le code HTTP, puis error.code.
Plus de champ code en succèsUn test code === "SUBMITTED" ne matche plus jamais.Tester status === "queued" sur la ressource.
Codes d’erreur renommésINSUFFICIENT_BALANCE devient insufficient_balance, sous error.Réécrire la table de correspondance des codes.
Identifiants en query refusésLes appels qui passaient la clé en URL échouent en 401.Basculer sur les en-têtes.
Envoi en GET supprimé404 sur GET /v2/sms/send.Passer en POST.
Format des webhooksLa charge utile v2 ne porte plus uuid ni level.Voir l’encart ci-dessous — vos rappels v1 ne changent pas.

Authentification

La v1 accepte cinq transports pour un même identifiant, essayés dans cet ordre. Cette souplesse est au contrat : des intégrations en place dépendent de chacune de ces variantes.

RangTransportForme
1En-têteAuthorization: Basic <clé>
2En-têtesusername + password
3En-têtex-api-key
4Paramètreusername + password (query en GET, corps sinon)
5Paramètrex-api-key
En-tête recommandé
x-api-key: fm_live_xxxxxxxxxxxxxxxxxxxxxxxx
Content-Type: application/json

Environnements

Pour éprouver une intégration sans facturer, deux voies : passer un compte en mode test depuis le backoffice, ou — c'est la voie recommandée — écrire l'intégration directement sur la v2.

Le bac à sable ci-dessous vise le même environnement de test que la vue v2 : il vous permet de comparer les deux contrats sur un appel identique.

Essayer l'API

Composez un appel au format v1 et exécutez-le depuis cette page. Le script se régénère en direct dans les quatre langages.

Environnement de test uniquement — n’utilisez jamais vos identifiants de production sur cette page. Les valeurs saisies restent dans votre navigateur : elles ne sont ni enregistrées, ni transmises à un tiers.

Identifiants de test

En-tête x-api-key — le seul identifiant exigé par le contrat v1.

Message

11 caractères au maximum. Obligatoire — aucun expéditeur par défaut.

Format E.164 : indicatif pays puis numéro, 8 à 15 chiffres.

37 caractères1 segment facturéGSM-7

curl -X POST https://api.fastermessage.com/v1/sms/send \
  -H "x-api-key: $FM_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "from": "FASTERMSG",
  "to": "",
  "text": "Votre code est 480912. Valable 5 min."
}'

Renseignez les champs requis pour lancer l’appel.

Envoyer un SMS

Méthode HTTP POSThttps://api.fastermessage.com/v1/sms/send

Le même envoi existe en GET /v1/sms/send, avec les paramètres en query. Il est maintenu pour les intégrations en place mais ne doit plus être employé : il expose la clé dans l'URL.

Paramètres

ChampTypeDescription
fromrequisstringNom alphanumérique (11 caractères max) ou numéro valide, approuvé sur le compte. Son absence répond MISSING_PARAMETERS_FROM : aucun expéditeur par défaut n'est appliqué.
torequisstringNuméro du destinataire avec indicatif pays (ex. 2296xxxxxxxx).
textrequisstringContenu du message. content en est un alias historique, prioritaire si les deux sont fournis.
sendAtoptionnelstringDate d’envoi programmé. Alias historique : date.
timezoneoptionnelstringFuseau appliqué à sendAt.
accentsoptionnelbooleanForce l’encodage UCS-2 pour les accents et caractères spéciaux. Divise la capacité par segment.
messageIdoptionnelstringIdentifiant fourni par le client, repris dans les accusés de livraison — et jusque dans les réponses d’échec, pour corréler un refus.
dlrUrloptionnelstringURL de rappel de l’accusé de livraison.
dlrMethodoptionnelstringMéthode du rappel : POST (défaut) ou GET.
Requête
curl -X POST https://api.fastermessage.com/v1/sms/send \
  -H "x-api-key: $FM_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "from": "FASTERMSG",
  "to": "22960000000",
  "text": "Votre commande cmd-42 est prête.",
  "messageId": "cmd-42",
  "dlrUrl": "https://exemple.test/webhooks/dlr"
}'
Succès — 202 Accepted
{
  "status": true,
  "code": "SUBMITTED",
  "description": "202: The request has been submitted and is being processed",
  "messageId": "cmd-42",
  "smsCount": 1
}
Erreur — 402 Payment Required
{
  "status": false,
  "code": "INSUFFICIENT_BALANCE",
  "description": "402: Insufficient balance to process the request",
  "messageId": "cmd-42"
}

Consulter le solde

Méthode HTTP GEThttps://api.fastermessage.com/v1/sms/balance

Renvoie le solde SMS, sans devise ni ventilation par canal — la v2 rend les quatre canaux et la devise du compte.

Requête
curl https://api.fastermessage.com/v1/sms/balance \
  -H "x-api-key: $FM_API_KEY"
Succès — 200 OK
{
  "status": true,
  "code": "SUCCESS",
  "description": "200: The operation was successful",
  "balance": 289009
}

Accusés de livraison (DLR)

L'URL déclarée dans dlrUrl est appelée à chaque changement d'état. La méthode est POST par défaut, GET si vous l'avez configuré ainsi.

Charge utile
{
  "uuid": "7d3b5e0c-1a84-4c1e-9f2a-2f1c9d4e8a6b",
  "level": 3,
  "status": "Delivered",
  "receivedAt": "2026-09-07T10:00:06.900Z",
  "messageId": "cmd-42",
  "to": "22960000000",
  "smsCount": 1
}

Quatre champs sont toujours présents : uuid, level, status et receivedAt. Les autres n'apparaissent que si vous les avez activés dans vos variables DLR, depuis le backoffice.

Variables DLR activables

VariableContenu
messageIdVotre identifiant, repris de la requête d’envoi.
fromExpéditeur employé.
toDestinataire.
textContenu émis.
smsCountNombre de segments facturés.
sentAtHorodatage de remise au transporteur.
messageStatusCodeCode d’état brut de l’opérateur.
messageStatusLibellé d’état de l’opérateur.
descriptionPrécision textuelle sur l’état.
referenceRéférence interne du message.
batchuuidIdentifiant du lot, pour un envoi groupé.

Sécurité

Chaque rappel porte l'en-tête X-Fastermessage-Signature — un HMAC-SHA256 de la charge utile — et s'annonce par l'agent Fastermessage-DLR/1.0. Vérifiez la signature avant de traiter, et servez votre point de terminaison en HTTPS.

Codes de statut

Chaque réponse porte un code et une description formatée "<code HTTP>: <message>". Ces valeurs sont gelées : ni les libellés, ni les codes HTTP ne changeront, y compris pour corriger une formulation — des intégrations les comparent à des chaînes fixes.

Codes d’envoi

codeHTTPSignification
SUBMITTED202The request has been submitted and is being processed
PROGRAMMED200The task is programmed
SENT200The message has been sent
DELIVERED200The message was delivered successfully
UNDELIVERED424The message could not be delivered
SUCCESS200The operation was successful

Codes de refus

codeHTTPSignification
AUTHENTICATION_FAILED401Authentication failed
FORBIDDEN403Access is forbidden
MISSING_PARAMETERS400Required parameters are missing
MISSING_PARAMETERS_TO400Required parameter [to] is missing
MISSING_PARAMETERS_CONTENT400Required parameter [content] or [text] is missing
MISSING_PARAMETERS_FROM400Required parameter [from] is missing
INVALID_SENDERID400Invalid sender ID
INVALID_PHONE400Invalid phone number
INVALID_OPERATOR400Invalid operator
INVALID_DATE_TIMEZONE400Invalid date or timezone
UNDEFINED_PRICE400Price not defined for this operator/country
INSUFFICIENT_BALANCE402Insufficient balance to process the request
SUSPENDED423The resource is suspended
RATE_LIMIT_EXCEEDED429The rate limit has been exceeded
GATEWAY_UNAVAILABLE503Gateway unavailable, please try again later
INTERNAL_SERVER_ERROR500Internal server error occurred

Limites

Le débit est plafonné par compte. Un dépassement répond RATE_LIMIT_EXCEEDED en 429.

  • Pas d'envoi en lot : un message par appel.
  • Pas d'idempotence : un rejeu après coupure réseau renvoie et refacture le message.
  • Pas d'identifiant de requête : un incident ne peut pas être corrélé à nos journaux.

Ces trois manques sont comblés par la v2 — voir le guide de migration.