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

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 (example: 2026-03-05T14:30:00Z)

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.

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

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

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

Endpoints

POST/api/send

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

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

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.