API Reference

Anthias API v2.0.0. Manage assets, device settings, backups, and integrations over HTTP.

Overview

Anthias exposes a REST API so you can manage a player without touching the web interface: script asset uploads, rotate playlists, trigger backups, or wire the device into your own tooling. Everything the dashboard does is available over HTTP, which makes Anthias straightforward to automate across a fleet of screens.

The API runs directly on each device, so the base URL is simply the player’s own address on your network, under /api/:

http://<device-ip>/api/

That is port 80 on a normal install; a development environment serves the same API on port 8000. If you have enabled SSL on the device, use https:// with the hostname on the certificate instead. Requests and responses are JSON, except for asset uploads, which use multipart/form-data.

Versioning

The API is versioned in the path, and several versions are served side by side so existing integrations keep working as new ones are added:

Pin your integration to a specific version so a future release cannot change the shape of the responses you depend on.

Authentication

The API is designed for use on a trusted local network and does not require an API token. Because there is no authentication layer in front of it, do not expose a device’s HTTP port directly to the public internet. Keep it behind your LAN, a VPN, or a reverse proxy that adds its own access control.

Responses and errors

Successful requests return a 2xx status with a JSON body. Client mistakes (a missing field, a malformed asset) return 4xx with a JSON error describing what went wrong; unexpected server-side failures return 5xx. Each endpoint below lists the response codes it can return and the schema of the body that comes with them. Expand a response to see the full field list.

Endpoints

The complete endpoint reference follows, grouped by tag. Each entry shows the method, path, parameters, request body, and every response it can return.

assets

get /api/v2/assets

Responses

200

Array of:

AssetSerializerV2

FieldTypeNotes
asset_id*stringread-only
custom_headers*objectread-only
durationinteger (int64) | null
end_datestring (date-time) | null
is_active*booleanread-only
is_enabledboolean
is_processingboolean
is_reachable*booleanread-only
last_reachability_check*string (date-time) | nullread-only
metadata*objectread-only
mimetypestring | null
namestring | null
nocacheboolean
play_days*integer[]read-only
play_orderinteger (int64)
play_time_fromstring (time) | null
play_time_tostring (time) | null
refresh_interval_s*integerread-only
skip_asset_checkboolean
skip_ssl_verifyboolean
start_datestring (date-time) | null
uristring | null
post /api/v2/assets

Request body application/json

Schema: CreateAssetSerializerV2

FieldTypeNotes
asset_id*stringread-only
custom_headersobjectwrite-only
duration*integer
end_date*string (date-time)
extstringwrite-only
is_enabled*boolean
is_processingboolean
mimetype*string
name*string
nocacheboolean
play_daysinteger[]
play_orderinteger
play_time_fromstring (time) | null
play_time_tostring (time) | null
refresh_interval_sintegerwrite-only
skip_asset_checkboolean
skip_ssl_verifyboolean
start_date*string (date-time)
uri*string

Responses

201

Schema: AssetSerializerV2

FieldTypeNotes
asset_id*stringread-only
custom_headers*objectread-only
durationinteger (int64) | null
end_datestring (date-time) | null
is_active*booleanread-only
is_enabledboolean
is_processingboolean
is_reachable*booleanread-only
last_reachability_check*string (date-time) | nullread-only
metadata*objectread-only
mimetypestring | null
namestring | null
nocacheboolean
play_days*integer[]read-only
play_orderinteger (int64)
play_time_fromstring (time) | null
play_time_tostring (time) | null
refresh_interval_s*integerread-only
skip_asset_checkboolean
skip_ssl_verifyboolean
start_datestring (date-time) | null
uristring | null
get /api/v2/assets/control/{command}

Use any of the following commands to control asset playback: * `next` - Show the next asset * `previous` - Show the previous asset * `asset&{asset_id}` - Show the asset with the specified `asset_id`

Parameters

NameInTypeRequired
commandpathstringyes

Responses

200

string

post /api/v2/assets/order

Request body application/json

Schema: PlaylistOrderSerializerMixin

FieldTypeNotes
ids*stringComma-separated list of asset IDs in the order they should be played. For example: `793406aa1fd34b85aa82614004c0e63a,1c5cfa719d1f4a9abae16c983a18903b,9c41068f3b7e452baf4dc3f9b7906595`write-only

Responses

204 No response body
get /api/v2/assets/{asset_id}

Parameters

NameInTypeRequired
asset_idpathstringyes

Responses

200

Schema: AssetSerializerV2

