WhatsApp, SMS, transactional email, smart routing (auto), sandbox testing, analytics, and outbound logs — all behind one API key.
Last updated: March 2026. Documentation reflects current production behavior.
https://api.notif.mlSend your first message with a single request:
curl -X POST https://api.notif.ml/api/send \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"to": "+1234567890",
"channel": "whatsapp",
"message": "Your order #1234 is ready"
}'torequiredstringE.164 phone (e.g. +22370123456) for whatsapp, sms, or auto. Valid email address when channel is email.
channelrequiredstringwhatsapp — WhatsApp (media supported). sms — SMS (text only). email — transactional email via HTTP (no SMSV key required). auto — route via SMSV (e.g. WhatsApp → SMS → email by availability).
Connecting WhatsApp (SMSV) is required for whatsapp/sms/auto unless you use sandbox mode or email-only sends.
messagerequiredstringBody text. Can be omitted if you use preset with presetVariables or only mediaUrl (WhatsApp).
htmloptionalstringHTML body for email channel. When provided alongside message, the email is sent with both text (plain) and html parts. Ignored for WhatsApp/SMS/auto.
subjectoptionalstringEmail subject line when channel is email (defaults to a generic title if omitted).
sandboxoptionalbooleanWhen true (or header X-Notif-Sandbox: 1, or env NOTIF_SANDBOX=1), no real delivery: response SANDBOX, IDs prefixed sb_. Optional fake webhook events unless sandboxWebhooks: false.
sandboxWebhooksoptionalbooleanIn sandbox mode, set to false to skip simulated message.status webhooks.
presetoptionalstringRenders a built-in template: otp, order_confirmed, order_shipped, delivery_out, appointment_reminder, payment_received. Use with presetVariables.
presetVariablesoptionalobjectKey/value strings passed into the selected preset.
mediaUrloptionalstringURL of an image, video, or document to attach (WhatsApp only)
scheduledAtoptionalstring (ISO date)Schedule sending for later (example: 2026-03-05T14:30:00Z)
senderIdoptionalstringSend from a specific WhatsApp number when your account has multiple senders.
captionoptionalstringCaption for media attachments
templateoptionalstringLegacy field accepted for older clients. Prefer preset for structured templates; this string is ignored on current Partner Cloud routes.
buttonsoptionalarrayLegacy interactive payload; ignored on current routes. Use WhatsApp-native flows via SMSV for rich UI.
{
"to": "+1234567890",
"channel": "whatsapp",
"message": "Here's your invoice",
"mediaUrl": "https://example.com/invoice.pdf",
"caption": "Invoice #1234"
}{
"to": "+1234567890",
"channel": "whatsapp",
"message": "Voice note",
"mediaUrl": "https://example.com/audio.mp3"
}{
"to": "+1234567890",
"channel": "whatsapp",
"message": "Reminder for tomorrow",
"scheduledAt": "2026-03-05T14:30:00Z"
}{
"messages": [
{
"to": "+1234567890",
"channel": "whatsapp",
"message": "Hello #1"
},
{
"to": "+22372830996",
"channel": "whatsapp",
"message": "Hello #2",
"mediaUrl": "https://example.com/video.mp4"
}
],
"continueOnError": true
}{
"to": "customer@example.com",
"channel": "email",
"subject": "Your receipt",
"message": "Thanks for your order — details inside."
}{
"to": "+1234567890",
"channel": "whatsapp",
"message": "Integration test",
"sandbox": true
}{
"to": "+1234567890",
"channel": "whatsapp",
"preset": "order_confirmed",
"presetVariables": {
"orderId": "A-1024",
"customerName": "Awa"
}
}{
"to": "+1234567890",
"channel": "whatsapp",
"message": "Your order is ready for pickup",
"template": "order_ready",
"buttons": [
{ "type": "reply", "text": "On my way" },
{ "type": "reply", "text": "Reschedule" }
]
}Legacy template / buttons are accepted for backward compatibility; prefer preset for structured copy.
Use your API key in either Authorization or X-API-Key header:
Authorization: Bearer YOUR_API_KEYX-API-Key: YOUR_API_KEY/api/sendSend WhatsApp, SMS, email, or auto-routed messages (same auth as below).
/api/send/batchSend up to 100 messages in one request (per-item results; supports the same fields as /api/send).
/api/status/:messageIdRetrieve message status (mainly used by dashboard and advanced integrations).
Same authentication as POST /api/send: X-API-Key: ntf_live_… or Bearer, or an authenticated dashboard session.
/api/notif-analyticsAggregates over recent outbound history (Convex). Optional query sample (50–500, default 200) controls sample size.
Example: curl -H "X-API-Key: YOUR_KEY" https://api.notif.ml/api/notif-analytics
/api/notif-logsPaginated-style list of recent outbound messages for your API key. Query limit (1–200, default 50).
Example: curl -H "X-API-Key: YOUR_KEY" "https://api.notif.ml/api/notif-logs?limit=50"
Use sandbox to integrate without connecting WhatsApp/SMSV: no carrier traffic, predictable SANDBOX responses and optional synthetic webhook events.
"sandbox": trueX-Notif-Sandbox: 1NOTIF_SANDBOX=1 (global)Keys prefixed ntf_test_ still return the historical TEST stub without hitting SMSV; sandbox complements that for ntf_live_ keys.
When daily quota is exceeded, POST /api/send returns 429 with messagesUsed, limit, and upgradeUrl.
If your account has a per-recipient daily cap configured, sends to the same phone/email may return 429 with recipientLimit when that cap is reached.
Plan limits and usage for the dashboard are also available on GET /api/me (session cookie).
Store a webhookUrl on your notif.ml user record. When set, notif.ml POSTs delivery and inbound events to your HTTPS endpoint. Authenticated GET /api/me returns the current URL; contact support or use your admin path to update it until self-serve settings ship in the dashboard.
message.status - sent, delivered, failed updates.message.received - inbound WhatsApp messages from your connected number.{
"event": "message.received",
"messageId": "wamid.HBg...",
"from": "+22370000000",
"to": "+22372830996",
"channel": "whatsapp",
"type": "text",
"text": "Bonjour",
"timestamp": "2026-03-04T13:37:00.000Z"
}