API Reference

Technical Documentation

Integrate EnvoiSMS.ma in under 15 minutes with our PHP, Node.js, and Python SDKs. Built for engineers.

Start here

Everything to get started before your first request.

EnvoiSMS.ma is a programmable messaging infrastructure built for Morocco. Our direct carrier routes with IAM, Inwi, and Orange guarantee minimal latency.

Base URLhttps://api.envoisms.ma
API Version/v1 (Stable)
Data Formatapplication/json; charset=utf-8
AuthenticationAuthorization: Bearer env_live_xxx
Default Rate Limit100 requests / minute
Number FormatE.164 (ex: +212612345678)
Active ChannelsPremium SMS, WhatsApp API
LocationIn Morocco — Cloudflare edge 🇲🇦
01

Generate your "env_live_..." API key from your EnvoiSMS.ma Console.

02

Use Bearer authentication in your HTTP headers for each request.

03

Test your integration using Sandbox mode to consume no real credits.

04

Integrate the WhatsApp Business API to divide your OTP costs by 10.

05

Configure a signed Webhook to receive delivery reports in real time.

06

Track your consumption and MAD invoices directly on your Dashboard.

Send your first message
// config/services.php
'envoisms' => [
    'key' => env('ENVOISMS_API_KEY'),
],

// Usage
Http::withToken(config('services.envoisms.key'))
    ->post('https://api.envoisms.ma/v1/messages', [
        'to' => '+212612345678',
        'message' => 'Votre commande est en cours de livraison đźšš',
        'from' => 'MaBoutique'
    ]);
OpenAPI Spec

Authentication

Bearer keys, headers, and security constraints.

Each /v1 endpoint requires a valid API key passed in the Authorization header as a Bearer token. Test and production keys can be generated or revoked from your console.

Authorization

Authorization: Bearer env_live_xxx

Rate Limit Headers

X-RateLimit-Limit and X-RateLimit-Remaining returned with each call.

IP Allowlists

Requests coming from unconfigured IP addresses return a 401 status.

CORS Supported

JSON, Authorization, X-EnvoiSMS.ma-Signature, and X-EnvoiSMS.ma-Version are supported.

HTTP Headers Example
POST /v1/messages HTTP/1.1
Host: api.envoisms.ma
Authorization: Bearer env_live_xxxxxxxx
Content-Type: application/json
Accept: application/json

Open Source

Official SDKs & Client Libraries

Integrate EnvoiSMS API into your application with our official open-source client libraries.

NPM PackageTypeScript & JavaScript
Node.js / TypeScript
npm install envoisms
GitHub Repository
Composer PackagePHP 8.0+
PHP Client
composer require envoisms/envoisms-php
GitHub Repository
PyPI PackagePython 3.8+
Python Client
pip install envoisms
GitHub Repository
Notification ChannelLaravel 9 - 11
Laravel OTP Package
composer require envoisms/laravel-otp
GitHub Repository
POST/v1/messages

Send a message

Sends a transaction or marketing message via SMS or WhatsApp Business API.

Request Body
tostringRequired
Numéro de téléphone au format E.164 (+212...).
messagestringRequired
Contenu textuel (max 1600 caractères). Également accepté sous le nom "body".
fromstringOptional
Sender ID personnalisé (ex: NOM_MARQUE). Par défaut "ENVOISMS".
channelstringOptional
"sms" ou "whatsapp". Par défaut "sms".
cascadebooleanOptional
Si activé, tente de délivrer par WhatsApp et bascule automatiquement sur SMS en cas d'échec.
metadataobjectOptional
Clés-valeurs personnalisées stockées avec le message et transmises dans les webhooks.
buttonsarrayOptional
Tableau d'objets boutons WhatsApp interactifs (max 3, type "copy" | "url" | "call").
Notes
  • Les sauts de ligne (\n) sont pleinement pris en charge sur tous les canaux et s'affichent correctement chez le destinataire.
  • Le formatage de texte enrichi (gras, italique, etc.) n'est pas supportĂ© par le canal SMS (texte brut uniquement).
  • Le canal WhatsApp prend en charge le formatage de texte avec la syntaxe standard (*gras*, _italique_, ~barrĂ©~).
POSThttps://api.envoisms.ma/v1/messages
curl -X POST "https://api.envoisms.ma/v1/messages" \
  -H "Authorization: Bearer env_live_xxx" \
  -H "Content-Type: application/json" \
  -d '{
    "to": "+212612345678",
    "message": "Votre code de validation est 849204",
    "from": "MaBoutique",
    "channel": "whatsapp"
  }'
{
  "id": "msg_8f2d...",
  "to": "+212612345678",
  "channel": "whatsapp",
  "cascade": false,
  "status": "queued",
  "cost": {
    "eur": 0.0118,
    "mad": 0.13
  },
  "segments": 1,
  "created_at": "2026-05-15T10:30:00Z"
}
POST/v1/messages/bulk

