Skip to main content
Version: v0.23.1

Administer WhatsApp channels

A channel — a newsletter in both engine libraries — is a one-way broadcast surface: the owner and the admins post, everyone else subscribes and reads. Channels live in their own JID domain, @newsletter, and their routes are nested under a session like every other resource.

This page documents the two administration routes added in v0.16.0: transferring ownership, and demoting an admin back to a subscriber. The rest of the channel family — listing, creating, reading, subscribing, unsubscribing, deleting, reading messages, and muting — is covered field by field in the API reference.

Prerequisites
  • A session that is started and connected. See Sessions and Connect your first session.
  • An API key with the operator role. See Authentication.
  • A session running the Baileys engine (ENGINE_TYPE=baileys) — both routes on this page answer 501 on whatsapp-web.js.
  • The session's WhatsApp account must own the channel; both routes require it.
  • A channel id in WhatsApp's @newsletter format, for example 120363000000000000@newsletter.

Examples use the local base URL http://localhost:2785/api, a session id of 8f3c2b1a-9d4e-4c7a-8b2f-1e6d5a4c3b2a, a channel id of 120363000000000000@newsletter, and the header X-API-Key: YOUR_API_KEY. Replace YOUR_API_KEY with a key from your dashboard. In production, swap the base URL for your domain over TLS.

How channel routes work

Every channel route is nested under a session, so the session id is always in the path. There are ten in all — listing and creating, subscribing and unsubscribing, reading metadata and messages, muting, deleting the channel itself, and the two administration routes this page documents:

GET /api/sessions/{sessionId}/channels
POST /api/sessions/{sessionId}/channels
POST /api/sessions/{sessionId}/channels/subscribe
GET /api/sessions/{sessionId}/channels/{channelId}
DELETE /api/sessions/{sessionId}/channels/{channelId}
POST /api/sessions/{sessionId}/channels/{channelId}/delete
GET /api/sessions/{sessionId}/channels/{channelId}/messages
POST /api/sessions/{sessionId}/channels/{channelId}/mute
POST /api/sessions/{sessionId}/channels/{channelId}/owner/transfer
POST /api/sessions/{sessionId}/channels/{channelId}/admins/demote

Three rules apply to the two administration routes below:

  • Identifiers. A channel is addressed by its @newsletter jid; the person you are naming in the body by a phone number, <phone>@c.us, or <lid>@lid. A bare number is qualified for you. Anything that does not name an individual — a group jid, a bare @c.us, free text — is rejected with 400 before the value reaches WhatsApp: Not an individual user id: <userId> — pass a phone number, <phone>@c.us or <lid>@lid.
  • Roles. Both require an operator-role key and return 403 otherwise.
  • Ownership. Both require this session's WhatsApp account to own the channel. An operator key authorizes the request; WhatsApp still decides whether the account may make the change.

The session must be started. Either route on a session that is not started returns 400; a started session whose engine is not connected yet returns 409.

Transfer channel ownership

POST /api/sessions/{sessionId}/channels/{channelId}/owner/transfer hands a channel you own to another account. newOwnerId is required.

Irreversible, and Baileys only

Once the transfer lands, this session is no longer the owner and cannot take the channel back through this API. There is no undo route — recovering the channel means asking the new owner to transfer it back from their side.

The route is implemented on the Baileys engine only. A whatsapp-web.js session answers 501 with Operation not supported by the active engine: transferChannelOwnership: its page function rejects every call locally against a subscriber list the page cannot repopulate. Set ENGINE_TYPE=baileys for the session that administers channels.

curl -X POST "http://localhost:2785/api/sessions/8f3c2b1a-9d4e-4c7a-8b2f-1e6d5a4c3b2a/channels/120363000000000000@newsletter/owner/transfer" \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "newOwnerId": "628123456789@c.us" }'
{ "success": true }
FieldTypeRequiredMeaning
newOwnerIdstringYesThe account that becomes the new owner — a phone number, <phone>@c.us, or <lid>@lid. A bare number is qualified for you; a value that does not name an individual is a local 400.

success is always true on a 200 — a failure is reported as a non-2xx status, not as success: false.

Two behaviours to plan for:

  • On whatsapp-web.js the 403 documented for this route is unreachable, because the engine refuses with 501 first. On Baileys a 403 is a real refusal from WhatsApp — typically because this account does not own the channel.
  • A 503 means WhatsApp did not answer within the request budget, so the transfer may or may not have applied. Read the channel back before retrying: a retry after a transfer that actually landed is refused, since the account no longer owns it.

The upstream option to dismiss yourself as an admin in the same call is not exposed. The WhatsApp Web function it depends on no longer exists and that branch swallows its own errors, so offering it would fail silently.

Demote a channel admin

POST /api/sessions/{sessionId}/channels/{channelId}/admins/demote returns an admin of a channel you own to an ordinary subscriber. userId is required.

curl -X POST "http://localhost:2785/api/sessions/8f3c2b1a-9d4e-4c7a-8b2f-1e6d5a4c3b2a/channels/120363000000000000@newsletter/admins/demote" \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "userId": "628123456789@c.us" }'
{ "success": true }
FieldTypeRequiredMeaning
userIdstringYesThe admin to demote back to a subscriber — a phone number, <phone>@c.us, or <lid>@lid. A bare number is qualified for you; a value that does not name an individual is a local 400.

A 403 means the engine refused: this account does not own the channel, or the named user is not an admin of it.

Demotion through the API is one-way — and Baileys only

There is no promote route on either engine. Neither engine library exposes a promote call for channels, so none is published: an admin is promoted from the WhatsApp app and demoted here. If you arrived from Groups, note the difference — group participants have promote and demote as a pair, channels have demote only.

Demotion itself is implemented on the Baileys engine only. A whatsapp-web.js session answers 501 with Operation not supported by the active engine: demoteChannelAdmin, because the WhatsApp Web module its library method targets no longer exports the function.

Troubleshooting

StatusCauseFix
400The session is not started, or the body failed validation — a missing newOwnerId / userId, or a value that does not name an individual user.Start the session first (see Sessions); pass a phone number, <phone>@c.us, or <lid>@lid.
401Missing or invalid X-API-Key.Send a valid key in the X-API-Key header.
403The key's role is below operator, or WhatsApp refused — this account does not own the channel, or the user is not an admin.Use an operator-role key (see Authentication); confirm the account owns the channel.
409The session is started but its engine is not connected.Wait for the session to reach ready, then retry.
501The session runs on the whatsapp-web.js engine. Neither route is available there.Run the administering session with ENGINE_TYPE=baileys.
503WhatsApp did not answer within the request budget. The change may or may not have applied.Read the channel back before retrying — do not replay blindly.

Next steps