Some widget use cases require validated data integrity from your backend to prevent misuse by end-users or malicious actors. Create and sign a JSON Web Token (JWT) with a public/private key pair, then pass that token to widgets as a property.
JWT tokens must be signed with RS256 (RSA signature with SHA-256).
jsonwebtoken)The following diagram illustrates the JWT authentication flow:
Create a 2048-bit RSA key pair with OpenSSL.
Send rsa-public.pem to Sportradar so tokens can be validated.
Build the payload with required claims and sign with your private key (RS256).
Deliver the token from your backend and set it on widget initialization.
Generate a pair of RSA keys using the OpenSSL toolkit:
# Generate private key (2048-bit RSA)
openssl genrsa -out rsa-private.pem 2048
# Extract public key from private key
openssl rsa -in rsa-private.pem \
-pubout \
-outform PEM \
-out rsa-public.pemrsa-private.pemKeep this secure on your backend server and use it to sign tokens.
rsa-public.pemSend this file to Sportradar for token validation setup.
Optional: Verify the Generated Keys
# View private key
openssl rsa -in rsa-private.pem -text -noout
# View public key
openssl rsa -in rsa-public.pem -pubin -text -nooutExample public key format (rsa-public.pem):
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA...
...
-----END PUBLIC KEY-----rsa-private.pem) in client-side code, version control, or logsIf you need development or non-production JWTs, tell client setup which environment the public key is for (, , or ), and put the same value in the claim on JWTs signed with that key. Production-only flows can omit ; it defaults to production behavior.
Every logged-in user requires their own unique JWT.
Create a new token for each page request.
Generate once and cache on your backend until near expiration.
JSON Web Token (JWT) is an open standard (RFC 7519) that defines a compact and self-contained way for securely transmitting information between parties as a JSON object. This information can be verified and trusted because it is digitally signed.
Learn more about JWT structure.
Algorithm and token type
Claims (identity, scope, product data)
RS256 signature over header + payload
{
"header": {
"alg": "RS256",
"typ": "JWT"
},
"payload": {
"iss": "your-organization",
"sub": "user123",
"scope": "vs",
"iat": 1681718850
All JWT tokens must include these standard claims:
{
iss: '<organization>',
sub: '<id>',
scope: 'av' | 'vs' | 'sb' | 'av vs sb',
iat: 1681718850
}Add product claims only for the scopes you enable.
Sign your JWT using the RS256 algorithm with your private key. Most JWT libraries support RS256 signing.
payload object required
Token payload containing all required claims (see claim descriptions above).
privateKey string required
Your RSA private key in PEM format.
algorithm string required
Must be RS256 (RSA signature with SHA-256).
Returns a signed JWT token string that can be used to authenticate with Sportradar widgets and products.
exp if specified)Example Token Output
eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ1c2VyMTIzIiwic2NvcGUiOiJ2cyIsImlhdCI6MTY4MTcxODg1MCwiYXBpS2V5Ijoidi3NfbGl2ZV9hYmMxMjN4eXo3ODkiLCJ1c2VySWQiOiJ1c2VyMTIzIiwiZGlzcGxheU5hbWUiOiJKb2huIERvZSIsInVzZXJUeXBlIjoiTm9ybWFsIn0.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c...Example With Multiple Scopes (Node.js)
import jwt from "jsonwebtoken";
const token = jwt.sign(
{
sub: "user_12345",
scope: "av vs", // Audio/video + Virtual Stadium
// iat is added automatically
},
process.env.PRIVATE_SIGNING_KEY,
{ algorithm: "RS256" },
);Deliver the signed JWT from your backend to your frontend application, then pass it to the widget during initialization.
Rotate signing keys without service interruption:
Create a new RSA key pair using the same process as Step 1.
Send the new public key to your Sportradar representative.
Sportradar adds the new key to your configuration and notifies you. Both old and new keys work during the transition.
Start signing with the new private key, then inform Sportradar when migration is complete so the old public key can be removed.
Send the rsa-public.pem file to your Sportradar sales or client setup representative. They will configure the system to validate tokens signed with your private key.
prodnonproddevenvenv| Claim | Type | Description | Example |
|---|---|---|---|
iss | string | Issuer identifier — identifies the principal that issued the JWT. Typically your organization or application identifier. | 'your-organization' |
sub | string | Unique end-user identifier. Use your system's user ID or a salted hash if you prefer not to expose actual IDs. | 'user_12345' or 'a3f5b2c8d1e4' |
scope | string | Space-separated permissions for this user. Controls access to specific features.av - Enables audio/video stream access in Live Match Tracker.vs - Virtual Stadium access.sb - Bet Concierge access | 'av vs' for LMT audio/video and Virtual Stadium (space-separated) |
iat | number | Token issued-at timestamp in seconds since Unix epoch (UTC). Default validity: 16 hours. Most JWT libraries add this automatically. | 1681718850 |
exp | number (optional) | Expiration timestamp in seconds since Unix epoch (UTC). If omitted, defaults to 16 hours after iat. | 1681776450 |
env | string (optional) | Which environment the signing key is for: prod, nonprod, or dev. Set when you use a non-production key (for example a development-only key pair); tell client setup the same when you submit that key's public key. Omit or leave empty for your production key—then behavior matches prod. | 'dev' |
The iat claim is typically added automatically by JWT libraries. You can also add an exp (expiration) claim to set a shorter validity period than the default 16 hours. Shorter token lifespans improve security.
{
"iss": "your-organization",
"sub": "user123",
"scope": "vs",
"iat": 1681718850,
"exp": 1681776450
}{
// Base claims (iss, sub, scope, iat)
apiKey: '<key>',
displayName: '<userName>',
userType: 'Normal' | 'VIP'
}| Claim | Type | Description | Example |
|---|---|---|---|
apiKey | string | Your Virtual Stadium API key (provided during onboarding) | 'vs_api_key_abc123' |
displayName | string | Public name shown to other users in the Virtual Stadium interface | 'JohnDoe' or 'Player123' |
userType | string | User access level: 'Normal' or 'VIP'. VIP users have highlighted chat messages. | 'VIP' |
VIP users receive enhanced visibility with different design styling. Their chat messages are highlighted to stand out in conversations. For more details, see the VIP functionality documentation.
Virtual Stadium Payload Examples
Normal User Claims:
{
"apiKey": "vs_live_abc123xyz789",
"displayName": "John Doe",
"userType": "Normal"
}VIP User Claims:
{
"apiKey": "vs_live_abc123xyz789",
"displayName": "Jane Smith",
"userType": "VIP"
}Complete JWT Payload:
{
"iss": "your-organization",
"sub": "user123",
"scope": "vs",
"iat": 1681718850,
"exp": 1681776450,
"apiKey": "vs_live_abc123xyz789",
"displayName": "John Doe",
"userType": "Normal"
Sign JWT Token:
import jwt from "jsonwebtoken";
import fs from "fs";
// Load private key
const privateKey = fs.readFileSync("rsa-private.pem", "utf8");
// Create token with base + Virtual Stadium claims
const token = jwt.sign(
{
iss: "your-organization",
sub: "user123",
scope: "vs",
apiKey: "vs_live_abc123xyz789",
displayName: "John Doe",
userType: "Normal",
// iat is added automatically
},
privateKey,
{ algorithm: "RS256" },
);
console.log(token);Pass the JWT as a property when adding the widget using SIR:
SIR("addWidget", "#my-widget", "widget_name_here", {
jwt: generatedJwtToken,
// ... other widget properties
});