Envoi groupé (Bulk)

Envoie jusqu'Ă  10 000 messages en un seul appel API avec des destinataires ou des contenus uniques.

Request Body
messagesarrayRequired
Tableau d'objets contenant "to", "message" (ou "body"), et un objet facultatif "metadata".
fromstringOptional
Sender ID global pour tout le lot.
channelstringOptional
Canal global ("sms" ou "whatsapp"). Par défaut "sms".
Notes
  • Les sauts de ligne (\n) sont pleinement pris en charge dans les corps des messages groupĂ©s.
  • Le formatage de texte enrichi (gras, italique, etc.) n'est pas supportĂ© par le canal SMS (texte brut uniquement).
  • Le canal WhatsApp prend en charge le formatage de texte avec la syntaxe standard (*gras*, _italique_, ~barrĂ©~).
POSThttps://api.envoisms.ma/v1/messages/bulk
curl -X POST "https://api.envoisms.ma/v1/messages/bulk" \
  -H "Authorization: Bearer env_live_xxx" \
  -H "Content-Type: application/json" \
  -d '{
    "messages": [
      {
        "to": "+212611111111",
        "message": "Hello Client 1"
      },
      {
        "to": "+212622222222",
        "message": "Hello Client 2"
      }
    ],
    "from": "ENVOISMS",
    "channel": "sms"
  }'
{
  "batch_id": "batch_9a3c...",
  "total": 2,
  "channel": "sms",
  "estimated_cost": {
    "eur": 0.056,
    "mad": 0.62
  },
  "messages": [
    {
      "id": "msg_1a2b...",
      "to": "+212611111111",
      "status": "queued"
    },
    {
      "id": "msg_3c4d...",
      "to": "+212622222222",
      "status": "queued"
    }
  ]
}
GET/v1/messages

Send a message

Sends a transaction or marketing message via SMS or WhatsApp Business API.

Query Parameters
limitintegerOptional
Nombre de résultats à retourner (1-200, défaut: 50).
offsetintegerOptional
Nombre de résultats à ignorer pour la pagination (défaut: 0).
statusstringOptional
Filtrer par statut (queued, sent, delivered, failed).
channelstringOptional
Filtrer par canal (sms, whatsapp).
from_datestringOptional
Filtrer par date de début (format ISO 8601).
to_datestringOptional
Filtrer par date de fin (format ISO 8601).
GEThttps://api.envoisms.ma/v1/messages
curl -X GET "https://api.envoisms.ma/v1/messages?limit=50&offset=0" \
  -H "Authorization: Bearer env_live_xxx"
{
  "data": [
    {
      "id": "msg_8f2d...",
      "to": "+212612345678",
      "channel": "whatsapp",
      "body": "Votre code de validation est 849204",
      "sender_id": "MaBanque",
      "status": "delivered",
      "cost_mad": 0.13,
      "created_at": "2026-05-15T10:30:00Z"
    }
  ],
  "limit": 50,
  "offset": 0,
  "total": 1
}
GET/v1/messages/:id

Get message status

Retrieves the current status and delivery logs of a specific message.

GEThttps://api.envoisms.ma/v1/messages/:id
curl -X GET "https://api.envoisms.ma/v1/messages/:id" \
  -H "Authorization: Bearer env_live_xxx"
{
  "id": "msg_8f2d...",
  "account_id": "acc_3f1a...",
  "api_key_id": "key_e84c...",
  "campaign_id": null,
  "to": "+212612345678",
  "channel": "whatsapp",
  "body": "Votre code de validation est 849204",
  "sender_id": "MaBanque",
  "unicode": 0,
  "segments": 1,
  "status": "delivered",
  "cost_eur": 0.0118,
  "cost_mad": 0.13,
  "metadata": "{\"purpose\": \"otp\"}",
  "created_at": "2026-05-15T10:30:00Z"
}
GET/v1/templates

Lister les templates

Récupère tous les templates WhatsApp et SMS approuvés de votre compte.

