Reference
Tokens
A Custom tab's token is a JWT (RFC 7519), signed with EdDSA (Ed25519). It's valid for ten minutes.
Header
json
{ "alg": "EdDSA", "typ": "JWT", "kid": "q3Xr9tL2mVb7Hc1d" }kid is the id of the deployment key that signed it.
Claims
| Claim | What it is |
|---|---|
iss | The deployment's public address, like https://chat.acme.com |
aud | Your app's origin, like https://crm.example.com |
sub | The user's id (also in ctx.user.id) |
iat | When it was issued, in seconds since the epoch |
exp | When it expires: iat + 600 |
ctx | Who's looking, and where: the same TabContext your page is told. See What you're told. |
json
{
"iss": "https://chat.acme.com",
"aud": "https://crm.example.com",
"sub": "6acf…",
"iat": 1792058400,
"exp": 1792059000,
"ctx": {
"user": { "id": "6acf…", "name": "Ada Lovelace" },
"workspace": { "id": "6abe…", "slug": "acme", "name": "Acme" },
"space": { "id": "uib59teu0eq9", "kind": "normal", "name": "Launch" },
"tab": { "id": "vuuxldzm", "appTabId": "contacts" },
"app": { "id": "acme-crm" },
"locale": "en"
}
}Keys
GET /api/apps/keys on the deployment's address returns its public keys as a JWK set. It needs no sign-in, and may be cached for an hour.
| Field | Value |
|---|---|
kty | OKP |
crv | Ed25519 |
x | The public key, base64url |
kid | Its id, matching tokens' kid |
alg | EdDSA |
use | sig |
Every workspace on a deployment shares its keys, so a token's ctx.workspace tells you which workspace it's for. Keys change only when the deployment's owner changes its secret.
Where tokens come from
Only the workspace's web app can get a token, for someone signed in who can see the space the tab is in. Each token is addressed to one app's origin, so a token for another app doesn't work on yours.