Mint
CallPOST /platform/client-tokens with a project or team key that has all of
sessions:manage, messages:write, contacts:read, presence:read,
presence:observe, and mcp. Updating session rules requires the same
permissions. Tokens issued with action ceilings carry an immutable action ceiling. Every request
intersects that ceiling with live session rules and current Number ownership.
Rule edits cannot grant actions outside the ceiling.
A human-owned team key or project token can mint only while its owner remains a
team owner or admin and is not banned. Service-account credentials cannot mint
tokens that permit messaging actions. The issuer must remain active and
unrevoked, with the required scopes and current ownership of the selected
Number or Customer. These checks apply to every mint, including token refreshes.
A current issuer or ownership denial returns 403 without a token. If Polymorfa
cannot complete the issuance checks, it returns 503 without a token.
ttlSeconds must be within the bounds documented for the endpoint. The token is
limited to its team, session, ephemeral ID, and expiry.
Session allow requires enrollment in the action-ceilings beta. Until that
beta is enabled, session allow requests are refused and omission retains the
existing rule-based token format. Existing sealed ceilings remain enforced if
new ceiling issuance is disabled.
allow also accepts an explicit ceiling for a session token, including mcp
and voip_* actions. An empty session allow grants no API actions. Customer allow must contain
at least one action. Set the rules before minting. A token with no permitted
actions needs reissuing after you configure its rules.
The action names chats_read, chats_manage, contact_write, and
contact_delete are reserved for enrolled regional beta access. Including a
reserved action does not enable regional Contacts or Chats. Regional ceilings
also require the corresponding chats:read, chats:manage, or contacts:manage
issuer scope. These permissions do not authorize legacy WhatsApp chat routes. read_contact
continues to cover its documented contact lookups; it grants no unrestricted
access to a retained contact directory. Existing tokens cannot gain these
reserved actions through a rule edit.
Session rules
Rules are managed independently:PUT replaces the whole rule set. Omitted optional fields return to their
defaults. Rules stay in effect until you replace or delete them, and deleting a
session also deletes its rules.
recipientMode is one of conversation, any, or none. Unknown modes fail
closed. allowedActions is a comma-separated list containing only these
values:
Conversation window
Inconversation mode, a client token can send only to a contact who messaged
the session within the conversation window. The window starts again with each
new message from that contact.
conversationTtlSeconds sets the window, in seconds:
Values outside this range return
400. A window without an expiry is not
available: a contact who has not messaged the session for more than 7 days
must message it again before a client token can reply.
The voip_* actions permit calling. Three optional rule fields limit calls:
maxSetupsPerMinute (call setups per minute for each ephemeralId; 0 uses
the default of 10), allowedNumber (a comma-separated list of E.164 numbers
the token can call or invite), and maxConcurrency (calls held at once; 0
means no limit). See Calls.
Client tokens never pair numbers. Use a QuickLink
to connect a number from a browser or phone.
The mcp action permits the protocol handshake. Each MCP tool still passes
through its ordinary session, recipient, action, origin, and rate rules.
Customer-scoped tokens
Customer-scoped tokens are a beta. When the beta is offered to your team, a
team owner or admin selects Join on its beta row on a project’s Numbers
page and accepts the terms. Until the team has joined, minting with
customer
returns 403.customer instead of
session:
- Send exactly one of
sessionorcustomer. customeris the Customer’s Polymorfa ID. Look up a Customer by your own external ID on your server first; tokens never accept an external ID.- The issuing key also needs
customers:read. A project token can mint only for Customers in its project. A team key can mint for any Customer in the team. A Customer outside the key’s team or project returns404. - The Customer must be active and own at least one number, and the project
must have Customers enabled. A token covers at most 64 numbers; minting for
a Customer with more returns
400.
Call the usual session routes with the number’s session ID in the path, for
example
POST /messaging/{session}/messages/send. Each request must also pass
that session’s rules: a Customer-scoped token never allows
more than the session’s rules do.
allow narrows the token further. It accepts send_message,
send_reaction, send_typing, send_seen, read_presence,
subscribe_presence, and read_contact. Omit it for a Customer to use that
original action set. For a session, omission snapshots the configured actions
at mint time; missing rules produce a token with no actions. A Customer-scoped token can’t use calling (voip_*) or MCP; mint a
session token for those.
Security behavior
- Client tokens cannot mint other tokens, including Customer-scoped tokens.
- Rules, recipient/conversation state, origin constraints, and rate limits are checked after the token authenticates.
- Delete or disable the session rules to stop permitted effects before all issued tokens expire.
- Each rule change appears in Audit logs as
clientToken.rulesCreated,clientToken.rulesUpdated, orclientToken.rulesDeleted. The entry records which fields changed, the recipient mode, the limits, and the conversation window. It records how many origins and numbers are allowed, not the origins or numbers themselves. - If a
PUTorDELETEreturns503with codeservice_unavailable, Polymorfa stored the change but could not confirm that client tokens use it. Repeat the same request after theRetry-Afterdelay.
Temporary unavailability
Client tokens fail closed. If Polymorfa cannot check a request’s rules, the request is refused instead of being allowed without checks:503with codecredential_verification_unavailablewhen the session rules cannot be loaded. The token is still valid; retry the request.503with codeservice_unavailableand aRetry-Afterheader when a per-minuterateLimitor theconversationwindow cannot be checked. Retry after the stated number of seconds.