GEThttps://api.envoisms.ma/v1/templates
curl -X GET "https://api.envoisms.ma/v1/templates" \
  -H "Authorization: Bearer env_live_xxx"
{
  "data": [
    {
      "id": "tpl_1234...",
      "name": "otp_verification",
      "channel": "whatsapp",
      "body": "Votre code de validation est {{1}}",
      "status": "approved",
      "category": "otp",
      "created_at": "2026-05-15T10:30:00Z"
    }
  ],
  "total": 1
}
POST/v1/templates

Créer un template

Soumet un nouveau template pour approbation par les opérateurs ou WhatsApp.

Request Body
namestringRequired
Nom interne du template.
channelstringRequired
"sms" ou "whatsapp".
bodystringRequired
Contenu du message avec variables (ex: {{1}}).
categorystringOptional
Catégorie du template (ex: "otp", "marketing").
POSThttps://api.envoisms.ma/v1/templates
curl -X POST "https://api.envoisms.ma/v1/templates" \
  -H "Authorization: Bearer env_live_xxx" \
  -H "Content-Type: application/json" \
  -d '{}'
{
  "id": "tpl_1234...",
  "name": "otp_verification",
  "status": "pending"
}
GET/v1/sender-ids

Lister les Sender IDs

Récupère la liste de vos Sender IDs avec leur statut d'approbation.

GEThttps://api.envoisms.ma/v1/sender-ids
curl -X GET "https://api.envoisms.ma/v1/sender-ids" \
  -H "Authorization: Bearer env_live_xxx"
{
  "data": [
    {
      "id": "sid_9a8b...",
      "sender_id": "MABANQUE",
      "status": "approved",
      "requested_at": "2026-05-10T09:00:00Z"
    }
  ]
}
POST/v1/sender-ids

Demander un Sender ID

Soumet un nouveau Sender ID pour approbation (requis pour le Maroc).

Request Body
sender_idstringRequired
Le nom d'expéditeur souhaité (max 11 caractères).
rc_urlstringOptional
Lien vers le Registre de Commerce pour vérification.
POSThttps://api.envoisms.ma/v1/sender-ids
curl -X POST "https://api.envoisms.ma/v1/sender-ids" \
  -H "Authorization: Bearer env_live_xxx" \
  -H "Content-Type: application/json" \
  -d '{}'
{
  "id": "sid_9a8b...",
  "sender_id": "MABANQUE",
  "status": "pending"
}
POST/v1/verify/send

Send an OTP code

Sends a one-time verification code. Two modes, your choice: "whatsapp" — managed verification, the simplest and cheapest (EnvoiSMS generates the code, delivers it on WhatsApp from a verified sender, then falls back to SMS automatically if unconfirmed within 60s; nothing to store on your side — code_length, expiry and template are ignored in this mode: the code is always 6 digits, valid 5 minutes) — or "sms" — you keep full control of the code, template and sender. Both modes are validated with the same /v1/verify/check call. Want your own brand on the managed SMS fallback? Available on request: [email protected].

Request Body
tostringRequired
Destinataire au format E.164.
channelstringOptional
"whatsapp" (vérification gérée : WhatsApp puis SMS automatique, code valide 5 min, 3 essais, facturée au tarif WhatsApp par vérification — le plus économique) ou "sms" (code généré pour vous, envoyé avec votre marque). Défaut: "sms".
app_idstringOptional
ID de l'application Verify configurée sur le tableau de bord (ex: vra_...). Applique automatiquement les paramètres de code, de délais et la cascade de canaux.
brandstring (Optionnel, canal sms)Optional
Nom de la marque affiché (ex: MonApp, max 32 car.). Par défaut "EnvoiSMS".
code_lengthinteger (Optionnel, canal sms)Optional
Longueur du code généré (de 4 à 8 chiffres, défaut: 6).
expiryinteger (Optionnel, canal sms)Optional
Durée de validité du code en secondes (de 60 à 1800, défaut: 600).
cascadearray (Optionnel, canal sms)Optional
Liste ordonnée de canaux pour le basculement automatique en cascade (ex: ["sms", "voice"]).
templatestring (Optionnel, canal sms)Optional
Texte personnalisé avec les variables {{code}} et {{brand}}. En mode whatsapp, le message localisé (fr/en/es) est géré pour vous.
otp_button_textstring (Optionnel, canal sms)Optional
Libellé personnalisé pour le bouton de copie automatique WhatsApp (max 25 car.).
POSThttps://api.envoisms.ma/v1/verify/send
curl -X POST "https://api.envoisms.ma/v1/verify/send" \
  -H "Authorization: Bearer env_live_xxx" \
  -H "Content-Type: application/json" \
  -d '{
    "to": "+212612345678",
    "brand": "MonApp",
    "channel": "whatsapp",
    "code_length": 6,
    "expiry": 600
  }'
{
  "session_id": "vrf_7e2a...",
  "to": "+212612345678",
  "channel": "whatsapp",
  "expires_at": "2026-05-15T10:35:00Z",
  "status": "sent",
  "cost": { "eur": 0.025, "mad": 0.275 }
}
POST/v1/verify/check

