# Publish content to a TV programmatically

> Canonical HTML: https://screenrig.ai/guides/publish-content-to-tv-programmatically

To publish content to a TV from code, tell your AI agent what to show, or run a short script from your CI job. Either way the file is uploaded, the screen is pointed at it and you get proof that it is playing. This page starts with the conversation, then shows the script.

Updated October 27, 2026.

## Start with a sentence

A CI job draws a status poster after every run, from a few lines of Python. You want the latest one on the team area TV.

> **You:** Our CI job draws a status poster after every run. Put the latest one on the team area TV, and tell me when the TV actually has it.
>
> **Agent:** Build 4821 is up: PASSED, 221 of 221 tests. The TV confirmed it had the poster about two seconds after I sent it, and I took a picture of the screen to check.

![A dark poster reading Main branch, Build 4821, PASSED in green and 221 of 221 tests](https://screenrig.ai/static-resources/images/screenshots/landing/guides-programmatic-build-passed-1870e75a.webp)
*Build 4821 on the TV: PASSED, 221 of 221 tests.*

> **You:** Build 4822 just failed. Update the TV.
>
> **Agent:** Updated. The TV now shows FAILED in red, 219 of 221 tests.

![A dark poster reading Main branch, Build 4822, FAILED in red and 219 of 221 tests](https://screenrig.ai/static-resources/images/screenshots/landing/guides-programmatic-build-board-ad72846b.webp)
*Build 4822 after the update: FAILED in red, 219 of 221 tests.*

## The same thing from a script

A CI job doesn't chat. It runs one command that uploads the picture and writes the playlist, and a second that puts it on the screen and waits until the TV confirms:

```bash
screenrig playlist init build-4821.png --screen-id SCREEN --duration-ms 600000 --output board.json
screenrig screen publish SCREEN board.json
```

Under the CLI are six HTTP calls with a bearer token. Declare the upload, send the bytes, commit, create the playlist, point the screen at it, read the screen back. The [API reference](https://screenrig.ai/docs/api.md) lists each one, and the [CLI reference](https://screenrig.ai/docs/cli.md) lists the exit codes. A script that runs unattended signs in as a [service client](https://screenrig.ai/docs/service-clients.md).

## What a publish tells you

A publish waits up to two minutes for the TV, then reports how it ended:

| The answer | What it means | What to do |
| --- | --- | --- |
| Playing | The TV confirmed it has the playlist. | Nothing. |
| Assigned, screen offline | The TV was off or disconnected. It plays the playlist when it reconnects. | Run the same publish again to wait. It never makes a second playlist. |
| Assigned, a takeover is showing | A temporary override is on the screen, so the new playlist is the default and plays when the override ends. | Wait, or clear the takeover. |
| Assigned, the TV refused it | The TV could not switch, for example to a page with a login in its address. | Read the reason, fix it, then refresh the screen. |
| Waiting for review | The project needs a person to approve changes. Nothing plays until they do. | Wait for the approval. |
| Already published | The identical publish already ran, and this is the earlier answer. | Nothing. |

## Safe to retry, safe to share

- **Retries never double up.** Send the same publish twice and you get the same playlist, not a second one.
- **A stale update is refused.** Update with the revision you read. If another job changed the playlist first, yours is refused and told the current revision, so two jobs can't overwrite each other.
- **A picture of the screen is free.** So is a refresh or a note on one screen. One command that updates a whole group of screens counts as one request, however many screens it reaches.

> Your agent can build a slideshow in a minute. Keeping it playing on every screen, on every device, for years, is what screenRIG does.

screenRIG is free. Pay only if you want more. [Pricing](https://screenrig.ai/pricing.md) lists every allowance, and [Players](https://screenrig.ai/docs/players.md) covers installing a Player on a given TV.

**Next:** every call, field and error is in the [API reference](https://screenrig.ai/docs/api.md).

## Watch: How your agent knows it’s playing

[How your agent knows it’s playing, 1:17](https://screenrig.ai/videos/verified-playback.md): Verified playback in 77 seconds: your agent publishes, checks the screen itself with a screenshot, catches a problem and fixes it.

## Related

- [Digital Signage REST API Reference](https://screenrig.ai/docs/api.md): screenRIG is free. Pay only if you want more. REST API for screens, playlists, media, apps and webhooks, generated from OpenAPI.
- [Digital Signage CLI Command Reference](https://screenrig.ai/docs/cli.md): screenRIG is free. Pay only if you want more. The CLI publishes media, playlists and apps to TVs and kiosks from a terminal or an agent. JSON output.
- [Service Clients for Servers and CI](https://screenrig.ai/docs/service-clients.md): Give a server, script or CI job its own screenRIG access: a service client signs in with a private key or secret and calls the API with 15-minute tokens.
- [Digital Signage for Developers (API, CLI, SDK)](https://screenrig.ai/developers.md)
- [Control TV Screens with an AI Agent](https://screenrig.ai/control-tv-screens-with-ai-agent.md): Ask your AI agent for a TV welcome board: preview, publish, check, change one guest. screenRIG is free. Pay only if you want more.

[Start free](https://screenrig.ai/docs/start.md). screenRIG is free. Pay only if you want more.
