One network.
One worldwide schedule.
The website is AVOBOX’s control center. It manages languages, station brands, multilingual channels, saved YouTube videos, and exact broadcast showtimes. Android reads the published lineup and handles playback.
All start and end times are stored in UTC. Pacific time is an administration display setting, with PST/PDT handled automatically. Every viewer receives the same broadcast IDs and showtimes.
The public contract
Base URL: https://avobox.cc/api/v1 (live over HTTPS). Public read endpoints need no credentials. CORS is enabled for these endpoints. Admin endpoints require a protected session and are not intended for Android clients.
| GET endpoint | Returns |
|---|---|
| /languages | Published language IDs, codes, and names |
| /stations | Published station brands |
| /channels?language=vi | Published channels matching a language code |
| /schedules?channelId=ch_001&from=…&to=… | Programs intersecting a UTC window, up to 31 days |
| /channels/ch_001/now | Current program, next program, server time, and revision |
| /lineup?language=en&limit=50 | Atomic, paginated channels and programs for a large guide |
Join at the right moment
{
"serverTimeUtc": "2026-10-25T05:00:00Z",
"scheduleRevision": 12,
"channelId": "ch_001",
"current": {
"broadcastId": "broadcast_1042",
"channelId": "ch_001",
"title": "Example Movie",
"startsAtUtc": "2026-10-25T04:30:00Z",
"endsAtUtc": "2026-10-25T06:30:00Z",
"source": {
"type": "youtube",
"videoId": "VIDEO_ID",
"inPointSeconds": 0
},
"durationSeconds": 7200
},
"next": null
}This is an illustrative response; real video IDs contain 11 characters. Thirty minutes after the start, join at 1,800 seconds. A source in-point of 120 seconds would make the playback position 1,920 seconds.
positionSeconds = source.inPointSeconds
+ (estimatedServerTime - startsAtUtc) / 1000- At request send and response receipt, record Android’s monotonic clock. Estimate one-way delay as half the round-trip time.
- At receipt, anchor estimated server time to the response’s
serverTimeUtcplus half the round-trip time. Advance it using the monotonic clock, rather than the Android wall clock. - Clamp playback to the interval between the source in-point and the source in-point plus broadcast duration. Stop or switch at the broadcast’s end.
- Poll
/nowperiodically, at boundaries, and after reconnecting. IfscheduleRevisionchanges, refetch cached schedules and re-evaluate the current broadcast. - A gap returns
current: null. Show an off-air state and use the next start time. A missing or unpublished channel returns 404. - YouTube playback availability and seeking are handled by the player. Handle unavailable, region-blocked, removed, and embedding-disabled videos. The API stores IDs; it does not provide temporary playback URLs or bypass YouTube restrictions.
Drafts, publishing, and permanent IDs
Edits are saved to the draft workspace. “Include in the next published lineup” marks eligibility. “Review & publish” validates the network and creates an immutable, atomic snapshot with an incremented revision. Public APIs only read that snapshot. Renaming, translating, or renumbering a channel preserves its permanent ID.
Channel languages are a list of permanent language IDs. A single channel may match ?language=en and ?language=vi, while keeping one shared schedule. Public list responses use items, serverTimeUtc, scheduleRevision, and publishedAtUtc.
Schedule boundaries
Programs occupy half-open intervals: startsAtUtc ≤ now < endsAtUtc. The end time is calculated from start plus broadcast duration. Clips must fit within exact saved video duration. Overlapping drafts are rejected. Gaps are flagged and may be explicitly published. The window query includes a program that starts before the requested window and ends within it.
Shuffle once. Broadcast everywhere.
The management shuffle tool chooses from saved videos and stores a full 24-hour draft schedule. It enforces a configurable no-repeat window (12hours by default), avoids consecutive YouTube creators, and refuses to save an incomplete day when the pool is too small. It clips the final video to fit the window, and rejects occupied windows. Randomization happens on the backend, before publication. Devices never search, shuffle, or generate their own lineup.
The sample channel
ch_001 is a clearly labeled test channel. On initial database creation, it receives three UTC days of sample programming, each containing 144 contiguous ten-minute clips. The sample source is Blender Foundation’s Big Buck Bunny on YouTube. Metadata is labeled sample/unverified until refreshed via YouTube import. This schedule is saved once, and does not regenerate per request.
The supplied sample JSON fixture is in docs/sample-day.json. Use the management calendar or shuffle tool to add future days. Demo schedules expire after their published dates; the API then correctly returns an off-air state.
A reusable video library
The test bed contains1,000channel concepts each for English, Vietnamese, Chinese, and Spanish. The library stores video IDs, titles, reported durations, creator identities, category and language tags. It deduplicates by YouTube video ID and caches each search for24hours. Scheduling reuses this library without searching. Bounded automatic discovery can find new videos; it saves draft metadata and never publishes automatically.
YouTube search and import
The current test bed can search through backend metadata extraction without a Data API key. These results are labeled search metadata and language tags require review. Set YOUTUBE_API_KEY on the backend to use the official Data API and import verified duration metadata. The protected control center searches embeddable videos and imports titles, descriptions, thumbnails, and exact durations from YouTube. Live streams and videos without finite durations are excluded. Search results only reach viewers after they are saved, scheduled, and published.
Implementation references: YouTube search and video metadata and durations. API credentials stay on the backend.
Website preview and Android
The Android integration and website read the same published IDs, showtimes and revisions. Android anchors server UTC to a monotonic clock and displays Pacific time. The website uses native video, starts muted, seeks to the live offset, and gives anonymous visitors60seconds from first playback before stopping and redirecting to the purchase page. Server-side trial state persists across refreshes. In this test deployment, native website media is relayed through the connected MEmu test device; its private resolver and the ADB tunnel must stay available. Production media delivery is a separate deployment step.
Purchases and advertising
Box reservations and advertising inquiries are saved privately for administrators. Payment processing and automatic advertisement delivery are not connected. No payment is collected and no ad-placement purchase is created by submitting a form.