---
title: "API Authentication"
canonical_url: "https://apidocs.sportradar.com/resources/virtual-stadium/docs/api/authentication"
markdown_url: "https://apidocs.sportradar.com/resources/virtual-stadium/docs/api/authentication.md"
last_updated: "2026-04-10T12:42:42Z"
---

# API Authentication

All Virtual Stadium API requests require authentication using JWT (JSON Web Token) bearer tokens. Authorization and permission checks are enforced server-side; contact your Sportradar integration contact for permission setup.

## Overview

JWT authentication in Virtual Stadium serves multiple purposes:

- User identification
- Authorization (enforced server-side)
- Security and integrity of requests
- Session management across API calls

## JWT Token Structure

Virtual Stadium uses JSON Web Tokens (JWT) to securely transmit information between parties. A JWT consists of three components:

- **Header**: Contains metadata about the token, including the algorithm used for signing and the token type.
- **Payload**: Contains the claims, which include user data and permissions.
- **Signature**: Ensures the integrity of the token by verifying that it hasn't been tampered with.

For more details about JWT, refer to the official documentation: [JSON Web Tokens (JWT)](https://jwt.io/introduction/)

### Claim Descriptions

Each claim in the JWT payload serves a specific purpose to ensure secure and accurate authentication. Below is a detailed description of each claim used in the Virtual Stadium API:

| Claim         | Required | Description                                                                                                                                                                                                                                                                                                                                                                  |                                                                           |
| ------------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------- |
| `iss`         | ✅        | **Issuer** - A unique identifier for the entity that issued the token. This is typically provided when you submit the RSA public key.                                                                                                                                                                                                                                        | expose user IDs, use a derivation such as a salted hash of the actual ID. |
| `env`         | ✅        | **Environment** - `"dev"` or `"prod"` to validate against correct signing key                                                                                                                                                                                                                                                                                                |                                                                           |
| `iat`         | ✅        | Time at which the JWT was issued. Its value is a JSON number representing the number of seconds from 1970-01-01T00:00:00Z as measured in UTC. It is often added automatically by libraries when signing the token. We use this to limit the maximum validity time, with a default duration of 16 hours. You can also add the exp claim to limit the expiration time further. |                                                                           |
| `scope`       | ✅        | **Scope** -  Space-separated list of permissions granted to this end-user. For example, only users with av in their scope can use the video stream in Live Match Tracker. For virtual stadium use vs in the scope. And for bet concierge use sb in the scope. If user has access to multiple products, add multiple scopes separated with space. Example: 'av vs'            |                                                                           |
| `sub`         | ✅        | **Subject** - Unique end-user ID. You can use the actual user ID from your system, or if you do not want to expose user IDs, use a derivation such as a salted hash of the actual ID.                                                                                                                                                                                        |                                                                           |
| `userId`      | ✅        | **User ID** - Unique end-user ID. You can use the actual user ID from your system, or if you do not want to expose user IDs, use a derivation such as a salted hash of the actual ID.                                                                                                                                                                                        |                                                                           |
| `displayName` | ✅        | **Display Name** - Name shown used in UI components                                                                                                                                                                                                                                                                                                                          |                                                                           |
| `userType`    | ✅        | **User Type** - `"Moderator"`                                                                                                                                                                                                                                                                                                                                                |                                                                           |
| `apiKey`      | ✅        | **API Key**                                                                                                                                                                                                                                                                                                                                                                  |                                                                           |

```json
{
    "iss": "issuer-id",
    "sub": "unique-user-id",
    "env": "prod",
    "scope": "vs",
    "iat": 1697040000, 
    
    // Virtual Stadium API requirements
    "apiKey": "your-api-key-from-operator",
    "userId": "unique-user-id",
    "displayName": "user-display-name",
    "userType": "Moderator" 
}
```

Note: Authorization and permission enforcement is performed server-side. If your integration requires specific management or moderation permissions, follow the setup instructions provided by your Sportradar contact.

## Setting up Authentication

### 1. Generate RSA Key Pair

```bash
# Generate private key
openssl genrsa -out rsa-private.pem 2048

# Generate public key
openssl rsa -in rsa-private.pem -pubout -outform PEM -out rsa-public.pem
```

Share the public key with Sportradar and keep the private key secure.

### 2. Create JWT Tokens (Example)

```javascript
const jwt = require('jsonwebtoken');
const fs = require('fs');

const privateKey = fs.readFileSync('rsa-private.pem');

const payload = {
  iss: 'your-client-identifier',
  sub: 'user123',
  env: 'prod',
  scope: 'vs',
  apiKey: 'your-api-key',
  userId: 'user123',
  displayName: 'John Doe',
  userType: 'Moderator'
};

const token = jwt.sign(payload, privateKey, {
  algorithm: 'RS256',
  expiresIn: '1h'
});
```

## Making Authenticated Requests

Include the JWT in the Authorization header:

```
Authorization: Bearer <your-jwt-token>
```

Example (fetch):

```javascript
const response = await fetch('https://management.vs.sportradar.com/api/channel/create', {
  method: 'POST',
  headers: {
    'Authorization': `Bearer ${jwtToken}`,
    'Content-Type': 'application/json'
  },
  body: JSON.stringify(channelData)
});
```

cURL example:

```bash
curl -X POST https://management.vs.sportradar.com/api/channel/create \
  -H "Authorization: Bearer <jwt-token>" \
  -H "Content-Type: application/json" \
  -d '{"channelId":"test-channel","channelName":"Test Channel",...}'
```

## Token Validation and Security

- env-based validation: `"dev"` vs `"prod"` selects validation key.
- Set appropriate expiration (`exp`) and implement refresh where needed.
- Handle token expiration and validation errors gracefully.

Security recommendations:

- Keep private keys secure and never expose them client-side.
- Use HTTPS for all requests.
- Avoid overly long-lived tokens.
- Validate tokens server-side and monitor token usage.

## Common Authentication Errors

### 401 Unauthorized

```json
{
  "success": false,
  "error": "Authentication required",
  "details": "Invalid or missing JWT token"
}
```

Causes: missing Authorization header, malformed token, expired token, invalid signature.

### 403 Forbidden

```json
{
  "success": false,
  "error": "Insufficient permissions",
  "details": "Required permissions missing"
}
```

Causes: server-side permission requirements not met for the requested operation.

## Testing Authentication

- Use `"env": "dev"` for development tokens.
- Use JWT decoders to inspect payload and claims.
- Test token validation against the public key provided to Sportradar.

## Integration Examples

### Web Widget

```html
<script>
  const jwtToken = 'your-jwt-token';
  SIR('init', {
    apiKey: 'your-api-key',
    jwtToken
  });
</script>
```

### API Client

```javascript
class VirtualStadiumAPI {
  constructor(jwtToken) {
    this.token = jwtToken;
    this.baseURL = 'https://management.vs.sportradar.com/api';
  }

  async createChannel(channelData) {
    const resp = await fetch(`${this.baseURL}/channel/create`, {
      method: 'POST',
      headers: {
        'Authorization': `Bearer ${this.token}`,
        'Content-Type': 'application/json'
      },
      body: JSON.stringify(channelData)
    });
    return resp.json();
  }
}
```

## Support and Resources

- [JWT Tutorial](https://apidocs.sportradar.com/resources/widgets/docs/tutorials/jwt.md)
- [Integration Overview](https://apidocs.sportradar.com/resources/virtual-stadium/docs/web/adapter/overview.md)
- [SDK Authentication](https://apidocs.sportradar.com/resources/virtual-stadium/docs/sdk/overview.md)

Note: contact your Sportradar integration contact for permission/role setup and any environment-specific details.
