EnvoiSMS Python SDK
Official Python SDK for EnvoiSMS.ma — the direct-operator SMS, WhatsApp Business (WABA) and OTP verification API platform for Morocco (Maroc). One client, one API key, four channels.
pip install envoisms
What is EnvoiSMS.ma?
EnvoiSMS.ma routes transactional and marketing messages through direct connections to Morocco's three mobile operators, plus the official WhatsApp Cloud API — no aggregator, no gray SIM routes.
| Channel | What it's for | Covered by this SDK |
|---|---|---|
| SMS Direct Opérateurs — IAM, Inwi, Orange | OTP codes, delivery alerts, marketing SMS, from 0.48 MAD/SMS | ✅ send(), send_bulk() |
| WhatsApp Business API (Meta WABA) | Approved templates, interactive buttons, catalog, multi-agent inbox, from 0.65 MAD/message | ✅ send(channel="whatsapp") |
| OTP / 2FA Verification | Send + check one-time codes over SMS or WhatsApp | ✅ send_otp(), check_otp() |
| Numéro Virtuel (+212) | Cloud Moroccan business line, no physical SIM, shared team inbox | Manage from the dashboard |
| Assistant IA Conversationnel | Darija/French AI agent for COD order confirmation & support handoff | Manage from the dashboard |
Numéros Virtuels and the AI assistant are configured from your EnvoiSMS.ma dashboard today; dedicated SDK endpoints for them are on the roadmap. Everything below (send, OTP, billing, webhooks) works with the SDK right now.
Quick Start — Send an SMS
import os
from envoisms import EnvoiSMSClient
client = EnvoiSMSClient(api_key=os.getenv("ENVOISMS_API_KEY"))
response = client.send(
to="+212600000000",
message="Votre code de vérification est 492018",
from_sender="MonBusiness", # validated Sender ID, or omit to use your default
)
print(f"Message ID: {response['id']}")
Send a WhatsApp Business Message
Same client, same method — just switch the channel. Requires WhatsApp connected in your dashboard.
response = client.send(
to="+212600000000",
message="Bonjour ! Votre commande #89240 a été expédiée.",
channel="whatsapp",
)
Automatic channel fallback (cascade)
Send over WhatsApp and drop back to SMS automatically when a number is unreachable or has no WhatsApp — the same fallback used for VTC riders on flaky mobile data.
response = client.send(
to="+212600000000",
message="Votre chauffeur arrive dans 2 minutes.",
channel="whatsapp",
cascade=True,
)
OTP / 2FA Verification
# 1. Send OTP (channel="sms" by default; pass channel="whatsapp" to send over WhatsApp instead)
otp_res = client.send_otp(
to="+212600000000",
brand="MonBusiness",
code_length=6,
expiry=600, # seconds
)
session_id = otp_res["session_id"]
# 2. Verify the code the user typed in
check_res = client.check_otp(session_id=session_id, code="492018")
if check_res.get("verified"):
print("OTP code is valid!")
# Optional: inspect a session's status without consuming an attempt
session = client.get_otp_session(session_id)
Bulk Sending
client.send_bulk(
messages=[
{"to": "+212600000001", "message": "Promo -20% ce week-end"},
{"to": "+212600000002", "message": "Promo -20% ce week-end"},
],
from_sender="MonBusiness",
)
Message Status & Delivery
status = client.get_message(message_id="msg_123")
recent = client.list_messages(limit=50, offset=0)
Verifying Delivery Webhooks (DLR)
If you configure a delivery-status webhook, verify its X-EnvoiSMS-Signature header before trusting the payload:
from envoisms import EnvoiSMSClient
is_valid = EnvoiSMSClient.verify_webhook_signature(
raw_body=request.body, # raw request bytes/string, not parsed JSON
signature_header=request.headers["X-EnvoiSMS-Signature"],
secret=os.getenv("ENVOISMS_WEBHOOK_SECRET"),
)
Account & Billing
balance = client.get_balance()
packs = client.list_packs()
payment_methods = client.list_payment_methods()
client.create_topup(amount_mad=200, payment_method="stripe")
Analytics & API Keys
stats = client.analytics(days=30)
new_key = client.create_api_key(name="Server key", scope="live")
Compliance: Opt-outs (STOP)
client.create_optout(phone="+212600000000")
Error Handling & Retries
The client retries 5xx responses and network errors up to max_retries times (default 2) with exponential backoff, and raises EnvoiSMSError — with status_code and code attributes — on any failure:
from envoisms import EnvoiSMSClient, EnvoiSMSError
client = EnvoiSMSClient(api_key=os.getenv("ENVOISMS_API_KEY"), max_retries=3, timeout=20)
try:
client.send(to="+212600000000", message="Test")
except EnvoiSMSError as e:
print(f"Send failed ({e.status_code} {e.code}): {e}")
Why teams pick EnvoiSMS.ma over an aggregator
- Direct routes to IAM, Inwi and Orange — no international transit hop, no gray-route ban risk.
- Sub-2-second OTP latency, measured — aggregators routing through Europe typically land in the 10s+ range.
- Billing in MAD, no EUR/USD conversion surprises.
- Local support based in Casablanca, not an offshore ticket queue.
See the full breakdown on envoisms.ma.
Documentation & Pricing
- Full API reference: envoisms.ma/fr/docs
- Pricing & credit packs: envoisms.ma/fr/tarifs
- Real customer use cases: envoisms.ma/fr/cas-usage
- Create a free account (5 MAD credit included): envoisms.ma/fr/register
Other official SDKs
- Node.js / TypeScript:
npm install envoisms - PHP:
composer require envoisms/envoisms-php - WooCommerce, Shopify, Zapier and Google Sheets integrations: envoisms.ma/fr/integrations
Support
- Email: support@envoisms.ma
- Sales: sales@envoisms.ma
License
MIT
Release files for envoisms 1.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| envoisms-1.1.0.tar.gz | 7.8 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| envoisms-1.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 15.3 kB
Release files / envoisms-1.1.0.tar.gz
| Download URL | envoisms-1.1.0.tar.gz |
|---|---|
| Size | 7.8 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
921e0bb3d9ecdc8c0fc9f4e5e3e64f6c036769a39e28034d4f8c80c7d1574787
|
|
BLAKE2b-256 checksum How to use checksums |
77ec3115ffc1c95b051d0818151789e8843d088e5e32e922938bb8b036fe37d3
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.6
|
Release files / envoisms-1.1.0-py3-none-any.whl
| Download URL | envoisms-1.1.0-py3-none-any.whl |
|---|---|
| Size | 7.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
28bdf47ac081131d212ab5e5b3e453da144321ffe81b4d5b87a55089099c0c36
|
|
BLAKE2b-256 checksum How to use checksums |
72505cc6aa878556ddff43fd2287cc795231891d0adde381155e5f52d6086ca7
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.6
|