FieldTypeNotes
asset_id*stringread-only
custom_headers*objectread-only
durationinteger (int64) | null
end_datestring (date-time) | null
is_active*booleanread-only
is_enabledboolean
is_processingboolean
is_reachable*booleanread-only
last_reachability_check*string (date-time) | nullread-only
metadata*objectread-only
mimetypestring | null
namestring | null
nocacheboolean
play_days*integer[]read-only
play_orderinteger (int64)
play_time_fromstring (time) | null
play_time_tostring (time) | null
refresh_interval_s*integerread-only
skip_asset_checkboolean
skip_ssl_verifyboolean
start_datestring (date-time) | null
uristring | null
put /api/v2/assets/{asset_id}

Parameters

NameInTypeRequired
asset_idpathstringyes

Request body application/json

Schema: UpdateAssetSerializerV2

FieldTypeNotes
custom_headersobject
duration*integer
end_date*string (date-time)
is_enabled*boolean
is_processingboolean
name*string
nocacheboolean
play_daysinteger[]
play_orderinteger
play_time_fromstring (time) | null
play_time_tostring (time) | null
refresh_interval_sinteger
skip_asset_checkboolean
skip_ssl_verifyboolean
start_date*string (date-time)

Responses

200

Schema: AssetSerializerV2

FieldTypeNotes
asset_id*stringread-only
custom_headers*objectread-only
durationinteger (int64) | null
end_datestring (date-time) | null
is_active*booleanread-only
is_enabledboolean
is_processingboolean
is_reachable*booleanread-only
last_reachability_check*string (date-time) | nullread-only
metadata*objectread-only
mimetypestring | null
namestring | null
nocacheboolean
play_days*integer[]read-only
play_orderinteger (int64)
play_time_fromstring (time) | null
play_time_tostring (time) | null
refresh_interval_s*integerread-only
skip_asset_checkboolean
skip_ssl_verifyboolean
start_datestring (date-time) | null
uristring | null
patch /api/v2/assets/{asset_id}

Parameters

NameInTypeRequired
asset_idpathstringyes

Request body application/json

Schema: PatchedUpdateAssetSerializerV2

FieldTypeNotes
custom_headersobject
durationinteger
end_datestring (date-time)
is_enabledboolean
is_processingboolean
namestring
nocacheboolean
play_daysinteger[]
play_orderinteger
play_time_fromstring (time) | null
play_time_tostring (time) | null
refresh_interval_sinteger
skip_asset_checkboolean
skip_ssl_verifyboolean
start_datestring (date-time)

Responses

200

Schema: AssetSerializerV2

FieldTypeNotes
asset_id*stringread-only
custom_headers*objectread-only
durationinteger (int64) | null
end_datestring (date-time) | null
is_active*booleanread-only
is_enabledboolean
is_processingboolean
is_reachable*booleanread-only
last_reachability_check*string (date-time) | nullread-only
metadata*objectread-only
mimetypestring | null
namestring | null
nocacheboolean
play_days*integer[]read-only
play_orderinteger (int64)
play_time_fromstring (time) | null
play_time_tostring (time) | null
refresh_interval_s*integerread-only
skip_asset_checkboolean
skip_ssl_verifyboolean
start_datestring (date-time) | null
uristring | null
delete /api/v2/assets/{asset_id}

Parameters

NameInTypeRequired
asset_idpathstringyes

Responses

204 No response body
get /api/v2/assets/{asset_id}/content

The content of the asset. `type` can either be `file` or `url`. In case of a file, the fields `mimetype`, `filename`, and `content` will be present. In case of a URL, the field `url` will be present.

Parameters

NameInTypeRequired
asset_idpathstringyes

Responses

200
FieldTypeNotes
contentstring
filenamestring
mimetypestring
typestring
urlstring
post /api/v2/assets/{asset_id}/recheck

On-demand reachability recheck, called from the viewer. The viewer cannot attach operator BasicAuth credentials, so this endpoint uses a lightweight internal token derived from the shared ``anthias.conf`` secret instead. The request still remains side-effect-only and rate-limited: it returns no asset data, queue churn is debounced here, and the Celery task enforces the longer per-asset probe cooldown.

Parameters

NameInTypeRequired
asset_idpathstringyes

Responses

202 No response body
403 No response body
404 No response body

backup

post /api/v2/backup

Create a backup of the current Anthias instance, which includes the following: * current settings * image and video assets * asset metadata (e.g. name, duration, play order, status), which is stored in a SQLite database

Responses

201

string

device settings

get /api/v2/device_settings

Responses

200

Schema: DeviceSettingsSerializerV2

