Viewer REST API
Overview
Note: The Viewer API does not require API Key authentication. Broadcasts are identified by the
{token}in the URL (a 4-character short code, character set a-z0-9, used as the broadcast share token).
GET /api/v1/viewer/broadcasts/{token}
Description
Retrieve the public information of a specific broadcast for display on the viewer side. This endpoint returns only public information and does not include sensitive data.
Authentication
No API Key authentication is required. The broadcast is identified by the {token} in the URL path.
Request Parameters
| Parameter | Type | Location | Required | Description |
|---|---|---|---|---|
token | string | path | Yes | Broadcast share token (4-character short code, character set a-z0-9) |
Request Example
curl -X GET "https://vas-poc.vurbo.ai/api/v1/viewer/broadcasts/a3f9"
Success Response
HTTP 200
{
"data": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"name": "My Broadcast Channel",
"access_type": "password",
"requires_password": true,
"status": "active",
"is_live": true,
"transcription_language": "zh-TW",
"transcription_languages": ["zh-TW", "en-US"],
"translation_languages": ["en-US", "ja-JP"],
"tts_languages": ["en-US", "ja-JP"],
"tts_voices": {
"en-US": [
{ "voice_name": "en-US-JennyNeural", "display_name": "Jenny", "gender": "Female" },
{ "voice_name": "en-US-GuyNeural", "display_name": "Guy", "gender": "Male" }
],
"ja-JP": [
{ "voice_name": "ja-JP-NanamiNeural", "display_name": "Nanami", "gender": "Female" },
{ "voice_name": "ja-JP-KeitaNeural", "display_name": "Keita", "gender": "Male" }
]
}
}
}
Response Fields
| Field | Type | Description |
|---|---|---|
id | string | Broadcast ID (UUID) |
name | string | Channel name |
access_type | string | Access type: public / password |
requires_password | boolean | Whether password verification is required |
status | string | Broadcast status |
is_live | boolean | Whether the broadcast is currently live |
transcription_language | string | Transcription language (backward compatible, equals the first element of transcription_languages) |
transcription_languages | array | List of transcription languages (string[], up to 10, distinct) |
translation_languages | array | List of translation languages |
tts_languages | array | Languages for which the host has enabled voice playback; an empty array when the channel is not live |
tts_voices | object | TTS voice list for each translation language (reduces extra API calls on the viewer side) |
tts_voices Structure
tts_voices is an object keyed by language code, where each language contains an array of available voices:
| Field | Type | Description |
|---|---|---|
voice_name | string | Voice name (for API use) |
display_name | string | Display name |
gender | string | Gender: Female / Male |
Specific Error Codes
| Error Code | HTTP Status | Description | Suggested Action |
|---|---|---|---|
broadcast_token_invalid | 401 | Token invalid or not found | Verify that the token is correct |
broadcast_token_revoked | 401 | Broadcast has been revoked | This broadcast is no longer available |
too_many_requests | 429 | Too many requests; see Rate Limits | Wait for the number of seconds in the Retry-After response header, then retry |
POST /api/v1/viewer/broadcasts/{token}/verify
Description
Verify the viewer password and obtain a viewer access token. The returned viewer_access_token is used to connect to the SSE real-time subtitle stream.
If the channel is public (no password required), you can still call this endpoint; it will return success directly with viewer_access_token set to null.
Authentication
No API Key authentication is required. The broadcast is identified by the {token} in the URL path.
Request Parameters
| Parameter | Type | Location | Required | Description |
|---|---|---|---|---|
token | string | path | Yes | Broadcast share token (4-character short code, character set a-z0-9) |
password | string | body | Yes | Channel password (up to 12 characters; whether the actual password is verified depends on the settings configured at creation time) |
Request Example
curl -X POST "https://vas-poc.vurbo.ai/api/v1/viewer/broadcasts/a3f9/verify" \
-H "Content-Type: application/json" \
-d '{
"password": "mySecret123"
}'
Success Response
HTTP 200 -- Password Correct
{
"data": {
"viewer_access_token": "aB3dE5fG7hI9jK1lM3nO5pQ7rS9tU1vWaB3dE5fG7hI9jK1lM3nO5pQ7rS9tU1vW",
"expires_at": "2026-02-24T10:00:00.000Z"
}
}
HTTP 200 -- Public Channel (No Password Required)
{
"data": {
"viewer_access_token": null,
"message": "此頻道為公開,不需要密碼驗證"
}
}
The
messagetext is returned in Traditional Chinese and is meant for display only -- do not parse or match on it.
Response Fields
| Field | Type | Description |
|---|---|---|
viewer_access_token | string | Viewer access token (valid for 24 hours); null for public channels |
expires_at | string | Token expiration time (ISO 8601 format) |
Usage
After obtaining the viewer_access_token, include it when connecting to the SSE real-time subtitle stream:
GET /broadcast/{token}/text?viewer_access_token=xxx
Specific Error Codes
| Error Code | HTTP Status | Description | Suggested Action |
|---|---|---|---|
broadcast_token_invalid | 401 | Token invalid | Verify that the token is correct |
broadcast_token_revoked | 401 | Broadcast has been revoked | This broadcast is no longer available |
broadcast_password_incorrect | 401 | Incorrect password | Re-enter the correct password |
validation_failed | 422 | Parameter validation failed | Verify that the password format is correct |
too_many_requests | 429 | Too many requests, or temporarily locked after too many incorrect passwords; see Rate Limits | Wait for the number of seconds in the Retry-After response header, then retry; while locked, even the correct password must wait |
Rate Limits
When a limit is exceeded, both viewer endpoints return HTTP 429 too_many_requests with a Retry-After header (the number of seconds to wait).
| Limit | Applies to | Rule |
|---|---|---|
| Per-channel total | Viewer page and password verification (counted separately) | Per channel, the limit per minute is about twice the channel's maximum number of viewers (max_viewers; see Broadcast API), with a minimum of 200; all viewers of the channel share this allowance |
| Lookups of nonexistent channels | Viewer page and password verification (counted together) | After 20 lookups of nonexistent channels (returning broadcast_token_invalid) from the same source within 1 minute, the viewer page and password verification temporarily return 429 for that source |
| Incorrect-password lock (per source) | Password verification | Temporarily locked after 30 incorrect passwords for the same channel from the same source within 5 minutes |
| Incorrect-password lock (per channel) | Password verification | Temporarily locked after 100 incorrect passwords for the same channel within 5 minutes (from any source); during that time, password verification returns 429 for every viewer of the channel |
- While locked, even the correct password returns 429; wait for the period given in
Retry-After, then retry. - Correct passwords do not count toward the incorrect-password limits.
- The incorrect-password lock affects only password verification: the viewer page remains available, and a
viewer_access_tokenalready obtained remains usable until it expires.
Calling from a Browser
Your viewer page can live on your own domain. Both viewer endpoints can be called directly from a web page on any domain; there is no need to register your domain in advance.
- Methods:
GETandPOST. Request headers are not restricted, e.g.Content-Type: application/json. - Do not send credentials, such as
credentials: 'include'infetchorwithCredentials = trueinXMLHttpRequest; otherwise the browser blocks the response. - When a 429 is returned, the web page can read the
Retry-Afterheader. - The caption stream
GET /broadcast/{token}/textalso accepts connections from any domain. For a password-protected broadcast, putviewer_access_tokenin the URL query parameter, not in a request header; the browser's nativeEventSourceis all you need. See Broadcast Viewer SSE.
Version: V1.24.1 Last Updated: 2026-10-07