REST API

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

ParameterTypeLocationRequiredDescription
tokenstringpathYesBroadcast 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

FieldTypeDescription
idstringBroadcast ID (UUID)
namestringChannel name
access_typestringAccess type: public / password
requires_passwordbooleanWhether password verification is required
statusstringBroadcast status
is_livebooleanWhether the broadcast is currently live
transcription_languagestringTranscription language (backward compatible, equals the first element of transcription_languages)
transcription_languagesarrayList of transcription languages (string[], up to 10, distinct)
translation_languagesarrayList of translation languages
tts_languagesarrayLanguages for which the host has enabled voice playback; an empty array when the channel is not live
tts_voicesobjectTTS 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:

FieldTypeDescription
voice_namestringVoice name (for API use)
display_namestringDisplay name
genderstringGender: Female / Male

Specific Error Codes

Error CodeHTTP StatusDescriptionSuggested Action
broadcast_token_invalid401Token invalid or not foundVerify that the token is correct
broadcast_token_revoked401Broadcast has been revokedThis broadcast is no longer available
too_many_requests429Too many requests; see Rate LimitsWait 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

ParameterTypeLocationRequiredDescription
tokenstringpathYesBroadcast share token (4-character short code, character set a-z0-9)
passwordstringbodyYesChannel 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 message text is returned in Traditional Chinese and is meant for display only -- do not parse or match on it.

Response Fields

FieldTypeDescription
viewer_access_tokenstringViewer access token (valid for 24 hours); null for public channels
expires_atstringToken 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 CodeHTTP StatusDescriptionSuggested Action
broadcast_token_invalid401Token invalidVerify that the token is correct
broadcast_token_revoked401Broadcast has been revokedThis broadcast is no longer available
broadcast_password_incorrect401Incorrect passwordRe-enter the correct password
validation_failed422Parameter validation failedVerify that the password format is correct
too_many_requests429Too many requests, or temporarily locked after too many incorrect passwords; see Rate LimitsWait 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).

LimitApplies toRule
Per-channel totalViewer 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 channelsViewer 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 verificationTemporarily locked after 30 incorrect passwords for the same channel from the same source within 5 minutes
Incorrect-password lock (per channel)Password verificationTemporarily 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_token already 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: GET and POST. Request headers are not restricted, e.g. Content-Type: application/json.
  • Do not send credentials, such as credentials: 'include' in fetch or withCredentials = true in XMLHttpRequest; otherwise the browser blocks the response.
  • When a 429 is returned, the web page can read the Retry-After header.
  • The caption stream GET /broadcast/{token}/text also accepts connections from any domain. For a password-protected broadcast, put viewer_access_token in the URL query parameter, not in a request header; the browser's native EventSource is all you need. See Broadcast Viewer SSE.

Version: V1.24.1 Last Updated: 2026-10-07

Copyright © 2026