Skip to main content
The management API is mounted at /api/v1/ (or /<path>/api/v1/ if a URL path prefix is configured). All endpoints except the public playlist resource endpoint require a valid admin JWT bearer token.
Authorization: Bearer <jwt-token>
Admin endpoints are protected by the validator_admin middleware. If web_auth_enabled is false in your tuliprox setup, the middleware is bypassed and no token is required.

System

Server status

GET /api/v1/status
Returns a JSON object describing the current server state.
curl -H "Authorization: Bearer $TOKEN" http://localhost:8901/api/v1/status

Active streams

GET /api/v1/streams
Returns the list of currently active streams.
curl -H "Authorization: Bearer $TOKEN" http://localhost:8901/api/v1/streams

GeoIP database update

GET /api/v1/geoip/update
Triggers an update of the GeoIP database used for connection geo-filtering. Returns 200 OK on success, 400 Bad Request if GeoIP is disabled or the download failed.
curl -H "Authorization: Bearer $TOKEN" http://localhost:8901/api/v1/geoip/update

IP info

GET /api/v1/ipinfo
Returns the server’s detected public IPv4 and IPv6 addresses. Requires ipcheck to be configured in config.yml.
curl -H "Authorization: Bearer $TOKEN" http://localhost:8901/api/v1/ipinfo

Configuration

Get full configuration

GET /api/v1/config
Returns the current config.yml, source.yml, and api-proxy.yml contents merged into a single JSON object. Response headers include revision hashes for each file:
HeaderDescription
x-config-main-revisionBLAKE3 hash of config.yml
x-config-sources-revisionBLAKE3 hash of source.yml
x-config-api-proxy-revisionBLAKE3 hash of api-proxy.yml
curl -H "Authorization: Bearer $TOKEN" http://localhost:8901/api/v1/config

Save main config

POST /api/v1/config/main
Saves a new config.yml. Requires the If-Match header to contain the current revision hash from x-config-main-revision. Request body: JSON ConfigDto object. Headers:
HeaderDescription
Content-Typeapplication/json
If-MatchCurrent x-config-main-revision value
Responses:
StatusMeaning
200 OKSaved successfully. New revision in x-config-main-revision response header.
400 Bad RequestValidation failed.
409 ConflictConfig changed on server since you last fetched it. Reload and retry.
428 Precondition RequiredIf-Match header missing.
Always fetch the config first, record the revision header, then send that revision in If-Match when saving. This prevents overwriting concurrent changes.

Save sources config

POST /api/v1/config/sources
Saves a new source.yml. Same If-Match / x-config-sources-revision revision-check protocol as config/main. Request body: JSON SourcesConfigDto object.

Get API proxy config

GET /api/v1/config/apiproxy
Returns the current api-proxy.yml content (excluding the user list). Response includes the x-config-api-proxy-revision header.
curl -H "Authorization: Bearer $TOKEN" http://localhost:8901/api/v1/config/apiproxy

Save API proxy config

PUT /api/v1/config/apiproxy
Saves updated server and global settings from api-proxy.yml. Uses the same If-Match / x-config-api-proxy-revision revision-check protocol. Request body: JSON ApiProxyConfigDto object (without the user list — use the user endpoints below to manage users).

Get batch content for an input

GET /api/v1/config/batchContent/{input_id}
Downloads the raw batch CSV file for a given input. Returns text/csv.
input_id
number
required
The numeric input ID.

Test Xtream provider login

POST /api/v1/config/xtream/login-info
Attempts to log in to an Xtream Codes provider and returns the login response. Useful for verifying provider credentials before saving them in source.yml. Request body:
{
  "url": "http://provider.example.com",
  "username": "provideruser",
  "password": "providerpass"
}

File downloads

Queue a file download

POST /api/v1/file/download
Queues a background file download task.

Get download status

GET /api/v1/file/download/info
Returns the status of any queued or in-progress file downloads.

Playlist management

Trigger playlist update

POST /api/v1/playlist/update
Triggers a manual playlist refresh. Deduplicates rapid calls — if an update is already pending, the response is still 202 Accepted but no duplicate run is queued. Request body: JSON array of target name strings. Send an empty array [] to update all targets.
curl -X POST http://localhost:8901/api/v1/playlist/update \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '["my_target"]'
StatusMeaning
202 AcceptedUpdate queued or already pending.
400 Bad RequestInvalid target name(s).
503 Service UnavailableServer is shutting down.

Get live channels

