Skip to content
Nofy by Encipher Docs

Sending

Sending on v2

One handoff, any mix of channels. The message shape for SMS, Email, Push and WhatsApp, and how to follow each delivery.

POST /v2/messages accepts one handoff: a tenant, an event type, and one entry per channel. Each entry fans out to one delivery per recipient. Every send needs an Idempotency-Key header (see Authentication); requests over 5 MB are rejected with 413.

JSON
{
  "tenant": "company-uuid-1",
  "event_type": "shift.closed",
  "reference": "shift-8841",
  "callback_url": "https://api.acme.co.tz/hooks/nofy",
  "messages": [
    {
      "channel": "sms",
      "recipients": ["255700000000"],
      "content": {
        "kind": "rendered",
        "body": "Shift closed at 18:00."
      }
    }
  ]
}

Channel and content

Channel Kind Carries
sms rendered body: plain text
email rendered subject, body, optional html and inline_images
push rendered subject, body, optional string map data
whatsapp template An approved template name, language, body_params

kind is checked against the channel: email with template, for example, is a 400 before anything is stored. Unknown fields are rejected rather than silently dropped, so a misspelled callback_url fails loudly instead of losing your status posts.

Channels

JSON
{
  "channel": "sms",
  "recipients": ["255700000000"],
  "content": {
    "kind": "rendered",
    "body": "Shift closed at 18:00."
  }
}

Recipients are E.164 digits; a leading + is accepted and removed. The delivery's provider_message_id carries Beem's request id.

The same send in your language

from ens_sdk import ENS

# ENS_SERVER_URL, ENS_CLIENT_ID, ENS_CLIENT_SECRET, ENS_TENANT
ens = ENS()
ens.send_sms("+255700000000", "Shift closed at 18:00.")

Responses

  • 202: accepted and queued. The body has your reference, the message_id, and one delivery per recipient with its id and status.
  • 400: validation details, unknown tenant, or a bad channel/kind pairing.
  • 401: missing or invalid token. 403: not a client-credentials token.
  • 413: body over 5 MB. 429: tenant or client quota reached.

Reconciling state

GET /v2/deliveries is the authoritative pull for your own records. It is scoped to your client; other clients' rows are never visible.

referencestring

One handoff's deliveries, e.g. ?reference=shift-8841.

updated_sincestring<date-time>

Everything touched since an ISO-8601 instant, e.g. ?updated_since=2026-09-25T10:00:00Z. Every attempt restamps a row, so retries show up here.

cursorlimitstring, integer

Keyset pages of up to 500; follow next_cursor until it is null.

Esc
↑↓ to move↵ to open