Skip to content
Get an API key

Get started

CLI

The nodium command: check your setup, read your numbers and conversations, ship templates and webhooks, and replay events to your machine.

@nodium.io/cli is a thin layer over the TypeScript SDK: every command calls one of its methods, with the same key, the same client header and the same errors. Node 20 or later.

Install and log in

Shell

npm install -g @nodium.io/cli # or: npx @nodium.io/cli <command>nodium login # paste your key (nod_…): kept in ~/.config/nodium, readable by you onlynodium status # what the key is, your numbers, your webhooks, the next step
  • The key is looked up in this order: --key, then NODIUM_KEY, then the file saved by nodium login. It is never printed in full; nodium logout deletes the file.
  • --tenant <id or externalId> acts for one of your clients, like the Nodium-Tenant header. Without it, a command acts on My company, or on the client the key is pinned to.
  • nodium help <command> (or --help) describes each command and its options.

Check your setup

Shell

$ nodium statusAuthentication: authenticatedKey: nod_1a2b… "ci", never expiresAccount: Acme (acc_…)Access: every client of the accountClients: 12WhatsApp Numbers: 3 (3 on)Webhooks: 1 active of 1Next: nodium numbers list nodium send --channel <id> --to <+33…> --text "Hello"
  • nodium status says which key is used, its account, what it reaches (every client of the account, or the client it is pinned to), your clients and numbers, your webhooks, and what to run next.
  • Clients shows only for a key that is not pinned: a pinned key cannot list the other clients.
  • Webhooks: not visible with this key (pinned to My company): the subscriptions of My company receive every client's events, so a key pinned to My company cannot read them. Use a key that is not pinned to see or manage them.

Read

  • nodium numbers list · numbers get <id> · numbers check <id> — your numbers, and a fresh check at Meta.
  • nodium conversations list · conversations get <id> · messages list <conversationId> · messages get <id>.
  • nodium contacts list · contacts get <id> · templates list · templates get <id>.
  • nodium webhooks list · webhooks deliveries --failed · tenants list · tenants get <id>.
  • nodium events --after <seq> reads the event log; nodium health exits 1 when a number needs attention.
  • Lists show the newest 20; --limit <n> shows more, following the pages for you.

Write

Shell

nodium templates new --input order_ready.json # a draft: nothing goes to Meta yetnodium templates deploy tpl_123 # asks "Proceed? [y/N]"nodium templates wait tpl_123 --timeout 10m # exit 0 approved, 1 refused or timed outnodium send --channel ch_123 --to +33612345678 --template order_ready --language en --var 1=Karim
  • nodium send takes --text or --template; any other message (a file by mediaId, buttons, a list, a location) as the JSON of POST /messages, with --input <file.json> or --stdin. A send Meta refuses exits 1.
  • nodium templates new|update --input <file.json>, deploy, refresh, wait, delete.
  • nodium webhooks new --url <https://…> --event message.received prints the signing secret once; also update, delete, test, redeliver <deliveryId>, rotate-secret.
  • nodium tenants new --name "Agence Horizon" --external-id crm-4187 --connect-link adds a client and prints the link to send it; nodium connect-link new --tenant <id> makes a new one.
  • nodium flows deploy flow.json creates a draft Flow at Meta (--id <flowId>: a new version of a draft) and prints Meta's validation problems with their line. --publish publishes it only when there are none — publishing is final.

Approval before a write

A command that sends or changes something — send, templates deploy|delete, webhooks new|update|delete|redeliver|rotate-secret, tenants new, connect-link new, flows deploy — says what it is about to do and asks Proceed? [y/N]. Outside a terminal there is nobody to ask: it refuses with exit code 2 unless you pass --yes.

Scripts and AI agents

Shell

# Piped, every command prints the API's object as JSONnodium conversations list --limit 5 | jq '.[].contact.identity'# Outside a terminal, a command that sends or changes something needs --yesecho '{"channelId":"ch_123","to":"+33612345678","type":"text","text":"Hello"}' \ | nodium send --stdin --yes# A refusal goes to stderr, as JSON, with exit code 1# { "error": { "status": 404, "code": "not_found", "message": "…", "requestId": "req_…" } }
  • --output json|human. The default is human in a terminal, ending with a Next: block of the commands that usually follow, and json when the output is piped — what a script or an agent sees. JSON is the object the SDK returns, unchanged.
  • Exit codes: 0 done, 1 refused by Nodium or Meta (or a template refused, a Flow with problems), 2 a wrong command line or a missing approval.
  • For an agent: read first (status, numbers list, templates get), show the person what will be sent, and pass --yes only once they agreed. Give the agent a key pinned to one client.

Develop locally

Shell

export NODIUM_KEY=nod_…npx @nodium.io/cli listen \ --forward http://localhost:3000/webhook \ --secret whsec_… \ --events message.received,message.failed# 10:32:01 message.received 200 12 ms evt_5f1c0a9e…# 10:32:07 message.failed 500 4 ms evt_8c2d41b7…# Try it: send a message to your own phone, then answer it.npx @nodium.io/cli send --channel <channel id> --to +33612345678 --text "Hello"

nodium listen reads your event log and calls your local server with real, signed deliveries — no tunnel, no public address. Ctrl+C stops it and prints where to resume (--from <seq>). See Webhooks.