Référence API v1Disponible

La documentation de l’API REST Sendimo v1.

Envoyez des SMS vers les numéros tunisiens avec un seul appel HTTP, suivez leur livraison et recevez les statuts par webhook. API REST en HTTPS, JSON en entrée et en sortie.

L’essentiel

ÉlémentValeur
URL de basehttps://api.sendimo.tn/v1
ProtocoleHTTPS uniquement (TLS 1.2+)
FormatJSON, UTF-8, Content-Type: application/json
AuthentificationAuthorization: Bearer sk_live_… (ou sk_test_…)
VersionsVersion majeure dans le chemin (/v1). Les ajouts non cassants sont publiés sans changer de version.
DatesISO 8601, UTC (2026-10-30T09:15:00Z)
IdentifiantsChaînes préfixées : msg_…, bat_…, snd_…
MontantsChaîne à 3 décimales, en TND ("0.140")
NumérosE.164 (+21620123456). Les numéros locaux à 8 chiffres sont acceptés et convertis en +216.

Endpoints v1

MéthodeCheminRôle
POST/messagesEnvoyer un SMS
POST/messages/bulkEnvoyer le même SMS, ou des SMS personnalisés, à plusieurs numéros
GET/messages/{id}Obtenir un message et son statut
GET/messagesLister les messages (filtres et pagination)
DELETE/messages/{id}Annuler un message programmé
GET/batches/{id}Suivre la progression d’un envoi en masse
GET/sender-idsLister vos noms d’expéditeur approuvés
POST/sender-idsDemander un nouveau nom d’expéditeur
GET/account/balanceConsulter le solde restant

Authentification

Chaque requête porte une clé API secrète en jeton Bearer. Les clés sont créées et révoquées dans votre espace ; chaque clé n’est affichée qu’une fois, à sa création.

  • Les clés s’utilisent uniquement côté serveur. Ne les placez jamais dans une application mobile ou du code navigateur.
  • Une clé absente ou invalide renvoie 401 unauthorized. Une clé révoquée renvoie 401 key_revoked.
  • Numéros de test : en mode test, +21600000001 finit toujours en delivered et +21600000002 toujours en failed.
PréfixeModeComportement
sk_live_ProductionEnvoie de vrais SMS et débite le solde
sk_test_TestValide la requête et renvoie des réponses réalistes ; rien n’est envoyé ni facturé. Les webhooks sont envoyés avec des statuts simulés.
ExemplecURL
curl https://api.sendimo.tn/v1/account/balance \
  -H "Authorization: Bearer sk_live_9f2c..."

Envoyer un SMS — POST /messages

Envoie un SMS. L’appel répond dès que le message est accepté (202) ; le statut final arrive ensuite par webhook ou via GET /messages/{id}.

ChampTypeRequisDescription
tostringOuiDestinataire, en E.164 ou numéro local à 8 chiffres
fromstringOuiUn Sender ID approuvé (par exemple SENDIMO)
textstringOuiContenu, 1 530 caractères GSM-7 ou 670 caractères Unicode maximum (10 segments)
scheduled_atstringNonDate ISO 8601 pour un envoi différé, jusqu’à 30 jours à l’avance
referencestringNonVotre propre identifiant (64 caractères max), renvoyé dans les réponses et les webhooks
webhook_urlstringNonRemplace le webhook du compte pour ce message
RequêtecURL
curl -X POST https://api.sendimo.tn/v1/messages \
  -H "Authorization: Bearer $SENDIMO_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: order-4821-otp" \
  -d '{
    "to": "+21620123456",
    "from": "SENDIMO",
    "text": "Votre code est 482913. Il expire dans 5 minutes.",
    "reference": "order-4821"
  }'
Réponse 202 AcceptedJSON
{
  "id": "msg_01HF8Z3K9QX2",
  "status": "queued",
  "to": "+21620123456",
  "from": "SENDIMO",
  "text": "Votre code est 482913. Il expire dans 5 minutes.",
  "encoding": "GSM-7",
  "segments": 1,
  "network": "ooredoo",
  "cost": { "amount": "0.140", "currency": "TND" },
  "reference": "order-4821",
  "scheduled_at": null,
  "created_at": "2026-10-30T09:15:00Z"
}

Envoi en masse — POST /messages/bulk

Envoie jusqu’à 10 000 messages en un seul appel, avec un texte commun ou un texte par destinataire pour personnaliser. Renvoie un lot (batch) que vous pouvez suivre.

Les numéros invalides ne font pas échouer tout le lot : ils sont listés dans rejected avec { "index", "to", "error" } et ne sont pas facturés. GET /batches/{id} renvoie le même objet avec le nombre de messages par statut (queued, sent, delivered, failed).

ChampTypeRequisDescription
fromstringOuiSender ID approuvé, utilisé pour tous les messages
textstringNon*Texte commun à tous les destinataires. *Requis sauf si chaque élément a son propre text
messagesarrayOuiListe de { "to", "text"?, "reference"? } ; un text par élément remplace le texte commun
scheduled_atstringNonEnvoyer tout le lot plus tard
referencestringNonVotre identifiant pour le lot
Corps de la requêteJSON
{
  "from": "SENDIMO",
  "text": "Promo -20% ce week-end sur tout le magasin.",
  "messages": [
    { "to": "+21620123456" },
    { "to": "+21698765432", "text": "Salut Amine, -20% pour toi ce week-end." }
  ]
}
Réponse 202 AcceptedJSON
{
  "id": "bat_01HF90AB7C",
  "status": "processing",
  "total": 2,
  "accepted": 2,
  "rejected": [],
  "estimated_cost": { "amount": "0.280", "currency": "TND" },
  "created_at": "2026-10-30T09:20:00Z"
}