Verify an OTP

Validates the code entered by the user for a given verification session.

Request Body
session_idstringRequired
ID de session reçu lors de l'appel à /v1/verify/send.
codestringRequired
Le code reçu et saisi par l'utilisateur.
POSThttps://api.envoisms.ma/v1/verify/check
curl -X POST "https://api.envoisms.ma/v1/verify/check" \
  -H "Authorization: Bearer env_live_xxx" \
  -H "Content-Type: application/json" \
  -d '{
    "session_id": "vrf_7e2a...",
    "code": "849204"
  }'
{
  "session_id": "vrf_7e2a...",
  "verified": true,
  "verified_at": "2026-05-15T10:35:12Z"
}
GET/v1/verify/:id

OTP session status

Retrieves the status (validated or expired) of a specific verification session.

GEThttps://api.envoisms.ma/v1/verify/:id
curl -X GET "https://api.envoisms.ma/v1/verify/:id" \
  -H "Authorization: Bearer env_live_xxx"
{
  "id": "vrf_7e2a...",
  "to": "+212612345678",
  "channel": "whatsapp",
  "expires_at": "2026-05-15T10:40:00Z",
  "verified_at": "2026-05-15T10:35:12Z",
  "created_at": "2026-05-15T10:30:00Z"
}
POST/v1/verify/lookup

Number Lookup

Validates the format, carrier network, line type, and geographic location of a phone number.

Request Body
numberstringRequired
Le numéro de téléphone à valider (format local ou international).
country_codestringOptional
Code pays ISO à 2 lettres (ex: MA, FR). Recommandé si le numéro est au format local.
POSThttps://api.envoisms.ma/v1/verify/lookup
curl -X POST "https://api.envoisms.ma/v1/verify/lookup" \
  -H "Authorization: Bearer env_live_xxx" \
  -H "Content-Type: application/json" \
  -d '{
    "number": "+212612345678",
    "country_code": "MA"
  }'
{
  "valid": true,
  "number": "212612345678",
  "local_format": "0612345678",
  "international_format": "+212612345678",
  "country_prefix": "212",
  "country_code": "MA",
  "country_name": "Morocco",
  "location": "Casablanca",
  "carrier": "Maroc Telecom (IAM)",
  "line_type": "mobile"
}
GET/v1/contacts

List contacts

Retrieves contacts with optional keyword search or contact list filtering.

Query Parameters
limitintegerOptional
Résultats par page (1-500, défaut: 100).
offsetintegerOptional
Pagination offset (défaut: 0).
qstringOptional
Recherche par nom, téléphone ou email.
list_idstringOptional
Filtrer uniquement les membres d'une liste de contacts spécifique.
GEThttps://api.envoisms.ma/v1/contacts
curl -X GET "https://api.envoisms.ma/v1/contacts?limit=50&offset=0" \
  -H "Authorization: Bearer env_live_xxx"
{
  "data": [
    {
      "id": "ctc_a2b3...",
      "phone": "+212612345678",
      "name": "Karim Bennani",
      "email": "[email protected]",
      "custom1": "VIP",
      "custom2": null,
      "custom3": null,
      "created_at": "2026-05-10T14:20:00Z"
    }
  ],
  "limit": 100,
  "offset": 0,
  "total": 1
}
POST/v1/contacts

List contacts

Retrieves contacts with optional keyword search or contact list filtering.

Request Body
phonestringRequired
Numéro de téléphone au format E.164.
namestringOptional
Nom complet du contact.
emailstringOptional
Adresse email.
list_idstringOptional
Associer immédiatement le contact à une liste existante.
custom_fieldsobjectOptional
Objet contenant jusqu'à 3 champs personnalisés ("custom1", "custom2", "custom3").
POSThttps://api.envoisms.ma/v1/contacts
curl -X POST "https://api.envoisms.ma/v1/contacts" \
  -H "Authorization: Bearer env_live_xxx" \
  -H "Content-Type: application/json" \
  -d '{
    "phone": "+212612345678",
    "name": "Karim Bennani",
    "email": "[email protected]",
    "list_id": "lst_f84b..."
  }'
{
  "id": "ctc_a2b3...",
  "phone": "+212612345678",
  "name": "Karim Bennani",
  "email": "[email protected]",
  "custom1": "VIP",
  "custom2": null,
  "custom3": null,
  "created_at": "2026-05-10T14:20:00Z"
}
POST/v1/contacts/import

