Get started
Authentication: API Secrets, Tokens and Roles
How VoltKit RTC authenticates your backend and your users: API secrets, short-lived room tokens, the four roles, and how to rotate a secret safely.
There are two kinds of credential, used by two different parties. Keeping them apart is most of what it takes to use the API safely.
| Credential | Held by | Lifetime | Used for |
|---|---|---|---|
API secret (sk_…) | Your backend | Until you revoke it | Creating rooms and streams, minting tokens, reading usage |
| Token | One of your users' devices | Minutes | Joining one room, one chat channel, or one stream |
API secrets
Send the secret on every request from your backend, in either header:
curl "$VOLTKIT_RTC_URL/v1/rooms" -H "X-API-Key: $VOLTKIT_RTC_SECRET"
curl "$VOLTKIT_RTC_URL/v1/rooms" -H "Authorization: Bearer $VOLTKIT_RTC_SECRET"
A project can hold up to five active secrets, so you can rotate without downtime.
Rotating a secret
- Create a new secret on the Credentials tab of your project. Your browser downloads it as a text file with a
.envblock, as when you created the project. - Deploy it to your servers, then delete the file.
- Revoke the old one.
Revoking takes effect immediately: requests using that secret start returning 401. Tokens it already minted stay valid until they expire.
Tokens
A token is a signed statement from your backend: this identity may join this room, with this role. Your backend asks for one per user:
curl -X POST "$VOLTKIT_RTC_URL/v1/rooms/show-42/tokens" \
-H "X-API-Key: $VOLTKIT_RTC_SECRET" \
-H "Content-Type: application/json" \
-d '{"identity":"user-99","role":"viewer"}'
Three properties matter:
- Your backend chooses the role. It is signed into the token and the client cannot change it.
- A token is short-lived. Ten minutes by default. It authorises the connection handshake, not the whole session: an established connection stays up past the token's expiry, and the service sends the client a fresh token before the old one lapses, so reconnecting hours later still works.
- A token opens one thing. A room token cannot open a chat-only connection or publish a broadcast stream, and the reverse is true too.
identity is your own id for the user. It is what other participants see, what appears in webhooks, and what moderation acts on, so use a stable id from your system.
Roles
| Role | Can publish camera and microphone | Can moderate |
|---|---|---|
host | Yes | Yes |
cohost | Yes | No |
moderator | No | Yes |
viewer | No | No |
Hosts may mute/remove non-host participants and assign roles. Moderators may mute/remove viewers, handle raised hands and moderate chat; they cannot grant roles, manage co-hosts or end a room. One participant cannot make another a host: only your backend can mint a host token, and a host cannot be demoted or removed by anyone in the room.
Roles can change during a session. When the host promotes a viewer to co-host, the service checks the live role on every action, so the change takes effect without your backend minting anything.
Three kinds of token
| Token | Minted by | Opens |
|---|---|---|
| Room token | POST /v1/rooms/{roomId}/tokens | The room connection: media and chat |
| Chat token | POST /v1/chat/{channel}/tokens | A chat-only connection |
| Stream token | POST /v1/streams/{streamId}/tokens | Publishing to, or playing, one broadcast stream |
When a request is refused
| Status | Code | Meaning |
|---|---|---|
401 | unauthorized | The secret is missing, wrong or revoked |
403 | tenant-suspended | The project is suspended |
402 | quota-exhausted | The project is out of hours. Rooms already running continue; new ones are refused |
429 | rate-limited | Too many API calls in a minute |
Another customer's room is never "forbidden". It simply returns 404, so nothing reveals what other customers have created.
Last updated . Something unclear or wrong? Tell us.