# EnvoiSMS - Morocco Developer SMS & WhatsApp Platform — Full Developer Spec > This file contains the complete developer specification, architecture blueprints, database schemas, and API routes designed for high-context ingestion by AI agents and LLMs. --- ## Architecture & Integration Blueprints ### System Architecture The platform operates on a robust Cloudflare-native stack: - **Cloudflare Workers** (`workers/api/index.ts`): High-performance routing, authentication, queue dispatch, and rate-limiting. - **D1 Database**: Stores stateful relational data (accounts, messages, api keys, contacts). - **KV Storage**: Stores high-throughput transient state like OTP verification codes and burst rate-limits. - **Cloudflare Queues**: Manages asynchronous message delivery pipelines (`workers/api/upstream.ts`) with automated retry semantics. ### Moroccan Carrier Integration & Fallback Cascade The unified `/v1/messages` endpoint accepts E.164 numbers (e.g. `+2126...` or `+2127...`) and normalizes prefixes. - **IAM (Maroc Telecom), Orange Maroc, Inwi**: All three primary operators are directly supported. - **Fallback Logic (`cascade: true`)**: When enabled, the system initially attempts secure WhatsApp delivery (if configured/authorized). If unreachable or unread, it automatically degrades to high-priority SMS delivery over premium DLR routes. --- ## Database Schemas (D1 SQLite) Below are the primary core tables you can model your SDKs against: ### 1. `messages` Tracks every dispatched message and state. ```sql CREATE TABLE IF NOT EXISTS messages ( id TEXT PRIMARY KEY DEFAULT (lower(hex(randomblob(16)))), account_id TEXT NOT NULL REFERENCES accounts(id) ON DELETE CASCADE, api_key_id TEXT REFERENCES api_keys(id), "to" TEXT NOT NULL, channel TEXT NOT NULL, -- sms|whatsapp|telegram body TEXT NOT NULL, sender_id TEXT, status TEXT NOT NULL DEFAULT 'queued', -- queued|sent|delivered|failed|undeliverable error_code TEXT, error_message TEXT, cost_eur REAL DEFAULT 0, cost_mad REAL DEFAULT 0, created_at TEXT NOT NULL DEFAULT (datetime('now')) ); ``` ### 2. `verify_sessions` High-speed OTP state storage. ```sql CREATE TABLE IF NOT EXISTS verify_sessions ( id TEXT PRIMARY KEY DEFAULT (lower(hex(randomblob(16)))), account_id TEXT NOT NULL REFERENCES accounts(id) ON DELETE CASCADE, "to" TEXT NOT NULL, channel TEXT NOT NULL, code_hash TEXT NOT NULL, status TEXT DEFAULT 'pending', -- pending|verified|expired|failed attempts INTEGER DEFAULT 0, max_attempts INTEGER DEFAULT 3, expires_at TEXT NOT NULL, verified_at TEXT, created_at TEXT NOT NULL DEFAULT (datetime('now')) ); ``` --- ## Core API Routes All endpoints must use `Authorization: Bearer ` and the prefix `https://api.envoisms.ma/v1`. ### 1. `POST /v1/messages` Send an SMS or WhatsApp message. **Payload:** ```json { "to": "+212612345678", "message": "Votre validation EnvoiSMS est 849302.", "channel": "sms", "from": "EnvoiSMS" } ``` ### 2. `POST /v1/messages/bulk` Send batches of up to 10,000 messages. **Payload:** ```json { "channel": "sms", "messages": [ { "to": "+212612345678", "message": "Message 1" }, { "to": "+212687654321", "message": "Message 2" } ] } ``` ### 3. `POST /v1/verify/send` Generate and dispatch an OTP code. **Payload:** ```json { "to": "+212612345678", "channel": "sms", "code_length": 6, "brand": "AppSecurise" } ``` ### 4. `POST /v1/verify/check` Validate an OTP session. **Payload:** ```json { "session_id": "abc123xyz...", "code": "849302" } ``` ### 5. `GET /v1/billing/packs` Retrieve active prepaid SMS tiers (e.g. `sms-1000` for 380 MAD / 34.55 EUR). ### 6. `POST /v1/billing/topups` Generate a Stripe or CashPlus invoice. Provide `"pack_id": "sms-1000"` or `"amount_eur": 50`. --- ## SDK Integration Examples ### Node.js (fetch) ```javascript const response = await fetch('https://api.envoisms.ma/v1/messages', { method: 'POST', headers: { 'Authorization': 'Bearer YOUR_API_KEY', 'Content-Type': 'application/json' }, body: JSON.stringify({ to: '+212612345678', message: 'Hello from Node.js!', channel: 'sms' }) }); const data = await response.json(); ``` ### Python (requests) ```python import requests url = "https://api.envoisms.ma/v1/verify/send" headers = { "Authorization": "Bearer YOUR_API_KEY", "Content-Type": "application/json" } payload = { "to": "+212612345678", "channel": "sms", "brand": "PythonApp" } response = requests.post(url, json=payload, headers=headers) print(response.json()) ```