APPSOCOMDocs

Join tokens

Your backend mints a join token for each person, and your app joins with it. The token decides who they are and what they may do. Our servers enforce it, so a modified app can't give itself more.

Minting a token

bash
curl -X POST https://api.appsocom.dev/tokens \
  -H "Authorization: Bearer $APPSOCOM_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"roomId":"class-1","userId":"u_7","name":"Ada","role":"student"}'
# → {"token":"eyJ…","expiresAt":1763000000}
Field
roomId, userId Required. Letters, numbers and . _ : @ -, up to 128 characters.
name Display name. Defaults to userId.
role "teacher", "student", "observer", or your own label. See below.
permissions Override single permissions: { "mic", "camera", "screen", "moderate" } as booleans.
canPublish false makes a view-only participant, such as a webinar audience member. Ignored for the built-in roles.
metadata App data everyone in the room can see but the participant can't change. Up to 4 KB as JSON.
ttlSeconds How long the token works. Default 7200 (2 hours), from 60 to 86400.
maxParticipants Room size limit when this token joins, from 2 to 10000. Use 2 for one-on-one calls.
e2ee true means this person must use end-to-end encryption (web only).

Mint tokens only after you've checked who the user is and that they may join that room. Mint a fresh token for each join, rather than storing them.

Call types

All calls use the same room API. Pick the call type with the token and the joinRoom options.

Call Token Frontend
One-on-one video maxParticipants: 2 joinRoom({ url, token })
One-on-one voice maxParticipants: 2 joinRoom({ url, token, mode: "audio" })
Group video optionally a limit, e.g. maxParticipants: 12 joinRoom({ url, token })
Group voice joinRoom({ url, token, mode: "audio" })
Webinar speakers as usual; audience with canPublish: false the same joinRoom

Roles and permissions

Role mic camera screen moderate
teacher ✓ ✓ ✓ ✓
student ✓ ✓ – –
observer – – – –
  • permissions overrides single values. For example, {"role":"student","permissions":{"screen":true}} is a student who may present.
  • Any other role name (up to 32 letters, numbers and . _ -) is a label your UI can show. Its permissions come from canPublish.
  • Without a role, everyone may publish (participant), or nobody may if canPublish is false (viewer).
  • moderate lets someone mute others, remove people, admit from the waiting room, run polls and start recordings. See Classrooms.

You can change a role or permissions during the call from your backend:

bash
curl -X PATCH https://api.appsocom.dev/rooms/class-1/participants/u_7 \
  -H "Authorization: Bearer $APPSOCOM_API_KEY" -H "Content-Type: application/json" \
  -d '{"role":"teacher"}'

Long calls

Tokens expire after ttlSeconds, and a participant whose token has expired is removed from the room (the left event's reason is unauthorized, and webhooks report token-expired). Pick a ttlSeconds longer than your calls, or refresh the token. The client fires token-expiring a minute before expiry. Fetch a new token and hand it over:

ts
room.on("token-expiring", async () => room.updateToken(await fetchNewToken()));

Limits

Your project's plan sets a room size limit and monthly allowances. When a limit is reached, new tokens are refused with 429, and people already in a call aren't cut off. See Pricing.