Importer des contacts

Importe massivement jusqu'Ă  5 000 contacts en un seul appel.

Request Body
contactsarrayRequired
Tableau d'objets contenant "phone", "name" (optionnel) et "email" (optionnel).
list_idstringOptional
ID de la liste dans laquelle importer le groupe.
POSThttps://api.envoisms.ma/v1/contacts/import
curl -X POST "https://api.envoisms.ma/v1/contacts/import" \
  -H "Authorization: Bearer env_live_xxx" \
  -H "Content-Type: application/json" \
  -d '{
    "contacts": [
      {
        "phone": "+212611111111",
        "name": "Karim"
      },
      {
        "phone": "+212622222222",
        "name": "Youssef"
      }
    ],
    "list_id": "lst_f84b..."
  }'
{
  "imported": 150,
  "skipped": 3
}
DELETE/v1/contacts/:id

Supprimer un contact

Supprime définitivement un contact à partir de son identifiant unique.

DELETEhttps://api.envoisms.ma/v1/contacts/:id
curl -X DELETE "https://api.envoisms.ma/v1/contacts/:id" \
  -H "Authorization: Bearer env_live_xxx"
{
  "deleted": true,
  "id": "ctc_a2b3..."
}
GET/v1/contacts/lists

Lister les listes

Récupère toutes les listes de contacts créées pour les campagnes de diffusion.

GEThttps://api.envoisms.ma/v1/contacts/lists
curl -X GET "https://api.envoisms.ma/v1/contacts/lists" \
  -H "Authorization: Bearer env_live_xxx"
{
  "data": [
    {
      "id": "lst_f84b...",
      "name": "Newsletter Clients",
      "description": "Clients inscrits Ă  notre lettre d'information",
      "count": 1420,
      "created_at": "2026-04-15T09:00:00Z"
    }
  ]
}
POST/v1/contacts/lists

Créer une liste

Crée un nouveau groupe (liste de contacts) vide destiné aux campagnes.

Request Body
namestringRequired
Nom de la liste.
descriptionstringOptional
Description de la liste.
POSThttps://api.envoisms.ma/v1/contacts/lists
curl -X POST "https://api.envoisms.ma/v1/contacts/lists" \
  -H "Authorization: Bearer env_live_xxx" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Newsletter Clients",
    "description": "Clients inscrits"
  }'
{
  "id": "lst_f84b...",
  "name": "Newsletter Clients",
  "description": "Clients inscrits",
  "count": 0
}
GET/v1/optouts

Lister les désinscriptions

Récupère la liste des numéros qui se sont désinscrits (STOP) de vos communications.

GEThttps://api.envoisms.ma/v1/optouts
curl -X GET "https://api.envoisms.ma/v1/optouts" \
  -H "Authorization: Bearer env_live_xxx"
{
  "data": [
    {
      "phone": "+212611111111",
      "opted_out_at": "2026-06-01T12:00:00Z"
    }
  ],
  "total": 1
}
POST/v1/optouts

Ajouter une désinscription

Ajoute manuellement un numéro à votre liste de désinscription (blacklist globale).

Request Body
phonestringRequired
Numéro de téléphone au format E.164.
POSThttps://api.envoisms.ma/v1/optouts
curl -X POST "https://api.envoisms.ma/v1/optouts" \
  -H "Authorization: Bearer env_live_xxx" \
  -H "Content-Type: application/json" \
  -d '{}'
{
  "success": true,
  "phone": "+212611111111",
  "opted_out_at": "2026-06-01T12:00:00Z"
}
DELETE/v1/optouts/:phone

Retirer une désinscription

Retire un numéro de la liste de désinscription.

DELETEhttps://api.envoisms.ma/v1/optouts/:phone
curl -X DELETE "https://api.envoisms.ma/v1/optouts/:phone" \
  -H "Authorization: Bearer env_live_xxx"
{
  "deleted": true,
  "phone": "+212611111111"
}
GET/v1/campaigns

Lister les campagnes

Récupère toutes vos campagnes d'envoi programmé ou de diffusion en cours.

