Context token
Your page runs in the person's browser, so anything it says about «who I am» can be faked. When your server needs to know who opened the app — to save results, charge, or give access — use the context token.
app.contextToken is a JWT signed by ReMeet (RS256). ReMeet issues a fresh one every time the app frame starts.
What's inside
{
"iss": "https://remeet.video",
"aud": "your-app-key",
"sub": "p_3f9c0a7d51e2b84c6a0d9e17",
"name": "Anna Ivanova",
"room": "01m6saztdr6cafg9yzx83db0fs",
"role": "host",
"surface": "panel",
"locale": "en",
"iat": 1794067200,
"exp": 1794067800,
"jti": "1b4e28ba-2fa1-11d2-883f-0016d3cca427"
}| Claim | Meaning |
|---|---|
iss | Always https://remeet.video. |
aud | Your app key. Reject tokens for other apps. |
sub | The participant id for your app — the same as app.me.id. Stable for one person across meetings. |
name | The name the person has in the meeting. |
room | The meeting id — the same as app.context.meeting.id. |
role | host, member or guest. |
surface | panel or stage. |
locale | en, ru or ar. |
iat, exp | Issued at and expiry (Unix seconds). The token lives 10 minutes. |
jti | Unique token id: remember used ones if you need to block replays. |
Verify it on your server
Public keys: remeet.video/.well-known/jwks.json. Pick the key by kid from the token header and cache the set — keys rarely change.
import { createRemoteJWKSet, jwtVerify } from 'jose';
const jwks = createRemoteJWKSet(new URL('https://remeet.video/.well-known/jwks.json'));
export async function verifyReMeet(token) {
const { payload } = await jwtVerify(token, jwks, {
issuer: 'https://remeet.video',
audience: 'your-app-key',
algorithms: ['RS256'],
});
return payload; // { sub, name, room, role, … }
}import jwt
jwks = jwt.PyJWKClient("https://remeet.video/.well-known/jwks.json")
def verify_remeet(token: str) -> dict:
key = jwks.get_signing_key_from_jwt(token)
return jwt.decode(
token,
key.key,
algorithms=["RS256"],
audience="your-app-key",
issuer="https://remeet.video",
)use Firebase\JWT\JWK;
use Firebase\JWT\JWT;
function verifyReMeet(string $token): object
{
$jwks = json_decode(file_get_contents('https://remeet.video/.well-known/jwks.json'), true);
$claims = JWT::decode($token, JWK::parseKeySet($jwks));
if ($claims->iss !== 'https://remeet.video' || $claims->aud !== 'your-app-key') {
throw new RuntimeException('Not a token for this app');
}
return $claims;
}The usual flow
The app starts:
const app = await ReMeet.ready().It sends
app.contextTokento your server once:jsconst response = await fetch('https://api.your-site.example/session', { method: 'POST', headers: { Authorization: `Bearer ${app.contextToken}` }, });Your server verifies the token and answers with its own session (a cookie or your own token) that lives as long as you need.
The 10-minute lifetime is for this exchange, not for the whole meeting. A new token comes when the frame starts again (the person reopens the panel or reloads the page).
CORS
Your API is called from your own page's origin (the frame address), not from remeet.video. Allow that origin in CORS.