Nebular Overlay Server API
The Overlay API lets an organization catalogue its templates, configure persistent overlay profiles and control a running overlay from Studio, an automation system or another authorized production tool.
An overlay profile is the saved configuration associated with a stream session ID. It contains the selected template, its current values, render resolution and maximum sampling rate. The profile remains available between ingestions.
Profiles have two states:
IDLEmeans the configuration is saved but no renderer currently owns it.RUNNINGmeans an active ingestion has claimed the profile and started its renderer on the worker identified byfqdn.
Starting a renderer is normally part of the hosting platform's ingestion lifecycle; it is not an organization-facing API operation. Configure the profile before publishing the stream. When ingestion starts, the platform restores that profile automatically.
Authentication and endpoints
Every organization-facing request requires an organization-scoped token:
x-ns-token: <token>
The verified token determines the organization. When an endpoint contains :sessionId, that session must belong to the authenticated organization.
Some deployments additionally protect the API with HTTP Basic authentication to further prevent server abuse or snooping by unauthorized parties. These credentials, if needed, will be provided by your platform operator. The examples include that optional layer:
Authorization: Basic <credentials>
There are two kinds of external endpoint:
- Global endpoint is the main endpoint provided by your platform operator, like
https://live.nebular.tv. API calls to this endpoint provide the organization catalogue and persistent profile registry. - Worker endpoints are specific endpoints returned after starting or listing running sessions in the field
fqdn. API calls to these endpoints interact with a running renderer and allows you to send real-time control commands.
The owning worker may change between ingestions. Retrieve the profile again instead of permanently caching its fqdn.
All request and response bodies use JSON. Send:
Content-Type: application/json
API summary
| Method | Path | Endpoint | Description |
|---|---|---|---|
GET |
/api/overlays/template |
Global | Lists templates belonging to the authenticated organization. |
GET |
/api/overlays/template/:templateId/meta |
Global | Returns the manifest metadata and instructions for one template. |
GET |
/api/overlays/overlay |
Global | Lists the organization's IDLE and RUNNING profiles. |
GET |
/api/overlays/overlay/:sessionId |
Global | Returns one persistent profile. |
GET |
/api/overlays/overlay/:sessionId/template-values?template=:templateId |
Global | Returns the values last used by a template in that profile. |
PUT |
/api/overlays/overlay/:sessionId |
Global | Creates or replaces the configuration of an IDLE profile. |
DELETE |
/api/overlays/overlay/:sessionId?force=1 |
Global | Releases a stale registry owner while preserving the profile. |
GET |
/api/overlays/overlay-local/:sessionId |
Worker | Returns detailed state for a renderer on that worker. |
PUT |
/api/overlays/overlay-local/:sessionId/template |
Worker | Switches the running renderer to another template and complete value set. |
PATCH |
/api/overlays/overlay-local/:sessionId/template |
Worker | Applies an incremental value update to the expected active template. |
PATCH |
/api/overlays/overlay-local/:sessionId/output |
Worker | Fades the rendered overlay in or out. |
DELETE |
/api/overlays/overlay-local/:sessionId |
Worker | Stops the renderer and returns its profile to IDLE. |
The server also has private lifecycle and rendering endpoints. They are reserved for trusted host-platform components and are intentionally omitted from this organization manual.
Template catalogue
List available templates
curl 'https://live.nebular.tv/api/overlays/template' \
--header 'Authorization: Basic <credentials>' \
--header 'x-ns-token: <token>'
Example response:
{
"templates": [
"broadcast/lower-third",
"broadcast/weather",
"gambling/bingo"
],
"deployment": {
"commitHash": "0123456789abcdef0123456789abcdef01234567",
"updatedAt": "2026-09-03T10:15:00Z"
}
}
Template IDs are organization-scoped slash-separated names. Use the returned ID exactly in profile and runtime requests.
deployment identifies the Git revision currently installed for the organization and the UTC time at which it was installed or updated. It is null for templates installed without deployment metadata.
Read a template manifest
curl 'https://live.nebular.tv/api/overlays/template/gambling/bingo/meta' \
--header 'Authorization: Basic <credentials>' \
--header 'x-ns-token: <token>'
Example response:
{
"template": "gambling/bingo",
"meta": {
"game/called": {
"type": "multi",
"label": "Called numbers",
"choose": [1, 2, 3, 4, 5]
}
},
"instructions": "Select each number as it is called, then press Update."
}
meta describes the accepted parameter paths and value shapes. Slash-separated definitions such as game/called correspond to nested JSON:
{
"game": {
"called": [3, 8]
}
}
See the template manual for the complete manifest and parameter-type reference.
Persistent profiles
Create or update an idle profile
curl --request PUT \
'https://live.nebular.tv/api/overlays/overlay/XQA0t-s3Zzx' \
--header 'Authorization: Basic <credentials>' \
--header 'x-ns-token: <token>' \
--header 'Content-Type: application/json' \
--data '{
"template": "gambling/bingo",
"width": 1920,
"height": 1080,
"everyNthFrame": 2,
"values": {
"content": {"title": "Friday Night Bingo"},
"game": {"called": []}
}
}'
The session ID belongs in the URL and must not also be supplied in the body.
| Field | Required | Meaning |
|---|---|---|
template |
Yes | Template ID from the organization catalogue. |
width |
No | Positive integer render width. The service default is normally 1920. |
height |
No | Positive integer render height. The service default is normally 1080. |
everyNthFrame |
No | Positive sampling interval relative to a nominal 60-frame render cycle. It limits maximum sampling and does not establish a fixed frame rate. |
values |
No | Complete initial template-value object. An omitted or null value becomes an empty object. |
Common sampling values are:
everyNthFrame |
Maximum sampling |
|---|---|
1 |
60 fps |
2 |
30 fps |
3 |
20 fps |
4 |
15 fps |
5 |
12 fps |
6 |
10 fps |
10 |
6 fps |
30 |
2 fps |
60 |
1 fps |
Actual capture may be lower because overlay capture is change-driven.
This endpoint creates a new profile or replaces an existing profile only while it is IDLE. A RUNNING profile must be changed through its owning worker.
List profiles
curl 'https://live.nebular.tv/api/overlays/overlay' \
--header 'Authorization: Basic <credentials>' \
--header 'x-ns-token: <token>'
The collection response contains compact summaries suitable for discovery and routing:
{
"overlays": [
{
"sessionId": "XQA0t-s3Zzx",
"status": "RUNNING",
"fqdn": "live-04.nebular.tv",
"template": "gambling/bingo"
}
]
}
Use the single-profile endpoint when complete persistent values and render settings are required.
Read one profile
curl 'https://live.nebular.tv/api/overlays/overlay/XQA0t-s3Zzx' \
--header 'Authorization: Basic <credentials>' \
--header 'x-ns-token: <token>'
Representative response:
{
"sessionId": "XQA0t-s3Zzx",
"status": "RUNNING",
"fqdn": "live-04.nebular.tv",
"template": "gambling/bingo",
"values": {"game": {"called": [3, 8]}},
"width": 1920,
"height": 1080,
"everyNthFrame": 2
}
Important fields are:
statusidentifies whether an active renderer owns the profile.fqdnisnullwhile idle and names the owning worker while running.templateandvaluesare the persistent state restored on the next ingestion.width,heightandeveryNthFrameare the persistent render settings.
If a requested profile does not exist, the API returns:
{
"running": false,
"sessionId": "XQA0t-s3Zzx"
}
Read values previously used by a template
An overlay profile remembers the values last used by each template. This allows an operator or production tool to switch away from a template and later restore its previous state—even after the client application has been reloaded.
Request the saved values from the global endpoint before constructing a template-switch request:
curl --get \
'https://live.nebular.tv/api/overlays/overlay/XQA0t-s3Zzx/template-values' \
--header 'Authorization: Basic <credentials>' \
--header 'x-ns-token: <token>' \
--data-urlencode 'template=gambling/roulette'
Example response for a template used previously by this profile:
{
"sessionId": "XQA0t-s3Zzx",
"template": "gambling/roulette",
"values": {
"content": {
"title": "Roulette Heat Map"
},
"game": {
"history": [0, 2, 4, 6]
}
}
}
The response follows these rules:
- If the requested template is active,
valuescontains its current persistent values. - If the profile used the template previously,
valuescontains the values saved when the profile switched away from it. - If the profile has never used the template,
valuesisnull. Use the template manifest defaults when preparing its initial values.
Template history is scoped to the profile identified by sessionId; it is not shared between streams. The history is maintained automatically when an IDLE profile is reconfigured or a RUNNING renderer switches templates. Stopping ingestion does not archive or discard the active values—the active template remains the profile's current persistent configuration.
The history itself is intentionally omitted from profile lists and normal status responses. Query only the template whose values are needed.
Runtime interaction
Before a runtime operation, retrieve the profile through the global endpoint and confirm that:
statusisRUNNING.fqdnis present.- The request is sent to
https://<fqdn>, not automatically to the global API host.
Parameter validation
The renderer validates values against the active template manifest when starting a session, switching templates or applying a parameter update. Invalid values are rejected before they are rendered or persisted.
Validation includes:
- rejecting parameter paths that are not declared in the manifest;
- checking strings, numbers, colors and action timestamps;
- enforcing numeric
minandmaxbounds and stringmaxLengthlimits; - accepting only values declared by
choose,selectandmultidefinitions; - checking that
multivalues are arrays whose members are declared choices; - recursively validating every object inside a structured
set, including its maximum item count and nested definitions.
Omitted properties are allowed. This is essential for incremental PATCH requests, which contain only changed values. Fields inside a set item may also be omitted, but unknown fields are rejected. Numeric strings such as "3" are accepted for number controls because HTML form inputs commonly produce them.
null is accepted only when the manifest explicitly permits an empty value, such as a removable color or a definition whose default is null.
A validation failure returns 400 Bad Request with the offending parameter path, for example:
{
"error": "Invalid value for home/score: expected a finite number",
"fqdn": "live-04.nebular.tv"
}
or:
{
"error": "Unknown template parameter home/scroe",
"fqdn": "live-04.nebular.tv"
}
Read local renderer state
curl 'https://live-04.nebular.tv/api/overlays/overlay-local/XQA0t-s3Zzx' \
--header 'Authorization: Basic <credentials>' \
--header 'x-ns-token: <token>'
Local status repeats the active template, values, dimensions and maximum sampling at the top level, then adds the public operational fields needed by production clients:
ffmpegFilteris the consumer filter for this profile.consumerConnected: whether the video-processing consumer is connected to the renderer socket through theffmpegFilterabove..framesanddroppedFrames: delivered and coalesced renderer-frame counters.outputEnabled: current runtime visibility.lastError: the latest recorded renderer warning or error, ornull. Most errors do not need action unless debugging unexpected behaviour.
Template metadata is intentionally available only through the template-manifest endpoint and is not repeated in runtime status responses.
If that session is not running on the addressed worker, the response is:
{
"running": false,
"sessionId": "XQA0t-s3Zzx"
}
Refresh the global profile before retrying because ownership may have moved.
Switch the active template
curl --request PUT \
'https://live-04.nebular.tv/api/overlays/overlay-local/XQA0t-s3Zzx/template' \
--header 'Authorization: Basic <credentials>' \
--header 'x-ns-token: <token>' \
--header 'Content-Type: application/json' \
--data '{
"template": "broadcast/lower-third",
"values": {
"content": {
"name": "Alex Morgan",
"role": "Creative Director"
}
}
}'
template is required. values is the complete starting value object for the new template, not an incremental patch, and is validated against that template's manifest. To restore a template's previous state, first obtain its saved values from the global template-values endpoint and supply them here. If that endpoint returns null, construct the initial values from the template manifest defaults.
On success, the outgoing template values are retained in the profile's template history, and the new template and values become the current persistent configuration. If rendering or persistence fails, the server attempts to restore the previous template and values.
Apply an incremental parameter update
curl --request PATCH \
'https://live-04.nebular.tv/api/overlays/overlay-local/XQA0t-s3Zzx/template' \
--header 'Authorization: Basic <credentials>' \
--header 'x-ns-token: <token>' \
--header 'Content-Type: application/json' \
--data '{
"template": "gambling/bingo",
"values": {
"game": {"called": [3, 8, 17]}
}
}'
Both fields are required for a meaningful update:
templateasserts which template the values belong to. If another template is active, the server returns409 Conflictrather than applying incompatible parameters.valuesis an incremental object. Send only the properties that changed. Every supplied path and value is validated against the active manifest.
On success, the response acknowledges the canonical incremental values applied by this operation rather than returning the complete renderer status:
{
"sessionId": "XQA0t-s3Zzx",
"template": "gambling/bingo",
"values": {
"game": {"called": [3, 8, 17]}
}
}
Use the local status GET endpoint when the complete active values or renderer metrics are required.
Nested objects are merged recursively with the persisted state. Scalars and arrays replace their corresponding values. Consequently:
- An absent property remains unchanged.
- An empty string is supplied data and clears a string.
- An empty array is supplied data and clears a collection.
- Supplying an object updates only the object properties present in that object.
For example:
{
"template": "sports/football/scoreboard",
"values": {
"home": {"score": 3}
}
}
changes only home.score; it does not clear the home name, away team or clock.
Dynamic updates are limited to one request per second by default, and their JSON request body is limited to 4 KiB. A rate-limited request returns 429; an oversized request returns 413.
Do not retry a template-mismatch response unchanged. Retrieve current state, decide whether the update is still relevant, and send it only when its declared template is active.
Hide or show the overlay
Hide the rendered overlay:
curl --request PATCH \
'https://live-04.nebular.tv/api/overlays/overlay-local/XQA0t-s3Zzx/output' \
--header 'Authorization: Basic <credentials>' \
--header 'x-ns-token: <token>' \
--header 'Content-Type: application/json' \
--data '{"enabled":false}'
Show it again:
curl --request PATCH \
'https://live-04.nebular.tv/api/overlays/overlay-local/XQA0t-s3Zzx/output' \
--header 'Authorization: Basic <credentials>' \
--header 'x-ns-token: <token>' \
--header 'Content-Type: application/json' \
--data '{"enabled":true}'
enabled must be a JSON boolean, not the string "true" or "false". Visibility changes use a short fade and affect runtime output only; they do not modify template values.
The response is a compact acknowledgment of the resulting visibility:
{
"sessionId": "XQA0t-s3Zzx",
"outputEnabled": false
}
Stop a running renderer
curl --request DELETE \
'https://live-04.nebular.tv/api/overlays/overlay-local/XQA0t-s3Zzx' \
--header 'Authorization: Basic <credentials>' \
--header 'x-ns-token: <token>'
The operation closes the local renderer and releases its owned profile back to IDLE. Persistent template configuration and values are preserved.
In normal operation, the hosting platform stops the renderer automatically when ingestion finishes. Use the external stop operation only when an authorized production workflow deliberately needs to stop it early.
Recovery: force release
Force release is intended for a stale RUNNING registry entry whose owning worker is no longer reachable:
curl --request DELETE \
'https://live.nebular.tv/api/overlays/overlay/XQA0t-s3Zzx?force=1' \
--header 'Authorization: Basic <credentials>' \
--header 'x-ns-token: <token>'
On success, the persistent template and values are preserved and the profile becomes IDLE.
Use force release only as a last resort when the recorded owner is unreachable and operational checks confirm that it is stale.
Responses and errors
Successful configuration and template-switch operations return their resulting profile or local renderer state as JSON. Parameter and output-control PATCH operations return compact acknowledgments containing only the fields affected by the operation.
Errors use this shape:
{
"error": "Template gambling/keno is no longer active; active template is gambling/bingo",
"fqdn": "live-04.nebular.tv"
}
Common status codes are:
| Status | Meaning |
|---|---|
400 |
Malformed JSON, missing fields, invalid values or parameter paths, unsafe template/session name, or incorrect route parameters. |
401 / 403 |
Missing, expired or unauthorized credentials. |
404 |
Template/resource not found, or a requested local renderer is not running. |
409 |
Profile is running when idle configuration was requested, renderer is busy changing state, ownership conflict, or expected template is no longer active. |
413 |
Dynamic-update request exceeds the configured size limit, normally 4 KiB. |
422 |
Template manifest is missing or invalid. |
429 |
Dynamic updates arrived faster than the configured minimum interval, normally one second. |
Treat 409 as a state conflict rather than a transient transport failure. Refresh the profile or local state before deciding whether to retry. Respect 429 by delaying the next update; do not run parameter PATCH requests in a tight loop.
Operational recommendations
- Obtain the active worker from the global profile before issuing runtime calls.
- Retrieve a template's saved values before switching back to it; use manifest defaults only when no saved values exist.
- Use template metadata to construct and validate values rather than hard-coding undocumented fields.
- Include the expected template in every parameter PATCH.
- Send incremental values instead of repeatedly replacing the complete state.
- Serialize operator updates; this API is designed for a coordinated production workflow, not competing concurrent editors.
- Keep tokens and Basic credentials out of source code, logs and command history.
- Use force release only for confirmed stale ownership.