GEThttps://api.envoisms.ma/v1/campaigns
curl -X GET "https://api.envoisms.ma/v1/campaigns" \
  -H "Authorization: Bearer env_live_xxx"
{
  "data": [
    {
      "id": "cmp_8d2a...",
      "name": "Soldes d'été 2026",
      "channel": "sms",
      "list_id": "lst_f84b...",
      "template_id": null,
      "body": "Bonjour {{name}}, profitez de -50% sur toute la collection avec le code ETE50 !",
      "sender_id": "SOLDES",
      "status": "draft",
      "scheduled_at": null,
      "created_at": "2026-06-01T12:00:00Z"
    }
  ]
}
POST/v1/campaigns

Créer une campagne

Enregistre une nouvelle campagne en tant que brouillon ou la planifie à une date précise.

Request Body
namestringRequired
Nom de la campagne.
bodystring (Requis*)Required
Corps du message. Peut utiliser la variable {{name}}.
template_idstring (Requis*)Required
Alternativement, ID d'un template approuvé. (*L'un des deux requis).
channelstringOptional
"sms" ou "whatsapp". Par défaut "sms".
list_idstringOptional
ID de la liste de contacts destinataire.
sender_idstringOptional
Nom d'expéditeur.
scheduled_atstringOptional
Date de programmation (ISO 8601). Met le statut en "scheduled".
buttonsarrayOptional
Tableau de boutons WhatsApp interactifs (max 3, type "copy" | "url" | "call").
metadataobjectOptional
Métadonnées personnalisées (ex: options de throttling / cadence d'envoi : {"throttling": "50_min"}).
POSThttps://api.envoisms.ma/v1/campaigns
curl -X POST "https://api.envoisms.ma/v1/campaigns" \
  -H "Authorization: Bearer env_live_xxx" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Soldes d'été 2026",
    "body": "Bonjour {{name}}, profitez de -50% avec le code ETE50 !",
    "channel": "sms",
    "list_id": "lst_f84b...",
    "sender_id": "SOLDES"
  }'
{
  "id": "cmp_8d2a...",
  "status": "draft"
}
GET/v1/campaigns/:id

Détails d'une campagne

Récupère les détails, la planification et le statut d'exécution d'une campagne.

GEThttps://api.envoisms.ma/v1/campaigns/:id
curl -X GET "https://api.envoisms.ma/v1/campaigns/:id" \
  -H "Authorization: Bearer env_live_xxx"
{
  "id": "cmp_8d2a...",
  "name": "Soldes d'été 2026",
  "channel": "sms",
  "list_id": "lst_f84b...",
  "body": "Bonjour {{name}}, profitez de -50%...",
  "sender_id": "SOLDES",
  "status": "running",
  "total_count": 1420,
  "sent_count": 840,
  "started_at": "2026-06-15T10:00:00Z",
  "created_at": "2026-06-01T12:00:00Z"
}
POST/v1/campaigns/:id/send

Lancer une campagne

Démarre immédiatement la diffusion d'une campagne de type brouillon vers tous les contacts associés.

POSThttps://api.envoisms.ma/v1/campaigns/:id/send
curl -X POST "https://api.envoisms.ma/v1/campaigns/:id/send" \
  -H "Authorization: Bearer env_live_xxx" \
  -H "Content-Type: application/json" \
  -d '{}'
{
  "id": "cmp_8d2a...",
  "queued": 1420,
  "total": 1420
}
GET/v1/webhooks

Lister les webhooks

Récupère la liste de tous vos endpoints de webhooks enregistrés.

GEThttps://api.envoisms.ma/v1/webhooks
curl -X GET "https://api.envoisms.ma/v1/webhooks" \
  -H "Authorization: Bearer env_live_xxx"
{
  "data": [
    {
      "id": "whk_5f2b...",
      "url": "https://mon-serveur.ma/api/envoisms-receiver",
      "events": [
        "message.delivered",
        "message.failed"
      ],
      "active": true,
      "last_triggered_at": "2026-06-15T09:30:15Z",
      "last_status": 200,
      "created_at": "2026-05-01T10:00:00Z"
    }
  ]
}
POST/v1/webhooks

Créer un Webhook

Enregistre une URL HTTPS de callback pour recevoir les notifications d'événements.

Request Body
urlstringRequired
URL cible sécurisée commençant par "https://".
eventsarrayOptional
Tableau d'événements (ex: ["message.delivered", "message.failed"]). Défaut: tous.
secretstringOptional
Clé de signature secrète. Si non fournie, elle sera générée automatiquement.
POSThttps://api.envoisms.ma/v1/webhooks
curl -X POST "https://api.envoisms.ma/v1/webhooks" \
  -H "Authorization: Bearer env_live_xxx" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://mon-serveur.ma/api/envoisms-receiver",
    "events": [
      "message.delivered",
      "message.failed"
    ]
  }'
{
  "id": "whk_5f2b...",
  "url": "https://mon-serveur.ma/api/envoisms-receiver",
  "events": [
    "message.delivered",
    "message.failed"
  ],
  "secret": "whsec_2f8a9e7d...",
  "active": true
}
PATCH/v1/webhooks/:id

