BingeBop exposes an HTTP API on port 18080 of the device's LAN IP.
All endpoints return JSON (Content-Type: application/json) and support CORS.
The API allows you to:
GET /api/describe to receive a machine-readable catalog of every endpoint,
step-by-step workflows, and the full settings reference. This is the recommended entry point
for AI agents and automation tools.
http://<device-ip>:18080
Find the device IP in Settings → Network on the TV, or via your router's client list.
The API uses a token-based authentication system with three tiers. Find the token in Settings → LAN API Access on your TV.
| Tier | Token Required | Access Level |
|---|---|---|
| OPEN | None | Read-only status, display modes, search, device profile |
| REMOTE | 4-character prefix (shown on QR code) |
Playback control, input, favourites, recordings |
| ELEVATED | Full 12-character token | Settings, data sources, backup, users, credentials |
Include the token as a query parameter or HTTP header:
# HTTP header (recommended)
curl -H "X-Api-Token: AB3KQ7M2X9V4" "http://192.168.1.50:18080/api/settings"
# Query parameter (discouraged — token appears in logs/history)
curl "http://192.168.1.50:18080/api/settings?token=AB3KQ7M2X9V4"
X-Api-Token header over the query parameter.
Tokens in URLs are visible in shell history, browser history, HTTP access logs,
and reverse-proxy logs. For POST endpoints, send credentials in the request body,
not the URL.
| Status | Body | Meaning |
|---|---|---|
| 401 | {"error":"unauthorized","hint":"..."} | Missing or wrong token |
| 403 | {"error":"insufficient_token","hint":"..."} | Endpoint needs the full token, but only the prefix was sent |
| 429 | {"error":"too_many_attempts","retry_after":N} | Brute-force protection — wait N seconds |
POST /api/data_source?type=xtream&url=http://provider:port&username=USER&password=PASSGET /api/data_sources — poll until refresh_status is complete (10–60 s)GET /api/search?q=BBCGET /api/play_channel?id=<id-from-search>POST /api/data_source?type=m3u&url=http://host/playlist.m3u&name=My+PlaylistGET /api/data_sources — wait for import to completePOST /api/data_source?type=hdhomerun&url=192.168.1.100&name=Living+RoomPOST /api/data_source?type=stalker&url=http://portal.example.com/c/&mac=00:1A:79:XX:XX:XXGET /api/storage/test?host=192.168.1.10&share=media&username=user&password=passGET /api/setting?key=local:samba_host&value=192.168.1.10GET /api/setting?key=local:samba_share&value=mediaGET /api/setting?key=local:samba_username&value=userGET /api/setting?key=local:samba_password&value=passGET /api/setting?key=local:storage_type&value=sambaGET /api/user/add?name=Kids&child=trueGET /api/user/switch?user_id=<id>GET /api/user/list — see all profilesGET /api/peers — find discoverable clustersGET /api/peer/initiate_join?cluster_id=<id>GET /api/peer/list_pendingGET /api/peer/approve_pair?device_uuid=<uuid>GET /api/backup/export?password=MySecretGET /api/backup/restore_stage?password=MySecretGET /api/backup/restore_apply?password=MySecretReturns the complete API catalog as structured JSON — endpoints, parameters, workflows, and settings reference. This is the recommended entry point for AI agents and automation tools.
Returns the current playback state: what's playing, codec, resolution, stream position, device UUID, etc.
Returns {"error":"No player active"} with HTTP 404 when nothing is playing.
Search the catalog by name. Returns channels, movies, series, and EPG programmes.
| Parameter | Required | Description |
|---|---|---|
| q | Yes | Search query (e.g. BBC, Breaking Bad) |
| limit | No | Max results, 1–200 (default: 30) |
| type | No | Filter by entity: channel, movie, series, epg |
| media | No | Filter by media: live, movie, series |
{
"q": "BBC",
"elapsed_ms": 12,
"count": 5,
"results": [
{
"type": "media",
"id": 4521,
"media": "c",
"name": "BBC One HD",
"poster": "http://...",
"channel_id": "bbc1.uk"
}
]
}
id field is the media_container ID — use it with
/api/play_channel, /api/play_movie, /api/favourite, etc.
Returns the device's hardware tier (FLOOR / LOW / MID / HIGH), capability manifest, and current provisioned settings.
Add a new IPTV data source. Supports four provider types. Parameters can be sent as query string or form body.
| Parameter | Required | Description |
|---|---|---|
| type | Yes | xtream, m3u, hdhomerun, or stalker |
| url | Yes | Provider URL (or device IP for HDHomeRun) |
| username | Xtream only | Xtream Codes username |
| password | Xtream only | Xtream Codes password |
| mac | Stalker only | MAC address (e.g. 00:1A:79:XX:XX:XX) |
| login | No | Stalker portal login (optional) |
| name | No | Display name for the source |
# Xtream Codes provider (recommended: header auth + form body)
curl -X POST -H "X-Api-Token: AB3KQ7M2X9V4" \
"http://tv:18080/api/data_source" \
-d "type=xtream&url=http://provider.com:8080&username=myuser&password=mypass&name=My+IPTV"
# M3U playlist
curl -X POST -H "X-Api-Token: AB3KQ7M2X9V4" \
"http://tv:18080/api/data_source" \
-d "type=m3u&url=http://example.com/channels.m3u"
# Query params also accepted (discouraged — credentials visible in logs)
curl -X POST "http://tv:18080/api/data_source?type=m3u&url=http://example.com/channels.m3u&token=AB3KQ7M2X9V4"
{"success":true, "id":3, "type":"xtream", "name":"My IPTV", "refresh":"started"}
The source starts importing immediately. Poll /api/data_sources to check progress.
Remove a data source and all its channels, credentials, and MACs.
| Parameter | Required | Description |
|---|---|---|
| id | Yes | Data source ID (from /api/data_sources) |
curl -X DELETE -H "X-Api-Token: AB3KQ7M2X9V4" "http://tv:18080/api/data_source?id=3"
List all configured data sources with their type, URL, EPG priority, refresh status, and (for Xtream) account info (username, expiry date, max connections, active connections).
Trigger a channel re-import for a single data source.
| Parameter | Required | Description |
|---|---|---|
| id | Yes | Data source ID |
Change a source's base URL (e.g. migrate to a mirror host). Cluster-synced.
| Parameter | Required | Description |
|---|---|---|
| id | Yes | Data source ID |
| value | Yes | New URL |
Set the country (ISO code) for a data source, used for channel-name normalization.
| Parameter | Required | Description |
|---|---|---|
| id | Yes | Data source ID |
| value | Yes | ISO country code (e.g. UK, US, DE) |
Set the EPG priority for a data source (lower number = higher priority when multiple sources provide guide data).
Play a stream URL directly.
| Parameter | Required | Description |
|---|---|---|
| url | Yes | Stream URL to play |
| play | No | true to start playback immediately (default: false, creates proxy only) |
| stream | No | Stream slot 1–4 for multi-view (default: 1) |
curl -H "X-Api-Token: ABCD" "http://tv:18080/api/play?url=http://stream.example.com/live.ts&play=true"
Tune to a channel by its catalog ID. Use /api/search to find the ID.
| Parameter | Required | Description |
|---|---|---|
| id | Yes | media_container ID |
Play a movie by catalog ID through the full StreamRouter path (source selection, failover).
| Parameter | Required | Description |
|---|---|---|
| id | Yes | media_container ID (use /api/search?media=movie to find it) |
Play a series episode by catalog ID.
| Parameter | Required | Description |
|---|---|---|
| id | Yes | media_container ID |
| resume_ms | No | Resume position in milliseconds |
Pause playback.
Resume playback.
Jump back to the live edge (exits timeshift).
Seek forward in the current stream.
| Parameter | Required | Description |
|---|---|---|
| seconds | No | Seconds to skip (default: 10) |
Seek backward in the current stream.
| Parameter | Required | Description |
|---|---|---|
| seconds | No | Seconds to skip back (default: 10) |
Change playback speed.
| Parameter | Required | Description |
|---|---|---|
| speed | No | Speed multiplier: 0.25–4.0 (default: 1.0) |
Adjust the audio-video synchronization offset.
| Parameter | Required | Description |
|---|---|---|
| offset | No | Offset in milliseconds (positive = delay audio, default: 0) |
Stop a specific stream slot.
| Parameter | Required | Description |
|---|---|---|
| stream | No | Stream slot 1–4 (default: 1) |
List all supported display modes with id, width, height, refreshRate, and active flag.
Switch to a specific display mode.
| Parameter | Required | Description |
|---|---|---|
| id | Yes | Mode ID from /api/display_modes |
Set the compositor layout for multi-stream viewing.
| Parameter | Required | Description |
|---|---|---|
| layout | Yes | fullscreen/0, pip/1, side_by_side/2, quad/3 |
Set which stream slot has focus in PIP mode.
| Parameter | Required | Description |
|---|---|---|
| stream | No | Stream slot 1–4 (default: 1) |
List audio tracks for the current stream. Returns trackIndex, language, label, mimeType, channels, bitrate, isSelected.
Select an audio track.
| Parameter | Required | Description |
|---|---|---|
| track | Yes | 0-based track index (-1 to disable audio) |
Returns the currently selected audio track, or null.
List subtitle tracks for the current stream. Returns trackIndex, language, label, mimeType, isSelected.
Select a subtitle track.
| Parameter | Required | Description |
|---|---|---|
| track | Yes | 0-based track index (-1 to disable subtitles) |
List available OCR languages and their download status.
Download OCR tessdata for a language.
| Parameter | Required | Description |
|---|---|---|
| lang | Yes | Language code (from /api/subtitles/languages) |
Add or remove a channel from the user's favourites.
| Parameter | Required | Description |
|---|---|---|
| channel_id | Yes | media_container ID |
| value | No | true to add (default), false to remove |
| user_id | No | User profile ID (default: current user) |
Add or remove a VOD title from the user's watchlist ("My List").
| Parameter | Required | Description |
|---|---|---|
| container_id | Yes | media_container ID of the movie or series |
| value | No | true to add (default), false to remove |
| user_id | No | User profile ID (must be > 0) |
Set a custom display name for a channel (user override — does not change the source data).
| Parameter | Required | Description |
|---|---|---|
| id | Yes | media_container ID |
| name | Yes | New display name |
| user_id | No | User ID (default: 0 = cluster-wide override) |
List all user profiles with their IDs, names, and child flags. Also returns active_user_id.
Create a new user profile.
| Parameter | Required | Description |
|---|---|---|
| name | Yes | Profile display name |
| child | No | true for a child profile (parental controls apply). Default: false |
curl -H "X-Api-Token: AB3KQ7M2X9V4" "http://tv:18080/api/user/add?name=Kids&child=true"
→ {"success":true, "id":2, "uuid":"a1b2c3...", "name":"Kids", "child":true}
Switch the active user profile. Returns 404 if the user ID doesn't exist.
| Parameter | Required | Description |
|---|---|---|
| user_id | Yes | User ID from /api/user/list (0 = Owner) |
Start recording the currently-playing channel.
| Parameter | Required | Description |
|---|---|---|
| title | No | Recording title (defaults to channel name) |
Stop a recording.
| Parameter | Required | Description |
|---|---|---|
| uuid | Yes | Recording UUID (from /api/recording/list) |
List all recordings with their UUIDs, titles, durations, and status.
Play back a recording.
| Parameter | Required | Description |
|---|---|---|
| uuid | Yes | Recording UUID |
Delete a recording.
| Parameter | Required | Description |
|---|---|---|
| uuid | Yes | Recording UUID |
Create, list, or cancel scheduled recordings.
| Parameter | Required | Description |
|---|---|---|
| op | No | create (default), list, or cancel |
| channel | Create | Channel media_container ID |
| kind | Create | programme or interval |
| start | Interval | Start time (epoch seconds) |
| end | Interval | End time (epoch seconds) |
| uuid | Cancel | Schedule UUID to cancel |
Set, list, or cancel reminders for upcoming programmes.
| Parameter | Required | Description |
|---|---|---|
| op | No | create (default), list, or cancel |
| channel | Create | Channel media_container ID |
| kind | Create | programme or series |
| uuid | Cancel | Reminder UUID to cancel |
Trigger an urgent EPG guide data refresh. EPG also refreshes automatically every few hours.
Pin a channel to a specific EPG source (overrides automatic matching).
| Parameter | Required | Description |
|---|---|---|
| media_container_id | Yes | Channel ID |
| channel_id | Yes | XMLTV channel ID |
| data_source_uuid | Yes | EPG data source UUID |
Remove an EPG pin (revert to automatic matching).
| Parameter | Required | Description |
|---|---|---|
| media_container_id | Yes | Channel ID |
Check EPG pin status for a channel — returns active pin, persisted pin, and total pin count.
Get all settings and their current values for the active user. Returns user_id and a settings object.
Read or write a single setting.
| Parameter | Required | Description |
|---|---|---|
| key | Yes | Setting key (see Chapter 19) |
| value | No | New value to set. Omit to read the current value. |
# Read a setting
curl -H "X-Api-Token: AB3KQ7M2X9V4" "http://tv:18080/api/setting?key=local:scaling_method"
→ {"key":"local:scaling_method", "value":"0"}
# Write a setting
curl -H "X-Api-Token: AB3KQ7M2X9V4" "http://tv:18080/api/setting?key=local:scaling_method&value=2"
→ {"success":true, "key":"local:scaling_method", "value":"2"}
Read or write a device-global (local:) setting, always stored under user 0.
Use this instead of /api/setting for device-level config that shouldn't vary per user.
| Parameter | Required | Description |
|---|---|---|
| key | Yes | Setting key (typically local:...) |
| value | No | New value to set. Omit to read. |
Apply (or re-apply) the per-tier device manifest into settings.
With ?force=true, re-seeds all tier defaults.
Test a Samba/NAS storage connection without changing any settings.
| Parameter | Required | Description |
|---|---|---|
| host | Yes | Server IP or hostname |
| share | Yes | Share name |
| path | No | Subdirectory (default: bingebop/segments) |
| username | No | Login username |
| password | No | Login password |
| domain | No | Windows domain/workgroup |
{"success":true, "message":"Connected successfully"}
{"success":false, "message":"Connection timed out"}
List available filesystem roots (local storage, USB, Samba shares).
List files and directories at a given path.
Create an encrypted backup ZIP containing all settings, data sources, and credentials.
| Parameter | Required | Description |
|---|---|---|
| password | No | Custom encryption password (uses built-in default if omitted) |
{"ok":true, "path":"/data/.../bingebop-backup.zip", "bytes":524288, "tables":12, "encryption":"aes256"}
Decrypt and validate a backup file without applying it. Use this to check a backup before restoring.
| Parameter | Required | Description |
|---|---|---|
| path | No | Path to backup ZIP (uses last export if omitted) |
| password | No | Decryption password |
Apply a backup and restart the app. This is destructive — it replaces the entire database.
| Parameter | Required | Description |
|---|---|---|
| path | No | Path to backup ZIP |
| password | No | Decryption password |
BingeBop devices on the same network can be paired into a household cluster. Paired devices share settings, data sources, user profiles, favourites, and recordings automatically.
Returns the current cluster state: cluster ID/name, this device's UUID, list of paired peers, and discoverable clusters on the network.
Request to join a discovered cluster. The cluster owner must approve.
| Parameter | Required | Description |
|---|---|---|
| cluster_id | Yes | Cluster ID from /api/peers → available_clusters |
List pending join requests on this device.
Approve a pending join request.
| Parameter | Required | Description |
|---|---|---|
| device_uuid | Yes | UUID of the requesting device |
Send a remote-control key press. Injects real Android KeyEvents — the native focus system handles navigation exactly like a physical remote.
| Parameter | Required | Description |
|---|---|---|
| key | Yes | Key name (see below) |
| long_press | No | true for long press (default: false) |
| hold_ms | No | Hold duration in ms (for Compose hold-timers) |
| value | No | Text string (required when key=text) |
up, down, left, right, select, back, menu, enter, backspace, space,
channel_up, channel_down, play_pause, a–z, 0–9, text
# Navigate down and select
curl -H "X-Api-Token: ABCD" "http://tv:18080/api/input?key=down"
curl -H "X-Api-Token: ABCD" "http://tv:18080/api/input?key=select"
# Type text into a focused field
curl -H "X-Api-Token: ABCD" "http://tv:18080/api/input?key=text&value=hello+world"
# Long press on a channel row
curl -H "X-Api-Token: ABCD" "http://tv:18080/api/input?key=select&long_press=true"
Read-back of the currently-focused text field. Returns the field name and current value.
Sensitive fields (passwords) report active:true but withhold the value.
Navigate directly to a UI screen by route path.
| Parameter | Required | Description |
|---|---|---|
| path | Yes | Route path, e.g. settings, settings/content/library_sources |
| focus | No | Focus region: settings, custom, selector, textfield |
Set a text field's value by name (bypasses keyboard input).
| Parameter | Required | Description |
|---|---|---|
| name | Yes | Field name (registered by BopTextField) |
| value | No | Text value to set (empty to clear) |
http://<device-ip>:18080/remote in any phone browser for a virtual remote control
with D-pad, media controls, numpad, and text input. No installation required.
Read the diagnostic event log — errors, channel changes, codec issues, imports, cluster events. Data is PII-scrubbed.
| Parameter | Required | Description |
|---|---|---|
| severity | No | Minimum severity: INFO, WARN, ERROR |
| category | No | EPG, NETWORK, PLAYBACK, CODEC, SYSTEM, CLUSTER |
| limit | No | Max rows, 1–5000 (default: 500) |
| since | No | Only events after this timestamp (epoch ms) |
| coalesce | No | true to collapse repeated events with a count |
Run a full network-path diagnostic: device → router → internet → source → stream. Takes 10–30 seconds. Returns hop-by-hop results including bandwidth measurement and per-source probes. Use a generous HTTP timeout (≥ 120 s).
Use these keys with GET /api/setting?key=KEY&value=VALUE. Keys prefixed with local: are per-device
and stored under user 0. Unprefixed keys are per-user and sync across clustered devices.
| Key | Type | Values / Default | Description |
|---|---|---|---|
| local:scaling_method | int | 0=APP_SHADER, 1=APP_1080_TV, 2=TV_SCALING, 3=DEVICE | Video upscaling method |
| local:shader_algorithm | int | MEDIUM_BICUBIC | Shader upscaling quality |
| local:match_framerate | bool | true | Match display refresh rate to video |
| local:tunneled_playback | bool | false | Hardware A/V sync via tunneled playback |
| local:audio_output_channels | int | 0=AUTO, 1=PASSTHROUGH, 2=PCM_7.1, 3=PCM_5.1, 4=PCM_STEREO | Audio output mode |
| local:overlay_autohide_seconds | int | 5 (0=never) | Seconds before playback overlay auto-hides |
| local:display_mode_resolution_floor | int | 1080 | Minimum resolution during mode switches |
| local:display_mode_switch_delay | long | (ms) | Delay before switching down in resolution |
| Key | Type | Values / Default | Description |
|---|---|---|---|
| local:startup_destination | string | home, last_channel, guide, specific_channel | Where app lands on cold start |
| local:startup_channel_id | long | -1 (unset) | Channel ID when startup_destination = specific_channel |
| local:auto_start_on_boot | bool | false | Auto-launch on device boot |
| local:resume_last_channel_mode | string | local, synced | Which last-played timeline to use |
| Key | Type | Values / Default | Description |
|---|---|---|---|
| local:storage_type | string | local, samba | Segment storage backend |
| local:samba_host | string | Samba/NAS server IP or hostname | |
| local:samba_share | string | Samba share name | |
| local:samba_path | string | bingebop/segments | Subdirectory within share |
| local:samba_username | string | Samba login username | |
| local:samba_password | string | Samba login password | |
| local:live_pause_enabled | bool | true | Enable live-pause / timeshift |
| Key | Type | Values / Default | Description |
|---|---|---|---|
| subtitle_ocr_enabled | bool | true | Enable OCR for bitmap subtitles (DVB/PGS → text) |
| Key | Type | Values / Default | Description |
|---|---|---|---|
| local:clock_overlay_enabled | bool | true | Show clock overlay during playback |
| local:clock_overlay_size | string | small, normal, large, xlarge | Clock font size |
| local:clock_overlay_opacity | string | 100, 85, 70, 50 (%) | Clock transparency |
| local:clock_overlay_show_date | bool | false | Show date under the clock |
| local:clock_overlay_wifi | bool | false | Show Wi-Fi quality icon |
| Key | Type | Values / Default | Description |
|---|---|---|---|
| local:sleep_inactivity_timeout | string | off, 2, 3, 4, 6 (hours). Default: 4 | Hours of inactivity before "Still watching?" prompt |
All endpoints return JSON error responses with appropriate HTTP status codes:
| Status | Meaning | Example |
|---|---|---|
| 400 | Bad request — missing or invalid parameters | {"error":"Missing 'url' parameter", "usage":"..."} |
| 401 | Unauthorized — missing or wrong API token | {"error":"unauthorized", "hint":"..."} |
| 403 | Forbidden — endpoint needs the full token | {"error":"insufficient_token", "hint":"..."} |
| 404 | Not found — resource doesn't exist | {"error":"data_source 99 not found"} |
| 429 | Too many attempts — brute-force protection | {"error":"too_many_attempts", "retry_after":10} |
| 500 | Internal error | {"error":"..."} |
| 503 | Player not ready — retry in a moment | {"error":"Player not ready yet", "retry":true} |
usage field with the correct call format,
and a valid_values or hint field to help you self-correct.
Always check these before retrying.
"retry":true — the player is starting up. Wait 2 seconds and retry.retry_after — wait the specified seconds before trying again.POST /api/data_source, poll GET /api/data_sources every 5 seconds until refresh_status indicates completion. Typical import takes 10–60 seconds.GET /api/describe.