Authentication
How to authenticate channel-sending requests and AI Gateway requests.
Mersal's API uses two separate authentication mechanisms, depending on which endpoint family you're calling. They use different key types generated in different places in the dashboard, and are not interchangeable.
Channel-sending endpoints (Api-key)
POST /api/sms/send, POST /api/whatsapp/send, POST /api/email/send, and their corresponding GET /api/get/{channel}/{id?} lookup endpoints authenticate with your personal API key. Mersal checks for the key in this order:
- Header
Api-key: <your-api-key>(recommended) - Query parameter
?api_key=<your-api-key> - POST body field
api_key
Not a Bearer token
The header name is genuinely Api-key, not Authorization: Bearer. Don't use Bearer-token style for the channel-sending endpoints — that style is reserved for the AI Gateway only.
Finding your API key
Open your account settings
Sign in to the Mersal dashboard and open your account settings.
Open the API key page
Your personal API key is displayed there, and can be regenerated at any time.
Store it securely
Treat it like a password — anyone with this key can send messages and spend your account's sending credits. Keep it in an environment variable, never in your code. See API Key Management.
Example in every language
curl -X POST https://mersal.it/api/sms/send \
-H "Api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"contact":[{"number":"+201234567890","message":"Hello from Mersal"}]}'<?php
$ch = curl_init('https://mersal.it/api/sms/send');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Api-key: ' . getenv('MERSAL_API_KEY'),
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => json_encode([
'contact' => [
['number' => '+201234567890', 'message' => 'Hello from Mersal'],
],
]),
]);
$response = json_decode(curl_exec($ch), true);
curl_close($ch);const response = await fetch("https://mersal.it/api/sms/send", {
method: "POST",
headers: {
"Api-key": process.env.MERSAL_API_KEY,
"Content-Type": "application/json",
},
body: JSON.stringify({
contact: [{ number: "+201234567890", message: "Hello from Mersal" }],
}),
});
const data = await response.json();import os
import requests
response = requests.post(
"https://mersal.it/api/sms/send",
headers={"Api-key": os.environ["MERSAL_API_KEY"]},
json={"contact": [{"number": "+201234567890", "message": "Hello from Mersal"}]},
)
data = response.json()Subscription requirement
Channel-sending endpoints require an active subscription/plan on your account. If your plan has expired, every request returns 403 regardless of whether the API key itself is valid:
{
"status": "error",
"error": "Your Subscription Is Expired! Buy A New Plan"
}AI Gateway (Bearer token)
POST /api/ai/v1/chat/completions and GET /api/ai/v1/models use a different key type: an AI Pool key, created specifically for AI Gateway access, sent as a standard Bearer token:
Authorization: Bearer <ai-pool-key>curl https://mersal.it/api/ai/v1/chat/completions \
-H "Authorization: Bearer YOUR_AI_POOL_KEY" \
-H "Content-Type: application/json" \
-d '{"messages":[{"role":"user","content":"Hello"}]}'AI Pool keys are generated separately from your channel API key — look for the AI Pool / AI Gateway section of the dashboard. See AI Gateway: Chat Completions for the full request/response contract.
Error responses
| Scenario | Status | Body |
|---|---|---|
| API key missing (channel endpoints) | 403 | {"status":"error","message":"API key is required. Provide via header (Api-key) or URL parameter (api_key)","error":"Invalid Api Key"} |
| API key invalid (channel endpoints) | 403 | {"status":"error","error":"Invalid Api Key"} |
| Subscription expired | 403 | {"status":"error","error":"Your Subscription Is Expired! Buy A New Plan"} |
For the full list of error conventions, see Errors and Status Codes.
