Speak login link with the administrator role
Kinescope lets you set a participant’s role in the Speak room link. You sign a JWT token (JSON Web Token) on your server and append it to the link. The person opens it and enters the room as an administrator.
You do not assign rights in the Speak interface. The role arrives with the link, and your system decides who receives it.
Who this article is for
- Platform developers — need to issue meeting links from an LMS, CRM, or personal account
- Backend developers — need to sign tokens with a role on their side
- Webinar integrators — need the host to enter the room with full rights
When you need a Speak link with a role
Typical cases:
- The host starts from your product — a teacher clicks “Start lesson” in your system and joins the room as an administrator
- Automatic link delivery — the meeting schedule lives in your system, and host links are generated without a person in the loop
- Several hosts in one room — your system manages rights, not the room owner
- No manual role assignment — nobody sets roles in the Speak UI before each meeting
If at least one of these is familiar, read on.
How login with a role works (4 steps)
The scheme is the same as for stream chat: RSA asymmetric cryptography, the private key stays with you.
- You create a key pair (private and public) on your server
- The public key is stored in Kinescope via API (the private key stays only with you)
- Your server creates a JWT token with
aud,room_id, androle, and signs it with the private key - The user opens the link with the token — Kinescope verifies the signature with the public key and lets them into the room with that role
Now the setup.
Step 1 — signing keys
Speak keys are generated and stored the same way as for stream chat. If you already set up JWT for chat, skip to step 2. You do not need a new key.
What to do:
- Generate an RSA key pair and prepare the public key in JWK format — generating keys
- Store the public key in Kinescope via
POST /v1/jwk— saving the public key - List active keys if you need to — key management
aud field in the token, not by the key.Step 2 — token for Speak
Create a JWT token and sign it with the private key using RS256. Pass the key identifier in the token header as kid.
Required fields
aud(audience) —"speak". This tells Kinescope the token is for a video meeting, not for chat.room_id— the room code from its link, for examplejqi-qhua-glk. It must match the code in the URL the user opens.role— participant role. The supported value is"admin": the participant gets room administrator rights.
Where to get the room code: it is at the end of the room link in the Speak interface. The API returns it in code and link in the GET /v1/speak/rooms response — see the API reference
.
Standard JWT fields (recommended)
Add exp, iat, and nbf. They work the same as in stream chat and are checked during validation. Details: standard JWT fields
.
Payload example
{
"aud": "speak",
"room_id": "jqi-qhua-glk",
"role": "admin",
"iat": 1703500800,
"exp": 1703504400
}
Token generation example
package main
import (
"crypto/rsa"
"time"
"github.com/golang-jwt/jwt/v5"
)
type SpeakClaims struct {
RoomID string `json:"room_id"` // room code from the link
Role string `json:"role"` // admin
jwt.RegisteredClaims
}
// Generate a token to join a Speak room
func generateSpeakJWT(privateKey *rsa.PrivateKey, kid, roomID, role string) (string, error) {
now := time.Now()
claims := SpeakClaims{
RoomID: roomID,
Role: role,
RegisteredClaims: jwt.RegisteredClaims{
Audience: []string{"speak"}, // must be "speak"
IssuedAt: jwt.NewNumericDate(now),
ExpiresAt: jwt.NewNumericDate(now.Add(1 * time.Hour)),
},
}
token := jwt.NewWithClaims(jwt.SigningMethodRS256, claims)
token.Header["kid"] = kid // Key ID of the public key stored in Kinescope
return token.SignedString(privateKey)
}
Signing mechanics and libraries for other languages: JWT generation example .
Login link
Append the finished token to the room link as the token parameter:
https://speak.kinescope.io/{{room_code}}?token={{jwt}}
Example:
https://speak.kinescope.io/jqi-qhua-glk?token=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6ImtleS0yMDI0LTEyLTI1In0.eyJhdWQiOiJzcGVhayIsInJvb21faWQiOiJqcWktcWh1YS1nbGsiLCJyb2xlIjoiYWRtaW4iLCJpYXQiOjE3MDM1MDA4MDAsImV4cCI6MTcwMzUwNDQwMH0.signature_here
Done. Anyone who opens this link joins the room as an administrator.
Security
admin role grants full rights in the room. Issue these links only to users your system has already authorized, and do not publish them. The link with the token is the pass: anyone who gets it enters as an administrator.What to follow:
- Short token lifetime — set
expclose to the meeting length, not months ahead - Generate on the backend — the private key must not reach a browser or a mobile app
- No tokens in logs or analytics — a link with a token must not leak into systems where strangers can see it
- A separate link per host — easier to revoke access and see who used what
Key rotation and what to do if the private key leaks are in the chat article: key rotation and actions when a key is compromised .
Troubleshooting
Token not accepted by the system
Problem: the user opens the link but does not enter the room, or joins without the administrator role.
Check in this order:
aud— must be exactly"speak"in lowercase. A chat token ("chat") will not work in Speak.room_id— the room code in the token must match the code in the URL. Forhttps://speak.kinescope.io/jqi-qhua-glkthe token needs"room_id": "jqi-qhua-glk".role—"admin"in lowercase.- Token lifetime — check
expand NTP clock sync on the server. - Public key — it must be uploaded to Kinescope, not expired, and the token signed with the matching private key using RS256.
To check the token structure and signature locally before sending it to a user, use the example in how to verify token validity . Common key mistakes are in troubleshooting .
If that does not help, write to support . Include the room code, a sample token (you can mask sensitive parts), and the steps to reproduce.
What’s next?
After you set up links with a role:
- What is Speak? — video meetings and saving recordings to the catalog
- JWT authentication for stream chat — the same key mechanism for chat
- Speak API reference — rooms, participants, and calls
Questions? Write to the support chat in the Kinescope interface.