notif.ml|Documentation
Dashboard →

API Documentation

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.

Base URL
https://api.notif.ml

CLI

Send quick WhatsApp, email, and scheduled messages from your terminal with notifml-cli.

npm i -g notifml-cli
notif init --key ntf_live_xxx --to +22370000000
notif me "Build failed on prod"
notif "Ship done"
notif send +22370000000 "Check ASAP"
notif run -- npm run build
notif balance
notif doctor
notif me --at "in 10m" "Check deploy"

Frequent recipients stay as local aliases in your terminal config, so Notif remains a lightweight notification API instead of duplicating SMSV contacts and campaigns.

notif alias set boss +22370000000
notif send boss "Besoin de ton retour"
notif boss "Besoin de ton retour"
tail -n 30 error.log | notif me --title "Prod error"

Developers can inspect their local key, account, usage, and credit balance without opening the dashboard.

notif whoami
notif key
notif key --show
notif balance --transactions
notif status ntf_msg_xxx
notif logs --limit 10

Quick example

Send your first message with a single request:

POST/api/send
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"
  }'

Request parameters

torequiredstring

E.164 phone (e.g. +22370123456) for whatsapp, sms, or auto. Valid email address when channel is email.

channelrequiredstring

whatsapp — 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.

messagerequiredstring

Body text. Can be omitted if you use preset with presetVariables or only mediaUrl (WhatsApp).

htmloptionalstring

HTML body for email channel. When provided alongside message, the email is sent with both text (plain) and html parts. Ignored for WhatsApp/SMS/auto.

subjectoptionalstring

Email subject line when channel is email (defaults to a generic title if omitted).

sandboxoptionalboolean

When 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.

sandboxWebhooksoptionalboolean

In sandbox mode, set to false to skip simulated message.status webhooks.

presetoptionalstring

Renders a built-in template: otp, order_confirmed, order_shipped, delivery_out, appointment_reminder, payment_received. Use with presetVariables.

presetVariablesoptionalobject

Key/value strings passed into the selected preset.

mediaUrloptionalstring

URL of an image, video, or document to attach (WhatsApp only)

scheduledAtoptionalstring (ISO date)

Schedule sending for later. Future dates return 202 SCHEDULED and can be tracked with /api/status/:messageId (example: 2026-03-05T14:30:00Z)

retryoptionalboolean | object

Retry provider delivery before marking a message failed. Use { maxAttempts: 3, delayMs: 1000 } for critical alerts.

senderIdoptionalstring

Send from a specific WhatsApp number when your account has multiple senders.

captionoptionalstring

Caption for media attachments

templateoptionalstring

Legacy field accepted for older clients. Prefer preset for structured templates; this string is ignored on current Partner Cloud routes.

buttonsoptionalarray

Legacy interactive payload; ignored on current routes. Use WhatsApp-native flows via SMSV for rich UI.

groupIdoptionalstring

WhatsApp group ID (format xxx@g.us) to send to a WhatsApp group instead of an individual contact. When provided, to is still required for internal tracking but the message is delivered to the group. Use GET /api/partner/whatsapp/groups to list available groups.

Examples

Send with media

{
  "to": "+1234567890",
  "channel": "whatsapp",
  "message": "Here's your invoice",
  "mediaUrl": "https://example.com/invoice.pdf",
  "caption": "Invoice #1234"
}

Send audio/video

{
  "to": "+1234567890",
  "channel": "whatsapp",
  "message": "Voice note",
  "mediaUrl": "https://example.com/audio.mp3"
}

Schedule a message

{
  "to": "+1234567890",
  "channel": "whatsapp",
  "message": "Reminder for tomorrow",
  "scheduledAt": "2026-03-05T14:30:00Z"
}

The API returns 202 with status: "SCHEDULED"; the message is sent automatically when due.

Batch send

{
  "messages": [
    {
      "to": "+1234567890",
      "channel": "whatsapp",
      "message": "Hello #1"
    },
    {
      "to": "+22372830996",
      "channel": "whatsapp",
      "message": "Hello #2",
      "mediaUrl": "https://example.com/video.mp4"
    }
  ],
  "continueOnError": true
}

Transactional email

{
  "to": "customer@example.com",
  "channel": "email",
  "subject": "Your receipt",
  "message": "Thanks for your order — details inside."
}

Send to WhatsApp group

{
  "to": "+22372830996",
  "groupId": "120363123456789@g.us",
  "channel": "whatsapp",
  "message": "Hello team! Meeting at 3pm"
}

Sandbox dry-run

{
  "to": "+1234567890",
  "channel": "whatsapp",
  "message": "Integration test",
  "sandbox": true
}

Preset template

{
  "to": "+1234567890",
  "channel": "whatsapp",
  "preset": "order_confirmed",
  "presetVariables": {
    "orderId": "A-1024",
    "customerName": "Awa"
  }
}

Legacy fields (template/buttons)

{
  "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.

Authentication

Use your API key in either Authorization or X-API-Key header:

Authorization: Bearer YOUR_API_KEY
X-API-Key: YOUR_API_KEY

WhatsApp Groups

Send messages to WhatsApp groups your connected number is a member of.

GET/api/partner/whatsapp/groups

List all WhatsApp groups your connected number is a member of.

Example: curl -H "X-API-Key: YOUR_KEY" https://api.notif.ml/api/partner/whatsapp/groups

{
  "success": true,
  "groups": [
    { "id": "120363123456789@g.us", "name": "Team Dev", "participants": 12, "isAdmin": true },
    { "id": "120363987654321@g.us", "name": "Marketing", "participants": 25, "isAdmin": false }
  ],
  "count": 2
}

Use the id from this response as groupId in POST /api/send.

Endpoints

POST/api/send

Send WhatsApp, SMS, email, or auto-routed messages (same auth as below). Supports group messages via groupId.

POST/api/send/batch

Send up to 100 messages in one request (per-item results; supports the same fields as /api/send).

GET/api/status/:messageId

Retrieve message status (mainly used by dashboard and advanced integrations).

GET/api/me

Retrieve the authenticated developer profile, masked/public key metadata, current plan, daily usage, credit balance, recent messages, and webhook settings.

GET/api/credits

Retrieve plan quota, usage today, credit balance, channel prices, and recent credit transactions.

Analytics & outbound logs

Same authentication as POST /api/send: X-API-Key: ntf_live_… or Bearer, or an authenticated dashboard session.

GET/api/notif-analytics

Aggregates 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

GET/api/notif-logs

Paginated-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"

Sandbox mode

Use sandbox to integrate without connecting WhatsApp/SMSV: no carrier traffic, predictable SANDBOX responses and optional synthetic webhook events.

  • JSON "sandbox": true
  • Header X-Notif-Sandbox: 1
  • Server env NOTIF_SANDBOX=1 (global)

Keys prefixed ntf_test_ still return the historical TEST stub without hitting SMSV; sandbox complements that for ntf_live_ keys.

Rate limits & HTTP 429

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).

Webhooks

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.

Events
  • 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"
}
Mobile apps: see Mobile SDKs. Billing & FCFA credits: Billing guide. For CRM, campaigns, and AI, explore SMSV.