Get started
Running your numbers
What happened to your sends, the files you hold, your contacts, the profile of a number, and finding things fast.
Delivery statistics
GET /stats/delivery counts what became of the messages you sent: sent, delivered, read, replied, failed and skipped, per day and per template (source=template, the default) or per broadcast (source=broadcast). The default period is the last 30 days; it cannot exceed 366 days. previous holds the same counts for the period of equal length just before, to compare. channelId narrows it to one number.
sentcounts every message whose sending was attempted, failures included.deliveredincludesread.repliedcounts messages after which the contact wrote within 24 hours.skippedcounts the recipients a broadcast left out before sending (no consent, no number); it is 0 for templates.- A message is counted on the day it was sent (UTC), with its current status: the exact time of a read is not kept.
curl "https://nodium.io/api/v1/stats/delivery?source=template&from=2026-09-01T00:00:00Z" \ -H "Authorization: Bearer $NODIUM_KEY"# → data.totals { sent, delivered, read, replied, failed, skipped },# data.previous (the period of equal length just before),# data.days[] and data.groups[] (per template, or per broadcast)Media
GET /medialists the files Nodium kept a copy of — images, videos, sounds, documents — most recent first. Filter bykind(image,video,audio,document) and byfrom/to; cursor pagination.- Download one with
GET /messages/{messageId}/media.DELETE /media/{id}(the id of the message that carries the file) removes Nodium's copy; the message stays. It cannot be recovered afterwards: WhatsApp deletes received media after seven days.
Contacts export
GET /contacts/export returns the contacts of the client as a CSV file (UTF-8) — not wrapped in data — with the same filters as GET /contacts (q, consent, blocked, channel). At most 10,000 rows: narrow the filters beyond that. Columns: id, name, phone, email, external_id, consent (in, out, unknown), blocked, conversations, created_at, updated_at.
Business profile of a number
GET /channels/{id}/profile reads what people see when they open the business profile: about, description, address, email, up to two websites, vertical (business category) and pictureUrl (read-only). It is read from Meta on every call. PATCH /channels/{id}/profile changes the fields you send and leaves the others alone; websites is replaced as a whole, an empty vertical clears the category. The shared sandbox number cannot be changed. Meta's limits apply (422 invalid_request); a refusal from Meta is 502 upstream_error.
curl -X PATCH https://nodium.io/api/v1/channels/<channel id>/profile \ -H "Authorization: Bearer $NODIUM_KEY" \ -H "Content-Type: application/json" \ -d '{ "about": "Opticians since 1987", "email": "contact@example.com", "websites": ["https://example.com"], "vertical": "HEALTH" }'GET /channels/{id} returns one channel with its quality rating, messaging tier and the result of the last health check (POST /channels/{id}/check).
Connect links
GET /connect-links lists the hosted links of your account and where each stands; DELETE /connect-links/{id} revokes one that is still pending. Creating one is POST /tenants/{id}/connect-links: see Your clients.
Search
GET /search?q= (2 to 100 characters) finds contacts (name, phone number, email), templates (name), channels (name, number) and — for a key that sees every client — clients (name or your externalId). A handful per family: it is for finding one thing fast; the list routes return everything.
The journal, filtered
GET /journal also filters messages by direction (inbound or outbound) and by channel; the other kinds of lines have neither and are left out when you use them.