FieldTypeNotes
audio_output*string
auth_backend*string
date_format*string
debug_logging*boolean
default_assets*boolean
default_duration*integer
default_streaming_duration*integer
display_power_days*string
display_power_off_time*string
display_power_on_time*string
display_power_schedule_enabled*boolean
player_name*string
prefer_dark_mode*boolean
screen_rotation*ScreenRotationEnum
show_splash*boolean
shuffle_playlist*boolean
timezone*string
use_24_hour_clock*boolean
username*string
verify_ssl*boolean
patch /api/v2/device_settings

Request body application/json

Schema: PatchedUpdateDeviceSettingsSerializerV2

FieldTypeNotes
audio_outputstring
auth_backendany
current_passwordstring
date_formatstring
debug_loggingboolean
default_assetsboolean
default_durationinteger
default_streaming_durationinteger
display_power_daysstring
display_power_off_timestring
display_power_on_timestring
display_power_schedule_enabledboolean
passwordstring
password_2string
player_namestring
prefer_dark_modeboolean
screen_rotationScreenRotationEnum
show_splashboolean
shuffle_playlistboolean
timezonestring
use_24_hour_clockboolean
usernamestring
verify_sslboolean

Responses

200
FieldTypeNotes
messagestring
400
FieldTypeNotes
errorstring

display

post /api/v2/display/{state}

Parameters

NameInTypeRequired
statepathstringyes

Request body application/json

Schema: DisplayPowerViewSerializerMixin

FieldTypeNotes
message*stringread-only

Responses

200

Schema: DisplayPowerViewSerializerMixin

FieldTypeNotes
message*stringread-only
400

Schema: DisplayPowerViewSerializerMixin

FieldTypeNotes
message*stringread-only
502

Schema: DisplayPowerViewSerializerMixin

FieldTypeNotes
message*stringread-only
503

Schema: DisplayPowerViewSerializerMixin

FieldTypeNotes
message*stringread-only

file asset

post /api/v2/file_asset

Parameters

NameInTypeRequired
X-Upload-Idheaderstringno

Request body multipart/form-data

FieldTypeNotes
file_uploadstring (binary)

Responses

200
FieldTypeNotes
extstring
upload_idstring
uristring

info

get /api/v2/info

Responses

200
FieldTypeNotes
anthias_versionstring
device_modelstring
display_powerstring | null
free_spacestring
host_userstring
ip_addressesstring[]
loadavgnumber
mac_addressstring
memoryobject
storageobjectHealth of the filesystem this device runs from, assembled from ext4 superblock error counters, a periodic write-and-read-back check, and eMMC wear registers where present. Branch on `status`. Check `supported` first: when it is false the filesystem could not be resolved and no other field carries information. `errors_count` is cumulative over the life of the filesystem and survives reboots; `errors_new` and the write-check fields reset on reboot.
timeobject
under_voltageobjectPower-supply health from the kernel rpi_volt sensor. Check `supported` first: when it is false this device has no such sensor and the other fields carry no information. Counters and timestamps reset when the device reboots.
up_to_dateboolean
uptimeobject
viewlogstring

integrations

get /api/v2/integrations

Responses

200

Schema: IntegrationsSerializerV2

FieldTypeNotes
balena_app_idstring | null
balena_app_namestring | null
balena_device_idstring | null
balena_device_name_at_initstring | null
balena_host_os_versionstring | null
balena_supervisor_versionstring | null
is_balena*boolean
post /api/v2/integrations/import/{provider}/item

Import a single remote media item as an Anthias asset. Per-item (not batch) for the same reason as ``ScreenlyMigrateAssetViewV2``: the wizard shows live progress and keeps going past individual failures. Known per-item failures return 200 with ``success: False`` so the queue keeps advancing; only a transport failure is a 502.

Parameters

NameInTypeRequired
providerpathstringyes

Request body application/json

Schema: ImportItemSerializerV2

FieldTypeNotes
enableboolean
remote_id*string
token*stringwrite-only

Responses

200
FieldTypeNotes
asset_idstring | null
errorstring | null
reasonstring | null
skippedboolean
successboolean
post /api/v2/integrations/import/{provider}/validate

Validate an import provider's token and enumerate its media. Inbound counterpart to ``ScreenlyValidateTokenViewV2``: validation and listing happen in one round-trip so the wizard's Continue button goes straight from the token field to the item picker. The token is not stored; each request forwards it inline. ``provider`` is the registry key from the URL (``yodeck``, later ``screencloud`` …).

Parameters

NameInTypeRequired
providerpathstringyes

Request body application/json

Schema: ImportValidateSerializerV2

FieldTypeNotes
token*stringwrite-only

Responses

200
FieldTypeNotes
errorstring | null
itemsobject[]
validboolean
post /api/v2/integrations/screenly/migrate

