Tenants
9 endpoints in this family.
List connect links
GET/api/v1/connect-links
Returns every hosted connect link of your account, most recent first: which client it is for, whether it is still pending, used (the client connected their number) or expired (past its date, or revoked). The address itself is never returned: Nodium keeps only a hash. Create a new link to replace a lost one.
Query parameters
statestringOnly links in this state.
pendingusedexpiredclientstringOnly the links of this client: its Nodium id or your
externalId.limitintegerHow many to return.
cursorstringOpaque cursor from the previous page. Omit for the first page.
Response
A page of connect links and the cursor for the next one.
data.itemsobject[]The links, most recent first.
Show fields
idstringThe link id.
clientobjectThe client it is for:
id,name,externalId,isHome.statestringWhere it stands.
pendingusedexpiredexpiresAtstringWhen it stops working, ISO 8601.
createdAtstringISO 8601.
usedAtstringWhen the client connected their number;
nullbefore.redirectUrlstringWhere the client goes back at the end;
nullwhen none.channelIdstringThe channel this link connected;
nullbefore it is used.
data.nextCursorstringPass it as
cursorfor the next page;nullat the end.data.hasMorebooleanWhether another page exists.
data.totalintegerHow many match, on the first page only;
nullafter.
curl https://nodium.io/api/v1/connect-links \ -H "Authorization: Bearer $NODIUM_KEY"{ "data": { "items": [ { "id": "…", "client": {}, "state": "pending", "expiresAt": "…", "createdAt": "…", "usedAt": "…", "redirectUrl": "…", "channelId": "…" } ], "nextCursor": "…", "hasMore": true, "total": 0 }}Revoke a connect link
DEL/api/v1/connect-links/{id}
Makes a link that has not been used yet stop working right away. It stays in the list as expired. A link that was already used, or already expired, cannot be revoked. Create a new one with POST /tenants/{id}/connect-links.
Path parameters
idstringThe link id.
Response
Confirmation that the link no longer works.
data.revokedbooleanAlways
true.
curl -X DELETE https://nodium.io/api/v1/connect-links/<id> \ -H "Authorization: Bearer $NODIUM_KEY"{ "data": { "revoked": true }}List your tenants
GET/api/v1/tenants
A tenant is one of your customers: a client of your account, with its own WhatsApp numbers, contacts, conversations and templates, isolated from the others. Each one comes with its WhatsApp state, its latest hosted connect link and its activity this month (a tenant is active once it has sent or received a message in the current UTC month).
"My company" — the client your account was born with — is not listed: calls without the Nodium-Tenant header act on it. Requires a key that is not pinned to a client. Newest first, paginated with cursor.
Query parameters
externalIdstringOnly the tenant carrying this identifier of yours.
limitintegerPage size, 1 to 100. Default 50.
cursorstringThe
nextCursorof the previous page.
Response
The tenants of your account, newest first.
data.itemsTenant[]The tenants.
data.nextCursorstringPass it as
cursorfor the next page;nullat the end.data.hasMorebooleanWhether another page exists.
Refusals
- 403
all_clients_requiredThe key is pinned to a client.
curl https://nodium.io/api/v1/tenants \ -H "Authorization: Bearer $NODIUM_KEY"{ "data": { "items": [ {} ], "nextCursor": "…", "hasMore": true }}Create a tenant
POST/api/v1/tenants
Adds one of your customers to your account. It has no human member: you drive it through the API with the Nodium-Tenant header (or a key pinned to it, POST /keys with clientId). Your customer then connects their WhatsApp number through a hosted link (POST /tenants/{id}/connect-links) — they never need a Nodium account.
Pass your own identifier as externalId: it is unique in your account, so replaying the call returns 409 tenant_exists with the existing tenant id instead of creating a duplicate. The clients limit of your plan applies to the whole account.
Body
namestringrequiredYour customer's name, 2 to 80 characters.
externalIdstringYour identifier for this customer, up to 200 characters. Unique in your account.
localestringLanguage of the hosted connect page.
frentimezonestringIANA time zone. Default
Europe/Paris.
Response
The tenant, ready for a connect link.
data.tenantTenantThe tenant.
Refusals
- 402
plan_limitYour plan has no room for another client (the Build plan includes none besides "My company"). - 403
all_clients_requiredThe key is pinned to a client. - 409
tenant_existsA tenant already carries this `externalId`; its id is in `details.tenantId`.
curl -X POST https://nodium.io/api/v1/tenants \ -H "Authorization: Bearer $NODIUM_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "Optique Martin", "externalId": "cust_1042", "timezone": "Europe/Paris" }'{ "data": { "tenant": { "id": "…", "externalId": "…", "name": "…", "slug": "…", "status": "active", "locale": "fr", "timezone": "…", "whatsapp": {}, "connectLink": {}, "activeThisMonth": true, "eventsThisMonth": 0, "createdAt": "…", "updatedAt": "…" } }}Close a tenant
DEL/api/v1/tenants/{id}
Closes the tenant: its channels are switched off, the numbers it connected through Meta's signup window are disconnected at Meta and freed so they can be connected elsewhere, the keys pinned to it are revoked, and its connect links stop working at once. Nothing is erased — conversations and messages are kept — but the tenant no longer appears in your list, and its externalId becomes free for a new tenant. This cannot be undone through the API.
Path parameters
idstringThe tenant id, or your
externalId.
Response
Confirmation, and what was switched off.
data.deletedbooleanAlways
true.data.channelsSwitchedOffintegerHow many active channels were switched off.
data.numbersDisconnectedintegerHow many numbers were disconnected at Meta and freed.
data.numbersToCleanintegerHow many numbers Meta refused to disconnect: Nodium is alerted and cleans them.
data.keysRevokedintegerHow many keys pinned to the tenant were revoked.
Refusals
- 403
all_clients_requiredThe key is pinned to a client. - 404
tenant_not_foundNo such tenant in your account.
curl -X DELETE https://nodium.io/api/v1/tenants/<id> \ -H "Authorization: Bearer $NODIUM_KEY"{ "data": { "deleted": true, "channelsSwitchedOff": 0, "numbersDisconnected": 0, "numbersToClean": 0, "keysRevoked": 0 }}Get a tenant
GET/api/v1/tenants/{id}
Returns one tenant of your account, with its WhatsApp state, its latest hosted connect link and its activity this month. The path accepts either the Nodium id or your own externalId; "My company" answers here too, by its id. A tenant of another account answers 404, exactly like one that does not exist.
Path parameters
idstringThe tenant id, or your
externalId.
Response
The tenant and its state.
data.tenantTenantThe tenant.
Refusals
- 403
all_clients_requiredThe key is pinned to a client. - 404
tenant_not_foundNo such tenant in your account.
curl https://nodium.io/api/v1/tenants/<id> \ -H "Authorization: Bearer $NODIUM_KEY"{ "data": { "tenant": { "id": "…", "externalId": "…", "name": "…", "slug": "…", "status": "active", "locale": "fr", "timezone": "…", "whatsapp": {}, "connectLink": {}, "activeThisMonth": true, "eventsThisMonth": 0, "createdAt": "…", "updatedAt": "…" } }}Update a tenant
PATCH/api/v1/tenants/{id}
Changes what you send, leaves the rest. externalId: null removes your identifier. Renaming changes the tenant's slug.
Path parameters
idstringThe tenant id, or your
externalId.
Body
namestringNew name, 2 to 80 characters.
externalIdstringNew identifier of yours, or
nullto remove it.localestringLanguage of the hosted connect page.
frentimezonestringIANA time zone.
Response
The tenant as it now is.
data.tenantTenantThe tenant.
Refusals
- 403
all_clients_requiredThe key is pinned to a client. - 404
tenant_not_foundNo such tenant in your account. - 409
tenant_existsAnother tenant already carries this `externalId`.
curl -X PATCH https://nodium.io/api/v1/tenants/<id> \ -H "Authorization: Bearer $NODIUM_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "…", "externalId": "…" }'{ "data": { "tenant": { "id": "…", "externalId": "…", "name": "…", "slug": "…", "status": "active", "locale": "fr", "timezone": "…", "whatsapp": {}, "connectLink": {}, "activeThisMonth": true, "eventsThisMonth": 0, "createdAt": "…", "updatedAt": "…" } }}List the channels of a tenant
GET/api/v1/tenants/{id}/channels
The WhatsApp numbers of one tenant, in the same shape as GET /channels. Call it after the hosted connect link redirects back to you, to confirm the number and store its channelId.
Path parameters
idstringThe tenant id, or your
externalId.
Response
The channels of the tenant.
data.itemsChannel[]The channels.
Refusals
- 403
all_clients_requiredThe key is pinned to a client. - 404
tenant_not_foundNo such tenant in your account.
curl https://nodium.io/api/v1/tenants/<id>/channels \ -H "Authorization: Bearer $NODIUM_KEY"{ "data": { "items": [ {} ] }}Create a hosted connect link
POST/api/v1/tenants/{id}/connect-links
Returns a link you send to your customer. It opens a Nodium-hosted page where they connect their WhatsApp number through Meta's signup window — they never create a Nodium account. When they finish, they are sent back to redirectUrl with status=connected&channel_id=…; if they give up, with status=cancelled.
"My company" can have one too: open it yourself to connect your own number. The link works once and expires after expiresInDays (7 by default, 30 at most). The address is shown only here: Nodium keeps a hash of it. Create a new one if it is lost. After the redirect, confirm with GET /tenants/{id}/channels.
Path parameters
idstringThe tenant id, or your
externalId.
Body
redirectUrlstringWhere to send your customer back. Must start with https://.
expiresInDaysintegerLifetime in days, 1 to 30. Default 7.
Response
The hosted link, shown only here, and when it expires.
data.idstringThe link id.
data.urlstringThe address to send to your customer. Shown only here.
data.expiresAtstringWhen it stops working, ISO 8601.
data.redirectUrlstringWhere your customer goes back, or
null.
Refusals
- 402
plan_limitThe tenant is not "My company" and your plan includes no clients (Build). - 403
all_clients_requiredThe key is pinned to a client. - 403
tenant_closedThe tenant is suspended or closed. - 404
tenant_not_foundNo such tenant in your account. - 422
invalid_request`redirectUrl` is not an https address, or `expiresInDays` is out of range.
curl -X POST https://nodium.io/api/v1/tenants/<id>/connect-links \ -H "Authorization: Bearer $NODIUM_KEY" \ -H "Content-Type: application/json" \ -d '{ "redirectUrl": "https://app.example.com/settings/whatsapp" }'{ "data": { "id": "…", "url": "…", "expiresAt": "…", "redirectUrl": "…" }}