Modifier un Webhook

Met à jour la configuration d'un webhook (URL, événements surveillés ou état actif).

Request Body
urlstringOptional
Nouvelle URL HTTPS.
eventsarrayOptional
Nouvelle liste d'événements abonnés.
activebooleanOptional
Activer (true) ou désactiver (false) le webhook.
PATCHhttps://api.envoisms.ma/v1/webhooks/:id
curl -X PATCH "https://api.envoisms.ma/v1/webhooks/:id" \
  -H "Authorization: Bearer env_live_xxx" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://mon-serveur.ma/api/envoisms-receiver-updated",
    "active": false
  }'
{
  "updated": true,
  "id": "whk_5f2b..."
}
DELETE/v1/webhooks/:id

Supprimer un Webhook

Désactive et supprime logiquement un endpoint de webhook.

DELETEhttps://api.envoisms.ma/v1/webhooks/:id
curl -X DELETE "https://api.envoisms.ma/v1/webhooks/:id" \
  -H "Authorization: Bearer env_live_xxx"
{
  "deleted": true,
  "id": "whk_5f2b..."
}
POST/v1/webhooks/:id/test

Tester un Webhook

Déclenche un événement de test ("message.test") vers l'URL configurée du webhook.

POSThttps://api.envoisms.ma/v1/webhooks/:id/test
curl -X POST "https://api.envoisms.ma/v1/webhooks/:id/test" \
  -H "Authorization: Bearer env_live_xxx" \
  -H "Content-Type: application/json" \
  -d '{}'
{
  "queued": true,
  "id": "whk_5f2b..."
}
GET/v1/api-keys

Lister les clés API

Récupère la liste de toutes vos clés d'API actives ou révoquées.

GEThttps://api.envoisms.ma/v1/api-keys
curl -X GET "https://api.envoisms.ma/v1/api-keys" \
  -H "Authorization: Bearer env_live_xxx"
{
  "data": [
    {
      "id": "key_e84c...",
      "name": "Production Server",
      "key_prefix": "env_live",
      "ip_whitelist": [
        "196.200.1.4"
      ],
      "rate_limit": 100,
      "permissions": [
        "send",
        "verify",
        "status"
      ],
      "active": true,
      "last_used_at": "2026-06-15T10:30:00Z",
      "created_at": "2026-05-01T08:00:00Z"
    }
  ]
}
POST/v1/api-keys

Créer une clé API

Génère un nouveau jeton d'API sécurisé avec des permissions et restrictions spécifiques.

Request Body
namestringOptional
Libellé pour identifier la clé (défaut: "API key").
permissionsarrayOptional
Droits accordés (send, verify, status, balance, contacts, campaigns, webhooks, billing, analytics, api_keys, optouts).
ip_whitelistarrayOptional
Liste d'adresses IP autorisées à exécuter des requêtes avec cette clé.
rate_limitintegerOptional
Limite maximale de requêtes/min (de 10 à 1000, défaut: 100).
POSThttps://api.envoisms.ma/v1/api-keys
curl -X POST "https://api.envoisms.ma/v1/api-keys" \
  -H "Authorization: Bearer env_live_xxx" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Production Server",
    "permissions": [
      "send",
      "verify",
      "status"
    ],
    "ip_whitelist": [
      "196.200.1.4"
    ],
    "rate_limit": 100
  }'
{
  "id": "key_e84c...",
  "name": "Production Server",
  "key_prefix": "env_live",
  "api_key": "env_live_a8f7d6c5b4a3...",
  "permissions": [
    "send",
    "verify",
    "status"
  ],
  "rate_limit": 100,
  "warning": "The full API key is shown once. Store it securely."
}
PATCH/v1/api-keys/:id

Modifier une clé API

Met à jour les permissions, restrictions IP ou l'état d'activation d'une clé API.

Request Body
namestringOptional
Nouveau nom.
permissionsarrayOptional
Nouvelle liste de permissions.
ip_whitelistarrayOptional
Nouvelle liste d'adresses IP autorisées.
rate_limitintegerOptional
Nouvelle limite de débit par minute.
activebooleanOptional
Activer ou suspendre la clé.
PATCHhttps://api.envoisms.ma/v1/api-keys/:id
curl -X PATCH "https://api.envoisms.ma/v1/api-keys/:id" \
  -H "Authorization: Bearer env_live_xxx" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Backup Server",
    "active": true
  }'
{
  "updated": true,
  "id": "key_e84c..."
}
DELETE/v1/api-keys/:id