Consulter et lister les messages

GET /messages/{id} renvoie le message avec son statut actuel, ainsi que sent_at, delivered_at et error (null sauf en cas d’échec).

GET /messages liste les messages, du plus récent au plus ancien, avec une pagination par curseur.

ParamètreExempleDescription
statusfailedFiltrer par statut
to+21620123456Filtrer par destinataire
batch_idbat_01HF90AB7CMessages d’un envoi en masse
referenceorder-4821Votre identifiant
created_after / created_before2026-10-01T00:00:00ZIntervalle de dates
limit501 à 100, 20 par défaut
cursoreyJpZCI6...Valeur de next_cursor de la page précédente
RéponseJSON
{
  "data": [ { "id": "msg_01HF8Z3K9QX2", "status": "delivered", "...": "..." } ],
  "has_more": true,
  "next_cursor": "eyJpZCI6Im1zZ18wMUhGOFoz..."
}

Statuts des messages

Un message passe de queued à sent puis delivered, ou se termine en failed, undelivered ou canceled. Les statuts finaux ne changent plus. Pour annuler un message programmé : DELETE /messages/{id} (uniquement tant qu’il est scheduled).

StatutFinalSignificationFacturé
scheduledNonEn attente de scheduled_at ; peut être annuléNon
queuedNonAccepté, en attente d’envoi à l’opérateurRéservé
sentNonTransmis à l’opérateur (Ooredoo, Orange, Tunisie Telecom)Oui
deliveredOuiL’opérateur a confirmé la remise sur le téléphoneOui
undeliveredOuiL’opérateur n’a pas pu livrer (téléphone éteint trop longtemps, abonné invalide)Oui
failedOuiRejeté avant d’atteindre l’opérateur ; voir error.codeNon, remboursé
canceledOuiMessage programmé annulé par vousNon

Sender IDs

Un Sender ID est le nom que voient les destinataires à la place d’un numéro (11 lettres ou chiffres max, par exemple SENDIMO). Les opérateurs tunisiens exigent que chaque nom soit approuvé avant utilisation : les nouveaux noms passent donc en revue.

Statuts : pending, approved, rejected (avec un motif). Envoyer avec un nom non approuvé renvoie 403 sender_not_approved.

GET /sender-idsJSON
{
  "data": [
    { "id": "snd_01HE7A", "name": "SENDIMO", "status": "approved", "created_at": "2026-10-01T10:00:00Z" },
    { "id": "snd_01HF2C", "name": "MYSHOP", "status": "pending", "created_at": "2026-10-29T14:30:00Z" }
  ]
}
POST /sender-idsJSON
{ "name": "MYSHOP", "use_case": "Order confirmations and delivery updates for myshop.tn" }

Solde — GET /account/balance

reserved est bloqué pour les messages en file d’attente, puis libéré ou débité quand ils atteignent un statut. Un envoi qui dépasse le solde disponible renvoie 402 insufficient_balance.

RéponseJSON
{
  "balance": { "amount": "152.340", "currency": "TND" },
  "reserved": { "amount": "0.900", "currency": "TND" },
  "low_balance_threshold": { "amount": "20.000", "currency": "TND" }
}

Erreurs

Toutes les erreurs ont le même format, avec un code stable lisible par machine et un request_id pour le support.

HTTPCodeCause
400invalid_requestJSON mal formé ou champ manquant
400invalid_phone_numberto n’est pas un numéro valide
400text_too_longPlus de 10 segments
401unauthorized / key_revokedClé API invalide, absente ou révoquée
402insufficient_balanceSolde insuffisant pour l’envoi
403sender_not_approvedfrom n’est pas un Sender ID approuvé
404not_foundMessage, lot ou Sender ID inconnu
409idempotency_conflictMême Idempotency-Key réutilisée avec un corps différent
422destination_not_supportedNuméro hors des pays pris en charge (v1 : Tunisie uniquement)
429rate_limitedTrop de requêtes ; voir Retry-After
500 / 503internal_error / unavailableErreur de notre côté ; vous pouvez réessayer avec la même clé d’idempotence
Format d’erreurJSON
{
  "error": {
    "code": "invalid_phone_number",
    "message": "'to' must be a valid Tunisian number in E.164 format.",
    "field": "to",
    "request_id": "req_01HF9C4D"
  }
}

Limites de débit

Chaque réponse contient X-RateLimit-Limit, X-RateLimit-Remaining et X-RateLimit-Reset. Une réponse 429 inclut Retry-After, en secondes.

PortéeLimite
Tous les endpoints, par clé API100 requêtes / seconde
POST /messages/bulk10 requêtes / minute
Débit d’envoi50 SMS / seconde par compte (plus sur demande)

Idempotence

Envoyez un en-tête Idempotency-Key (n’importe quelle chaîne unique, 64 caractères max) sur chaque POST. Si une erreur réseau vous laisse dans le doute, réessayez avec la même clé : Sendimo renvoie la réponse d’origine au lieu d’envoyer deux fois. Les clés sont conservées 24 heures.

Encodage et segments

Sendimo choisit l’encodage automatiquement et facture par segment. Le texte arabe, les emojis et certains caractères accentués imposent l’Unicode, ce qui divise environ par deux le nombre de caractères par SMS.

La réponse indique toujours encoding, segments et cost : vous pouvez afficher le prix avant un envoi en masse.

Encodage1 segmentPar segment si découpéContenu typique
GSM-7160 caractères153 caractèresTexte latin, français sans la plupart des accents
Unicode (UCS-2)70 caractères67 caractèresArabe, emojis, caractères hors GSM-7

Les autres intégrations

Prêt à envoyer vos SMS ?

Lancement bientôt en Tunisie. Rejoignez l’accès anticipé.