Forward a single Anthias asset to the configured Screenly account. Per-asset rather than batch on purpose: the UI shows live progress and continues past individual failures, which matches the way operators run this (large libraries, some assets reachable, some not). Batching would either swallow partial failures or hand-roll the same loop server-side with worse feedback.

Request body application/json

Schema: ScreenlyMigrateAssetSerializerV2

FieldTypeNotes
asset_group_idstring
asset_id*string
token*stringwrite-only

Responses

200
FieldTypeNotes
errorstring | null
screenly_asset_idstring | null
successboolean
post /api/v2/integrations/screenly/validate

Probe a Screenly v4.1 API token and reserve the migration group. Two steps in one round-trip because the wizard's UX is "click Continue → either an error or the asset picker". Validating the token alone would leave a follow-up call between Continue and the next screen, and the asset-group creation is cheap (idempotent get-or-create against ``/asset-groups``). The token is not stored; each request forwards it inline.

Request body application/json

Schema: ScreenlyTokenSerializerV2

FieldTypeNotes
token*stringwrite-only

Responses

200
FieldTypeNotes
asset_group_idstring | null
asset_group_titlestring | null
errorstring | null
validboolean

network

get /api/v2/network/ip-addresses

Lightweight IP-list endpoint for the splash page to poll. Unauth'd because the splash page itself is unauth'd and the viewer isn't a credentialed client. The data here is already disclosed by /splash-page rendering — there's no new exposure. Narrow on purpose: only IPs, no diagnostics. /api/v2/info covers the "everything about the device" case but is auth'd and does heavier work (psutil, statvfs, version checks) that would compound on a 2-second poll. Don't bolt onto this; add a sibling endpoint if a different unauth'd value is ever needed. **KNOWN LIMITATION (deferred to broader auth work).** This GET has a side effect — ``_resolve_node_ip`` calls ``_publish_refresh()`` on cache miss / hit / empty-list, which publishes ``hostcmd: set_ip_addresses`` to host_agent. ``host_agent.set_ip_addresses`` in turn does an internet probe (``requests.get`` to 1.1.1.1 with a 10×1s tenacity retry). An unauthenticated LAN client can drive that side effect at the debounce-bounded rate (one publish per ``_IP_REFRESH_DEBOUNCE_S``). The mitigations already in place keep blast radius bounded: * SETNX-debounced publishes (only one refresh per 12s window regardless of poll volume), * the response body carries no data not already disclosed by the splash page itself, * host_agent's own retry/throttle behavior caps the downstream cost. The proper fix is a shared internal-auth gate (matching the one on AssetRecheckViewV2) — but the splash polling endpoint is consumed by the viewer's webview from the device's local network with no way to attach BasicAuth, so internal-auth here needs to be designed alongside the broader auth rework. Tracked in the same followup as AssetRecheckViewV2's gating.

Responses

200
FieldTypeNotes
ip_addressesstring[]

reboot

post /api/v2/reboot

Responses

200 No response body

recover

post /api/v2/recover

Recover data from a backup file. The backup file must be a `.tar.gz` file.

Request body multipart/form-data

FieldTypeNotes
backup_uploadstring (binary)

Responses

200

string

shutdown

post /api/v2/shutdown

Responses

200 No response body

viewer

get /api/v2/viewer/playlist

Active assets + next deadline, evaluated against server time. Intended for the C++ viewer (GH #2906 Phase 3) so the viewer no longer needs Django ORM access or its own ``Asset.is_active()`` re-implementation. The Python viewer keeps using ``anthias_viewer.scheduling.generate_asset_list()`` directly until Phase 3 swaps it. Internal-auth gated for the same reason as ``AssetRecheckViewV2``: the viewer can't attach operator BasicAuth, so it presents the shared token derived from ``anthias.conf``.

Responses

200

Schema: ViewerPlaylistSerializerV2

FieldTypeNotes
assets*AssetSerializerV2[]
deadline*string (date-time) | null
now*string (date-time)
403 No response body
get /api/v2/viewer/settings

Viewer-relevant settings subset for the C++ viewer. Narrower than ``DeviceSettingsViewV2`` on purpose: only the keys the viewer reads at runtime are exposed, so the internal-auth path doesn't surface operator credential fields. Internal-auth gated like ``ViewerPlaylistViewV2`` above.

Responses

200

Schema: ViewerSettingsSerializerV2

FieldTypeNotes
audio_output*string
debug_logging*boolean
screen_rotation*ScreenRotationEnum
show_splash*boolean
shuffle_playlist*boolean
403 No response body