> ## Documentation Index
> Fetch the complete documentation index at: https://docs.polymorfa.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Number capabilities

> Read which WhatsApp features WhatsApp has enabled for each of your numbers, and the limits it applies.

<Note>
  Number capabilities are a beta. On the **Numbers** page of the Console, a team
  owner or admin selects **Join** on the Number capabilities beta row, reviews
  the terms and selects **Accept and join**. Until the team has joined and the
  beta is offered to it, every capability request returns `403 permission_denied`.
</Note>

WhatsApp does not enable every feature for every account at the same time. It
rolls features out by account, country and app version, and it sets limits such
as how long a sent message stays editable. The capabilities endpoint tells you
which configuration gates are enabled for one of your numbers. Your app must
also check client requirements and handle operations WhatsApp rejects.

## How the values are produced

Polymorfa reads the WhatsApp configuration of each number connected as a linked
device when the number
first connects, at each login when WhatsApp reports a change, when WhatsApp asks
for a refresh, and on the refresh interval WhatsApp sets for the number (one day
by default). Each capability evaluates the configuration gates identified in
WhatsApp Web. These values do not check client-environment requirements or
guarantee that WhatsApp's server will accept an operation.

* **Values come from a linked-device connection.** A number that has never had
  one (connected only through the Official API) reports `status` `unknown`. A
  number whose linked-device connection was removed keeps the values last
  synced.
* **Values reflect WhatsApp's configuration at `syncedAt`.** They are not a live
  check. A change WhatsApp makes appears after the number's next sync.
* **Values describe the WhatsApp account last linked to the number**, whether
  or not it is connected now. Read the number's session for its connection
  status.
* **`status` is `unknown` and every `value` is `null`** before the number's
  first sync, and when another WhatsApp account is linked to the number: from
  that account's first sync attempt until its configuration is synced.
  Polymorfa recognizes another account by the account creation time WhatsApp
  reports when the number logs in. If WhatsApp does not report it for the newly
  linked account, the change is not detected, and the values stay those of the
  account they were synced for until the next sync. When Polymorfa cannot tell
  whether the stored configuration belongs to the account linked now, `status`
  is also `unknown` until WhatsApp's configuration is synced again for that
  account; failed sync attempts do not clear it.
* **A capability says what WhatsApp allows the number.** It does not mean the
  Polymorfa API offers an operation for that feature.
* `source` is `server` only when every setting a value was evaluated from was
  sent by WhatsApp and used as sent; otherwise WhatsApp's own default or limit
  took part and `source` is `client_default`.

## Before you start

* **Your team has joined the beta.** Leaving it refuses capability reads;
  numbers and every other API are unaffected.
* **You call from your server with an organization key or project token** that
  has the `sessions:read` scope. A project token reaches only its own project's
  numbers. Client tokens are rejected.

| Method | Scope |
| - | - |
| [Get session capabilities](/api-reference/platform/sessions/get-session-capabilities) `GET /platform/sessions/{sessionId}/capabilities` | `sessions:read` |

`sessionId` is the session name or its ID.

## Read a number's capabilities

```bash theme={null}
curl "https://api.polymorfa.com/platform/sessions/support-line/capabilities" \
  -H "Authorization: Bearer $POLYMORFA_PROJECT_TOKEN"
```

```json theme={null}
{
  "data": {
    "session": "support-line",
    "projectId": "0198a2cb-0000-7000-8000-000000000002",
    "status": "synced",
    "syncedAt": "2026-09-24T10:00:00.000Z",
    "checkedAt": "2026-09-24T11:00:00.000Z",
    "accountType": "business",
    "capabilities": [
      { "key": "channels", "kind": "feature", "unit": null, "value": true, "source": "server" },
      { "key": "messageEdit.windowSeconds", "kind": "limit", "unit": "seconds", "value": 1200, "source": "client_default" },
      { "key": "polls.maxOptions", "kind": "limit", "unit": "count", "value": 12, "source": "client_default" }
    ]
  }
}
```

The example shows three of the entries. The response always contains every
capability, in the same order.

| Field | Meaning |
| - | - |
| `status` | `synced` when the values reflect the account last linked to the number, otherwise `unknown`. |
| `syncedAt` | When the configuration the values reflect was read from WhatsApp. `null` while `status` is `unknown`. |
| `checkedAt` | When Polymorfa last asked WhatsApp for the configuration, whether or not anything changed. |
| `accountType` | `business` or `personal`: the account type the values were evaluated for. `null` when not known. |
| `capabilities[].kind` | `feature`: `value` is `true` or `false`. `limit`: `value` is an integer in `unit`. A limit is `null` on a synced number when WhatsApp's setting for it is not a usable number. |
| `capabilities[].source` | `server`: every WhatsApp setting the value was evaluated from was sent by WhatsApp and used as sent. `client_default`: WhatsApp's own default or limit took part, because a setting was not sent or not usable, or WhatsApp caps or replaces the value it sent. `account_type`: the capability does not apply to this account type. `null` when `value` is `null`. |

