PHP SDK

Send SMS, WhatsApp and OTP from PHP with the official SDK

envoisms/envoisms-php is EnvoiSMS.ma's official PHP SDK. One client, one API key: SMS and WhatsApp sends, OTP codes, bulk sends, message status, webhook verification and account balance. It is also the base of the envoisms/laravel-otp Laravel package.

cURL REST API
curl -X POST https://api.envoisms.ma/v1/messages \ -H "Authorization: Bearer env_live_votretoker" \ -H "Content-Type: application/json" \ -d '{ "to": "+212661234567", "message": "Votre code de confirmation est : 849201. Expire dans 3 minutes.", "from": "VOTREMARQUE" }'
● Routes locales MarocIAM • Inwi • Orange
https://api.envoisms.ma/v1
Local Routes
Maroc Telecom (IAM) • Inwi • Orange
Verified DLR Receipts
HMAC-SHA256 Signed
Clear MAD Pricing
dès 0,60 MAD/SMS • 5 MAD offerts

Install and send your first SMS

composer require envoisms/envoisms-php, then $client = new EnvoiSMS\Client(getenv('ENVOISMS_API_KEY')). $client->send(['to' => '+212600000000', 'message' => '…', 'from' => 'MyBusiness']) returns the message id, which you find again with getMessage() and in your webhooks.

  • 'from': your validated Sender ID, or omit it for your default
  • sendBulk(['messages' => [...], 'from' => ...]) for a bulk send
  • getMessage($id) and listMessages(50, 0) to follow your sends

Retry-safe sends and error handling

Every send() and sendBulk() carries an Idempotency-Key, generated or passed as the second argument: a retry after a timeout never bills the same message twice. The client itself retries 5xx responses and cURL errors up to maxRetries times (2 by default) with exponential backoff, then throws EnvoiSMSError with statusCode and errorCode.

  • new Client(getenv('ENVOISMS_API_KEY'), maxRetries: 3, timeoutSeconds: 20)
  • catch (EnvoiSMS\EnvoiSMSError $e): $e->statusCode, $e->errorCode

SMS or WhatsApp: choosing the channel

SMS is the default: it reaches every Moroccan mobile (IAM, Inwi, Orange) with no setup beyond the API key. 'channel' => 'whatsapp' sends from your own WhatsApp Business number: it must be connected (otherwise 403 WHATSAPP_NOT_CONNECTED), and free text is accepted only within 24 hours of the customer's last message (otherwise 400 OUT_OF_24H_WINDOW). Outside that window, send an approved template. Nothing is charged when the API refuses.

  • 'template' => ['name' => 'order_shipped', 'language' => 'fr', 'variables' => ['89240']]
  • 'cascade' => true: automatic fallback to SMS when the number has no WhatsApp

OTP codes and webhooks

$client->sendOtp(['to' => …, 'brand' => 'MyBusiness', 'code_length' => 6, 'expiry' => 600]) returns a session_id; $client->checkOtp($sessionId, $code) returns verified. getOtpSession() reads a session's status without consuming an attempt. For a delivery-status webhook, Client::verifyWebhookSignature($rawBody, $signature, $secret) checks the X-EnvoiSMS-Signature header against the raw request body.

  • 'channel' => 'whatsapp' in sendOtp(): a WhatsApp code through the shared sender, no connection needed
  • getBalance(), listPacks(), createTopup() for the account
  • createOptout($phone) to record a STOP

Everything you need to know about PHP SDK.

How do I verify a delivery webhook in PHP?
Read the raw body with file_get_contents('php://input') — not the decoded array — and pass it to Client::verifyWebhookSignature() with the X-EnvoiSMS-Signature header and your webhook secret. Only process the delivery if verification succeeds.
Can I use the SDK with Laravel?
Yes, directly, or through the envoisms/laravel-otp package, which builds on it and adds a Laravel notification channel and facade.
What happens if my script sends the same SMS twice?
Nothing more: with the same Idempotency-Key, the API returns the original response without sending or billing the message again. A key is valid for 24 hours.

Ready to integrate with PHP SDK?

Create your account in under 2 minutes. Get 5 MAD of free credit instantly to test the API.