notimba

API documentation

One authenticated call sends a notification across in-app, email, SMS and WhatsApp. Notimba picks the provider, handles failover and reports delivery back onto the message.

Quickstart

Create an account and copy your API key (shown once). Then send your first message:

curl -X POST https://notimba.informationvillagelimited.com/api/notify \
  -H "Authorization: Bearer ntb_yourkey..." \
  -H "Content-Type: application/json" \
  -d '{
    "event": "order.confirmed",
    "recipient": { "user_ref": "cust_8812", "phone": "+256772123456" },
    "body": "Payment of UGX 45,000 received."
  }'

A 202 comes back with one message id per resolved channel. That is the whole integration.

Authentication

Every request carries your key as a bearer token:

Authorization: Bearer ntb_<8 chars>_<32 chars>

Keys are shown once at signup and stored only as a hash - a lost key is replaced, never recovered. Failed authentication is always a uniform 401, and repeated failures from one address are rate limited.

Send a notification

POST/api/notify

FieldTypeNotes
eventstring, requiredYour name for what happened, e.g. order.confirmed.
recipient.user_refstring, requiredYour stable id for the person. Keys the in-app feed and opt-outs.
recipient.emailstring, optionalEnables the email channel for this send.
recipient.phonestring, optionalEnables SMS (and WhatsApp when requested). Use +256... format.
channelsstring[], optionalSubset of in_app, email, sms, whatsapp. Omitted = in_app + email + sms where contact exists.
reply_tostring, optionalReply-To address on the email channel, so replies reach a human instead of the sender identity.
subjectstring, optionalEmail subject and in-app title.
bodystring, optionalThe message text, all channels.

Response, always one id per channel that resolved:

HTTP 202
{ "message_ids": ["82d42c8f-...", "2fd71914-..."] }

Channels

ChannelFires whenNotes
in_appAlwaysWritten to the feed your product pulls. Never billed.
emailrecipient.email presentWarmed sending path, no SMTP setup. Free tier: a fair daily share of the shared pool (at least 10 a day, 10 a day for your first week), then402 quota_exhausted until the UTC day resets.
smsrecipient.phone presentNetwork-aware routing across Ugandan providers with automatic failover. Prepaid only: without credits every SMS is 402 wallet_required. Uganda (+256) numbers only.
whatsappExplicitly requested + phone present + enabled for your accountMeta Cloud API with delivery and read receipts. On request: call POST /api/channels/whatsapp/request and we configure your sender, until then it is 403 channel_not_enabled.
WhatsApp is opt-in per message: it only fires when your channels array names it, so adding a phone number to a request never triggers an unexpected WhatsApp send.
{ "channels": ["whatsapp"], ... }   // WhatsApp only
{ "channels": ["sms", "whatsapp"], ... }  // both
Request WhatsApp for your account once. We reply by email when your sender is configured and the channel is switched on.
curl -X POST https://notimba.informationvillagelimited.com/api/channels/whatsapp/request \
  -H "Authorization: Bearer $NOTIMBA_KEY" \
  -H "Content-Type: application/json" \
  -d '{"note":"OTP and order updates, ~2k/month"}'
# 202 { "status": "requested", "request_id": "..." }

Message status

GET/api/messages/:id

Look up any message id from a send. Statuses move queuedsent delivered as provider receipts arrive; failures land on bounced (rejected) or undelivered (retries exhausted). Messages belonging to another tenant are a 404, indistinguishable from nonexistent ones.

In-app feed

GET/api/notifications?user_ref=cust_8812

Pull a user's notifications to render an inbox or a bell badge. Delivery is asynchronous: a notification appears in the feed within a few seconds of the 202, not in the same instant. Mark one read with:

POST/api/notifications/:id/read

Idempotency

Send an Idempotency-Key header to make retries safe: the same key, tenant and channel never creates a second message, you get the original ids back. Keys are limited to 255 characters.

curl -X POST https://notimba.informationvillagelimited.com/api/notify \
  -H "Authorization: Bearer ntb_yourkey..." \
  -H "Idempotency-Key: order-8812-confirmed" \
  ...

Errors and limits

StatusShapeMeaning
401{ "error": "unauthorized" }Missing, malformed or wrong key.
422{ "error": "validation_error", "fields": { "recipient.user_ref": [...] } }Invalid body. Fields are keyed by full dotted path.
429{ "error": "rate_limited" }Per-tenant burst limit or repeated auth failures. Back off and retry.
404{ "error": "not_found" }Unknown id, or a resource that is not yours.
402{ "error": "wallet_required", "channel": "sms" }SMS is prepaid. Top up before sending.
402{ "error": "quota_exhausted", "channel": "email", "reason": "share", "share": 60, "used": 60 }Your free email share for this UTC day is spent. reason is share, ramp (first week) or pool_full.
403{ "error": "email_unverified" }Click the verification link we emailed at signup before sending.
403{ "error": "channel_not_enabled", "channel": "whatsapp" }WhatsApp is not switched on for your account yet. Request it above.
403{ "error": "channel_disabled", "channel": "email" }Sending on this channel was paused for your account after bounce or complaint rates crossed the limit. We email you when this happens.
202{ "message_ids": [...], "skipped": [{ "channel": "email", "reason": "suppressed" }] }The recipient previously bounced or complained, so that channel was skipped. Other channels in the request still went out.

Need a higher limit or a channel configured for your account? ivilleinc@gmail.com