The goal of this page is a real outcome: a web page playing on one of your screens, put there entirely over HTTP. Five requests.
You need an API token and a screen already paired.
export API_TOKEN=your-token-here
export API=https://api.screenlyapp.com/api/v4.11. Prove the token works
curl -s -H "Authorization: Token $API_TOKEN" "$API/screens" | jq '.[].name'If you get a list of screen names, everything after this is detail. A 401 means the token is wrong; a 403 usually means the token belongs to an account without access to what you asked for.
2. Find the screen you want
Filters go in the query string, as field=operator.value, because the API is built on PostgREST.
curl -s -H "Authorization: Token $API_TOKEN" \
"$API/screens?name=eq.Reception&select=id,name,location"eq is one of several. like, in, gt, is and the rest all work, which is why there is no endpoint per question.
A screen’s status is not on the screen. Online and in-sync live on /v4.1/screens/statuses, keyed by screen_id. That separation is deliberate: the screen record is what you configured, the status record is what the device reported.
3. Add the content
curl -s -X POST -H "Authorization: Token $API_TOKEN" \
-H "Content-Type: application/json" \
-H "Prefer: return=representation" \
-d '{"title": "Ops dashboard", "source_url": "https://example.com/dashboard"}' \
"$API/assets"Prefer: return=representation makes the API hand back the object it created, including its id. Without it you get a 201 and nothing to work with, and then have to go looking for what you just made.
Screenly works out what the URL is from what it serves: a page becomes a web asset, an image or video is fetched and stored.
4. Put it in a playlist
curl -s -X POST -H "Authorization: Token $API_TOKEN" \
-H "Content-Type: application/json" \
-H "Prefer: return=representation" \
-d '{"playlist_id": "PLAYLIST_ID", "asset_id": "ASSET_ID", "duration": 30, "position": 0}' \
"$API/playlist-items"Note the hyphen in playlist-items. position is zero-based, so this puts it first.
5. Point the playlist at the screen
Assignment goes through labels, and every screen has one matching its own name, created when it was paired.
# the screen's own label
curl -s -H "Authorization: Token $API_TOKEN" "$API/labels?human_name=eq.Reception"
# attach the playlist to it
curl -s -X POST -H "Authorization: Token $API_TOKEN" \
-H "Content-Type: application/json" \
-d '{"label_id": "LABEL_ID", "playlist_id": "PLAYLIST_ID"}' \
"$API/labels/playlists"The screen picks it up on its next check-in, usually within a minute or two.
The one query worth learning
select embeds related records, which is the difference between one request and a hundred:
curl -s -H "Authorization: Token $API_TOKEN" \
"$API/playlists?select=title,playlist_items(duration,position,asset_id)"Ask for the nested data rather than looping over ids.
Where to go next
The full v4.1 schema has every endpoint, field, and filter.
Versions covers what is in v4.1 that is not in v4, and the v3 shutdown on 1 October 2026.