Skip to content

Mint a Client token

POST
/v1/namespaces/{namespace}/tokens
curl --request POST \
--url https://app.caprid.com/v1/namespaces/acme/tokens \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '{ "path": "room/42", "subscribe": "" }'

Signs a Client token with one of the Namespace’s Signing keys. Use it when you’d rather not hold a Signing key’s secret in your own backend.

A token gets no grants by default. Name what it may publish, subscribe to, or both. A request that names neither is a 400. Whatever you ask for has to fit inside the Signing key’s scope.

namespace
required

A Namespace’s name, which is the root of every path signed for it. It never changes. Use lowercase letters, digits and hyphens, and start and end with a letter or digit. Some names, like admin and default, are reserved, and so is every name that starts with trial-, which only Trial Organizations get.

string
>= 3 characters <= 32 characters /^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/

Example

acme
Media typeapplication/json
object
kid

The kid of the Signing key to sign with. You can leave it out when the Namespace has exactly one.

string
path

Where the token is rooted, relative to the Namespace. The token’s root claim is <namespace>/<path>.

string
""
publish
One of:
string
subscribe
One of:
string
expires_in

Seconds until the token expires. 0 means never.

integer
default: 3600

Examples

Watch one room for an hour

{
"path": "room/42",
"subscribe": ""
}

The signed token and what it grants.

Media typeapplication/json
object
token
required

A JWT. Give it to the Client, which passes it to the relay as ?jwt=.

string
kid
required
string
claims
required

A Client token’s payload. root is absolute and starts with your Namespace. put (publish) and get (subscribe) are prefixes relative to root.

object
root
string
put
Array<string>
get
Array<string>
exp

When the token expires. Absent for a token that never expires.

integer
iat

When the token was issued.

integer

Example

{
"claims": {
"root": "acme/room/42",
"get": [
""
]
}
}

The request can’t be signed: it grants nothing, it asks for more than the key’s scope, it reaches outside the Namespace, or it names no key while the Namespace has zero or several.

Media typeapplication/json
object
error
required
string

Example

{
"error": "the requested grants exceed the key's scope"
}

No valid credential. Missing, expired and revoked credentials all get the same response, and so does an API key whose trial has lapsed. An Agent token from before a claim gets a 401 too, once the claim has made the trial a person’s, with a message saying to get a new token.

Media typeapplication/json
object
error
required
string

Example

{
"error": "the requested grants exceed the key's scope"
}
WWW-Authenticate
string
Example
Bearer realm="switchboard"

Sent with an API key limited to some Namespaces, to a Namespace outside its limit, or to a route that acts on the Organization as a whole. A limited key can never create API keys.

Media typeapplication/json
object
error
required
string

Example

{
"error": "this API key is limited to the Namespaces acme-staging, and acme isn't one of them"
}

The Namespace isn’t one you can reach, or the kid isn’t one of its keys.

Media typeapplication/json
object
error
required
string

Example

{
"error": "the requested grants exceed the key's scope"
}