Mint an end-user Portal JWT
Mints a signed Portal user JWT for one of your end users. Send the token to
your client; it then connects to the realtime edge and calls client routes
with Authorization: Bearer <jwt>.
claims is an opaque bag you define — it travels with the token and is
available to your channel config's authorization logic and to message
senders (as read-only metadata). channels, when present, restricts the
token to the listed channels and grants; omit it to allow whatever the
channel config permits. ttl accepts values like 1h, 30m, 45s,
2d, or a bare number of seconds; it defaults to one hour.
Server-only. A request carrying an Origin header (a browser) is rejected.
Body·
- Type: stringuser
Id requiredYour end user's id. Becomes the JWT
sub. - Type:channelsProperties: 1
A map of channel id to a list of granted capabilities (for example
["connect", "publish"]). Omit on a token to allow whatever the channel config permits. - Type: objectclaimsProperties: 1
Opaque claims bag; travels with the token and is visible to your config's authorization logic.
- Type: stringttl
Token lifetime. Accepts
1h,30m,45s,2d, or a bare number of seconds. Defaults to one hour.
Responses
- application/json
- application/json
- application/json
- application/json
curl https://api.useportal.co/v1/tokens \
--request POST \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer YOUR_SECRET_TOKEN' \
--data '{
"userId": "u_123",
"claims": {
"username": "ada",
"avatar": "https://cdn.example.com/ada.png"
},
"ttl": "1h"
}'
{
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6ImVudl8xMjMifQ.eyJzdWIiOiJ1XzEyMyIsImFub24iOmZhbHNlLCJpYXQiOjE3NTI5MTIwMDAsImV4cCI6MTc1MjkxNTYwMH0.signature",
"expiresAt": "2026-07-19T03:00:00.000Z"
}