Révoquer une clé API

Révoque définitivement une clé API pour l'empêcher d'authentifier les requêtes.

DELETEhttps://api.envoisms.ma/v1/api-keys/:id
curl -X DELETE "https://api.envoisms.ma/v1/api-keys/:id" \
  -H "Authorization: Bearer env_live_xxx"
{
  "revoked": true,
  "id": "key_e84c..."
}
GET/v1/billing/balance

Consulter le solde

Consulte le solde disponible en Dirhams Marocains (MAD) ainsi que la devise et le forfait actif.

GEThttps://api.envoisms.ma/v1/billing/balance
curl -X GET "https://api.envoisms.ma/v1/billing/balance" \
  -H "Authorization: Bearer env_live_xxx"
{
  "balance_mad": 1492.5,
  "currency": "MAD",
  "plan": "croissance"
}
GET/v1/analytics

Statistiques d'usage

Récupère des métriques clés sur vos envois (volumes totaux, taux de délivrabilité, et coûts facturés).

GEThttps://api.envoisms.ma/v1/analytics
curl -X GET "https://api.envoisms.ma/v1/analytics" \
  -H "Authorization: Bearer env_live_xxx"
{
  "summary": {
    "total": 12840,
    "delivered": 12570,
    "delivery_rate": 97.9,
    "cost_mad": 2663.1
  }
}

Webhooks Guide

Signed and secure delivery callbacks.

EnvoiSMS.ma posts JSON events to your server's HTTPS URL with an X-EnvoiSMS.ma-Signature header to authenticate the sender.

message.delivered

Triggered when the operator confirms successful delivery to the recipient's device.

message.failed

Triggered when delivery fails (invalid number, expired, rejected by carrier).

message.expired

Triggered when the message expires in the operator queue.

message.inbound

Triggered when a recipient sends a reply text message back to you (inbound SMS).

contact.optout

Triggered when a recipient unsubscribes using a STOP keyword or similar opt-out trigger.

verify.success

Triggered immediately when an OTP session is successfully validated by a correct code.

Signature Validation
import crypto from 'node:crypto';

export function verifySignature(body: string, sig: string, secret: string) {
  const hmac = crypto.createHmac('sha256', secret)
    .update(body)
    .digest('hex');
    
  return crypto.timingSafeEqual(Buffer.from(sig), Buffer.from('sha256=' + hmac));
}
OpenAPI Spec

Errors

API error response structure.

All API errors return an appropriate HTTP code (4xx or 5xx) along with a predictable JSON envelope containing the error code and description.

{
  "error": {
    "code": "INVALID_PHONE",
    "message": "to must be E.164 format, for example +212612345678",
    "docs": "https://envoisms.ma/docs#errors"
  }
}
UNAUTHORIZED

The API key is missing or invalid. Verify your Bearer token in the headers.

INSUFFICIENT_BALANCE

Solde insuffisant pour effectuer l'envoi.

INVALID_PHONE

The recipient number format is invalid. Use E.164 standard.

RATE_LIMITED

Limite de requêtes par minute dépassée.

CHANNEL_NOT_ALLOWED

Le canal demandé (ex: WhatsApp) n'est pas activé sur votre compte.

SENDER_ID_TOO_LONG

Le Sender ID dépasse la limite de 11 caractères.

SENDER_ID_INVALID

Le Sender ID contient des caractères non autorisés.

SENDER_ID_NOT_APPROVED

Le Sender ID n'a pas encore été approuvé par les opérateurs.

SENDER_ID_PENDING

Le Sender ID est en cours d'approbation.

SENDER_ID_REJECTED

Le Sender ID a été rejeté par les opérateurs.

MISSING_FIELD

Un champ obligatoire est manquant dans la requĂŞte.

CASCADE_TIMEOUT

Le premier canal a expiré, basculement vers le canal secondaire (cascade).

UPSTREAM_ERROR

Erreur de livraison au niveau de l'opérateur ou de la passerelle.

OPTED_OUT

Le numéro a refusé vos communications (STOP). Envoi interdit.

Limits

Constraints and quotas in the production environment.

OpenAPI YAML
API Requests

100 requests / minute (scalable upon request).

Message Size

1600 characters maximum per message.

Bulk Batch

Up to 10,000 messages per API call.

Log Retention

90 days for detailed reports.