Skip to content

An API that does not surprise you.

One base URL, one key, two response shapes. Everything the console does, your code does too.

cURL

Example
curl "https://nodium.io/api/v1/conversations?limit=20" \ -H "Authorization: Bearer $NODIUM_KEY" -i
200
X-RateLimit-Limit: 600X-RateLimit-Remaining: 599{ "data": { "items": [ { "id": "c81d…", "status": "open" } ], "nextCursor": "MjAyNi0wOS0yOFQw…", "hasMore": true }}

The basics

What to know before the first call.

  • A versioned base URL

    Every route lives under /api/v1. A published version does not change shape.

    https://nodium.io/api/v1
  • One key per account

    The key acts as itself and opens the whole API: on your own company, on the client it is pinned to, or on the one named by the Nodium-Tenant header. It is created in the console or through the API.

    Authorization: Bearer nod_…
  • One envelope

    A successful response sits under data; a refusal, under error. Never both.

    { "data": … }
  • Stable errors

    Test the code, never the text. Every refusal carries the request id.

    { "error": { "code", "requestId" } }
  • Cursor pagination

    Send back nextCursor until it is null. Cursors are opaque.

    ?limit=100&cursor=…
  • No double sends

    Every send carries your idempotency key: replayed after a timeout, it leaves once.

    "idempotencyKey": "order-1042"

Webhooks

Subscribe an https URL to events. Nodium signs every call and retries failures.

  • Answer 2xx within 10 seconds, do the work afterwards.
  • Six attempts: after 1 min, 5 min, 30 min, 2 h and 12 h.
  • In the order of each conversation; ignore a duplicate thanks to the event id.
  • Log, redelivery, test call, secret rotation and pause, through the API.
  • message.received
  • message.imported
  • message.echoed
  • message.edited
  • message.revoked
  • message.sent
  • message.delivered
  • message.read
  • message.failed
  • conversation.opened
  • contact.opted_in
  • contact.opted_out
  • template.status_changed
  • channel.connected
  • channel.connect_failed
  • channel.health_changed
  • history.progress
Example
import crypto from 'node:crypto'// X-Nodium-Signature: t=<seconds>,v1=<hex>[,v1=<hex>]export function verifyNodium(rawBody, header, secret) { const parts = header.split(',') const t = parts.find(p => p.startsWith('t='))?.slice(2) const sigs = parts.filter(p => p.startsWith('v1=')).map(p => p.slice(3)) if (!t || Math.abs(Date.now() / 1000 - Number(t)) > 300) return false const expected = crypto.createHmac('sha256', secret) .update(`${t}.${rawBody}`).digest('hex') return sigs.some(s => s.length === expected.length && crypto.timingSafeEqual(Buffer.from(s), Buffer.from(expected)))}

One key for all your customers

One client per end customer, driven with a single key.

  • One key acts on every client of your account; the Nodium-Tenant header names which one.
  • Your customer id is enough to name a client: replaying the creation makes no duplicate.
  • A hosted, single-use connect link brings your customer back to you once their number is connected.
  • A webhook on your own company tells you about every client, and every time a number is connected.
Read the clients guide

cURL

Example
# One account key adds and drives every clientcurl https://nodium.io/api/v1/tenants \ -H "Authorization: Bearer $NODIUM_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "Optique Martin", "externalId": "cust_1042" }'# Then act for that client with the Nodium-Tenant headercurl https://nodium.io/api/v1/conversations \ -H "Authorization: Bearer $NODIUM_KEY" \ -H "Nodium-Tenant: cust_1042"

Limits

Every response tells you what is left: X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset.

  • 600 / min

    Calls per client

    Above that, 429 and a Retry-After header in seconds.

  • 600 / min

    Replies per minute

    On free-text sends (text and files), per key and per client. For volume, queue your sends.

  • 6

    Attempts per webhook

    Then the delivery is marked failed; it can be redelivered on demand.

For your tools and your agents

Everything is drawn from the code, never copied by hand.

  • OpenAPI 3.1

    The full description, to generate a client or import into your API tool.

    openapi.json
  • llms.txt

    Every published route, in one file, for a language model.

    llms.txt
  • AGENTS.md

    An Agent Skill: the routes, the signature and the pitfalls, for your coding assistant.

    AGENTS.md
  • The status page

    The state of the API, machine-readable.

    status.json

Your first key, in five minutes.

Create a free account, then a key in the developer portal.

Talk to the Nodium team

Tell us what you are connecting. We get back to you within one business day, with a tailored price if you have more than twenty-five clients.