POST /api/v1/playlist/live
Returns the live channel playlist for the specified source. Used by the web UI playlist browser. Request body: A PlaylistRequest object:
{ "Target": 1 }
or for an input:
{ "Input": 2 }
or for a custom Xtream provider:
{
  "CustomXtream": {
    "url": "http://provider.example.com",
    "username": "user",
    "password": "pass"
  }
}
or for a custom M3U URL:
{ "CustomM3u": { "url": "http://example.com/playlist.m3u" } }

Get VOD

POST /api/v1/playlist/vod
Same request body as /playlist/live. Returns VOD items.

Get series

POST /api/v1/playlist/series
Same request body as /playlist/live. Returns series items.

Get series info

POST /api/v1/playlist/series_info/{virtual_id}/{provider_id}
Returns detailed info for a series item.
virtual_id
string
required
The virtual stream ID of the series.
provider_id
string
required
The provider stream ID.
Request body: A PlaylistRequest with Target variant.

Get series episode item

POST /api/v1/playlist/series/episode/{virtual_id}
Returns a single series episode item.
virtual_id
string
required
The virtual stream ID of the episode.
Request body: A PlaylistRequest with Target variant.

Get EPG for playlist

POST /api/v1/playlist/epg
Returns the EPG data for a target or custom source. Used by the web UI EPG viewer. Request body: A PlaylistEpgRequest object:
{ "Target": 1 }
or for a custom URL:
{ "Custom": "http://example.com/epg.xml" }

Get web player URL

POST /api/v1/playlist/webplayer
Generates a short-lived stream URL for the built-in web player. Request body:
{
  "target_id": 1,
  "cluster": "live",
  "virtual_id": 12345
}
Returns a plain-text URL string using a JWT access token valid for 30 seconds.

Public: playlist resource proxy

GET /api/v1/playlist/resource/{resource}
Proxy for obfuscated resource URLs (e.g., cover images) embedded in web UI playlist responses. This endpoint is public — no authentication required.
resource
string
required
Obfuscated resource identifier generated internally by tuliprox.

Library management

These endpoints are available only when library.enabled: true in config.yml.

Trigger library scan

POST /api/v1/library/scan
Starts a background scan of the configured library directories. Returns 202 Accepted immediately; the scan runs asynchronously. If a scan is already in progress, returns 400 Bad Request. Request body:
{ "force_rescan": false }
force_rescan
boolean
When true, forces a full re-scan of all library directories even if files have not changed.
StatusMeaning
202 AcceptedScan started.
400 Bad RequestLibrary not enabled or scan already in progress.
curl -X POST http://localhost:8901/api/v1/library/scan \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"force_rescan": false}'

Get library status

GET /api/v1/library/status
Returns the current status of the local media library, including item counts.
curl -H "Authorization: Bearer $TOKEN" http://localhost:8901/api/v1/library/status

User management

These endpoints manage proxy users in api-proxy.yml (or the user database when use_user_db: true).

Create a user

POST /api/v1/user/{target}
Creates a new user credential under the specified target.
target
string
required
The target name (as defined in source.yml) to associate the user with.
Request body: JSON ProxyUserCredentialsDto object:
{
  "username": "newuser",
  "password": "newpass",
  "token": "optional-token",
  "proxy": "reverse",
  "server": "default",
  "max_connections": 2,
  "status": "Active",
  "exp_date": null
}
StatusMeaning
200 OKUser created.
400 Bad RequestDuplicate username, duplicate token, or validation error.

Update a user

PUT /api/v1/user/{target}
Updates an existing user credential. The username in the request body identifies the user to update. If the target path parameter differs from the user’s current target, the user is moved to the new target. Request body: Same ProxyUserCredentialsDto structure as create.
StatusMeaning
200 OKUser updated.
400 Bad RequestUser not found, duplicate token, or validation error.

Delete a user

DELETE /api/v1/user/{target}/{username}
Deletes a user credential.
target
string
required
The target the user belongs to.
username
string
required
The username to delete.
curl -X DELETE \
  -H "Authorization: Bearer $TOKEN" \
  http://localhost:8901/api/v1/user/my_target/alice
StatusMeaning
200 OKUser deleted.
400 Bad RequestUser not found in the specified target.

User self-service API

These endpoints are for authenticated end-users (not admins). They use a user JWT bearer token rather than the admin token, and are enabled only when user_ui_enabled is true in config.yml.

Get playlist categories

GET /api/v1/user/playlist/categories
Returns the category groups available to the authenticated user, split by output type.

Get user bouquet

GET /api/v1/user/playlist/bouquet
Returns the user’s saved channel bouquet (favourite/selected channels) for both Xtream and M3U output types.

Save user bouquet

POST /api/v1/user/playlist/bouquet
Saves the user’s channel bouquet. Request body: JSON PlaylistBouquetDto object.

Build docs developers (and LLMs) love