Ignore keys your app does not recognize. New capabilities can be added; an
existing key never changes meaning.

## Capabilities

| Key | Kind | Meaning |
| - | - | - |
| `usernames.display` | feature | WhatsApp shows other people's usernames to this number. |
| `usernames.search` | feature | The number can find people by username. |
| `usernames.contactlessChat` | feature | The number can start a chat with someone by username, without their phone number. `true` only when both username features above are on. |
| `channels` | feature | Channels are enabled on the number's linked devices. |
| `channels.creation` | feature | The number can create channels from a linked device. `true` only when `channels` is `true`. |
| `metaAi` | feature | WhatsApp has enabled Meta AI for the number. On a personal account WhatsApp also requires a supported display language unless it enables every language; the language is not checked. `null` when `accountType` is `null`, because business and personal accounts use different settings. |
| `calling.linkedDevice` | feature | Voice and video calls are enabled on the number's WhatsApp Web linked devices. WhatsApp also requires a supported browser, which this does not check. |
| `calling.linkedDeviceGroup` | feature | Group calls are enabled on the number's WhatsApp Web linked devices. `true` only when `calling.linkedDevice` is `true`. WhatsApp also requires a supported browser, which this does not check. |
| `events` | feature | Event messages (invitations with a date, and responses) are enabled on the number's linked devices. |
| `polls.endTime` | feature | The number can send polls with an end time in every chat. When `false`, WhatsApp can still allow it in individual groups; use the group capability read for one group. |
| `polls.hideVoters` | feature | The number can send polls that hide who voted, in every chat. Use the group capability read for one group. |
| `polls.creatorEdit` | feature | The number can edit polls it created, in every chat. Use the group capability read for one group. |
| `polls.maxOptions` | limit, count | The most options a poll can have. Never more than 20. |
| `polls.maxQuestionLength` | limit, characters | The longest poll question. Never more than 500. |
| `polls.maxOptionLength` | limit, characters | The longest poll option. Never more than 255. |
| `messageEdit.windowSeconds` | limit, seconds | How long after a message was sent WhatsApp accepts an edit to it, outside channels. |
| `messageEdit.offerSeconds` | limit, seconds | How long after sending a message the WhatsApp app offers to edit it, outside channels. |
| `groups.maxSize` | limit, members | The most members in a group, other than a community announcement group. |
| `communities.maxGroups` | limit, count | The most groups a community can contain. |
| `pinnedMessages.maxPins` | limit, count | The most messages the number can pin in one chat. |
| `business.chatAssignment` | feature | The business number can assign chats to people using its linked devices. `false` with `source` `account_type` for a personal account. |

## Errors

| Status | Code | Cause |
| - | - | - |
| `400` | `invalid_parameter` | `sessionId` is missing or too long. |
| `403` | `permission_denied` | The team is not enrolled in the beta or the beta is not offered to it, or the request uses a client token. |
| `403` | `missing_scope` | The credential lacks `sessions:read`. |
| `404` | `resource_not_found` | No number with this name or ID exists in the credential's team or project. |

## Group capabilities

The group read and capability-change event are not offered. Number-capabilities
beta enrollment does not enable these extensions.

The group read contract is `GET /messaging/{session}/groups/{id}/capabilities`.
Use the group's Polymorfa identifier and a server credential with `groups:read`.
The linked number must be a current member of the group. Official API group
connections do not provide this read.

The response includes `status`, `syncedAt`, `checkedAt`, and three feature keys:
`polls.endTime`, `polls.hideVoters`, and `polls.creatorEdit`. A gate is enabled
when WhatsApp enables it for the number or that group. A value's `source` is
`server` or `client_default`; unknown values have a null value and source.

Values stay unknown until the number has completed its first number-level
configuration sync and a group configuration sync has succeeded for the
account linked to the number. Reading capabilities does not open the chat or
fetch configuration. `syncedAt` identifies the successful configuration read;
`checkedAt` includes later failed checks. Account replacement makes the former
account's group values unknown. These gates describe configuration and do not
grant permission to edit another participant's poll.

The corresponding MCP tool is `groups_capabilities`, with `session` and `id`
arguments. It follows the same server credential, scope, membership and beta
checks as the API. The extension is not offered through either interface.

See [Read group capabilities](/api-reference/messaging/groups/get-group-capabilities).

## Capability change events

The `session.capabilities_updated` contract describes changes to a number's
effective capabilities on a project webhook. The payload contains the number capability
response and `changedKeys`, the keys whose value or source changed. A status or
account-type change also produces an event, even when `changedKeys` is empty.
Routine checks and configuration changes that leave capabilities unchanged do
not produce events. Group capability changes do not produce this event.

Publication and delivery require the same beta access as a capability read.
When access is withdrawn or unavailable, queued changes wait for access to
return and expire after seven days. Published history follows your ordinary
event retention. Retries retain the event ID; deduplicate by that ID. See
[Webhooks](/api/webhooks) for signature verification and delivery handling.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.