HTTP API

The HTTP API is the control surface for the project that is currently loaded and running in a Composer instance — Desktop or Runtime. Use it to read what's in the project, change property values on the fly, invoke commands, drive media playback, control targets and layers, fetch live snapshots and statistics, and reach into the project script. If you need to make something happen inside a show — show a graphic, switch an input, trigger a connector, kick off a recording, query a target's status — this is the API you want.

What the API can do

  • Drive project lifecycle — start, stop, save, reload, and exit the running project.
  • Read and write the live project — list named objects (inputs, scenes, operators, targets), get / set their properties, and invoke their commands.
  • Control media and layers — play .mp4 / .mxf files in Video File Inputs, jump CAV Players to cue points, switch a layer's source input, and toggle scene render.
  • Move groups of layers together/api/batch/{command} shows / hides / solos every layer carrying a given Batch tag in one call.
  • Stream and snapshot the rendered output — JPEG snapshots, long-lived MJPEG streams, and perceptual-hash image checksums for visual-regression workflows.
  • Trigger connectors and run script — fire a project's API connectors, execute a Script Engine function on demand, and pipe its return value back as the HTTP response.
  • Query state and telemetry — runtime statistics, per-target / per-input status, audio levels, alarms, recent errors, the full performance report, and host capabilities (CUDA / NVENC / NDI / DeckLink / fonts / disk).
  • Manage settings and the license at runtime, scoped by [ApiSetting] for what's editable on the fly.
  • Build projects programmatically — when the Builder API is enabled, create and edit inputs, scenes, layers, targets, operators, and connectors from outside Composer.
  • Discover endpoints at runtimeGET /api/endpoints returns a machine-readable JSON listing of every registered route, useful for client codegen and tooling.

How it differs from the Runtime API

Composer exposes two distinct HTTP APIs on two different ports — they don't overlap, and most production setups use both:

HTTP API (this manual) Runtime API
Scope The currently loaded project The runtime process itself
Available when no project is loaded? No (DisableWebApiWhenNotRunning further restricts it) Yes — stays reachable in the Idle state
Available on Desktop? Yes No — Runtime executable only
Typical use Operating a running show: switching scenes, triggering graphics, querying status Deploying / swapping projects, supervising the runtime process, scraping metrics
URL prefix /api/... /runtime/...

In other words: the Runtime API decides which project is loaded, and the HTTP API drives what happens inside that project. A scheduler that swaps MorningShow.prj for EveningShow.prj uses the Runtime API; a control surface that flips a lower-third on cue uses the HTTP API.

The two APIs share the same apikey authentication mechanism and the same apikeys.json file — see Authentication below.

General Information

  • Base URL: http://{hostname}:{port}/api/
  • HTTPS: Optionally available at https://{fqdn}/api/ if configured
  • Method: All endpoints accept GET requests
  • Authentication: API key via apikey header or ?apikey= query parameter. Keys are validated against apikeys.json.
  • CORS: All responses include Access-Control-Allow-Origin: *
  • Suppress logging: Add NOLOG=TRUE to the query string to prevent the call from being logged
  • API when stopped: If DisableWebApiWhenNotRunning is enabled in settings, only /api/start, /api/stop, /api/quit, and /api/exit are available when playback state is not Running.
  • All endpoint paths are case-insensitive.
  • Endpoint discovery: GET /api/endpoints returns a machine-readable JSON listing of all registered endpoints with descriptions, categories, and response types.
  • Unknown endpoints: Requests that don't match any registered route return 404 Not Found with body api command not found.

Note — not available on Core licences

The HTTP API is disabled at startup under a Vindral Composer Core (free) licence. No listener is opened on HttpApiPort and all requests will fail with connection refused. A single Core license: HTTP API disabled. line is written to the Composer log. Upgrade to a Subscription or full licence to enable the HTTP API. See Activating a license for licence-tier details.


Authentication

Both the HTTP API and the Runtime Lifecycle API use the same API key mechanism.

How it works

API keys are provided via the apikey HTTP header or the ?apikey= query parameter. The header is checked first; if empty, the query parameter is used as fallback.

# Header
curl -H "apikey: my-secret-key" http://localhost:8080/api/getstatistics

# Query parameter
curl http://localhost:8080/api/getstatistics?apikey=my-secret-key

Keys are validated against apikeys.json, located in the application directory (next to the executable).

apikeys.json format

{
  "Keys": [
    "my-secret-key",
    "another-key"
  ]
}

A backup (apikeys.bak) is created automatically on startup. If apikeys.json is missing but apikeys.bak exists, the backup is restored. If neither file exists, an empty apikeys.json is created.

Validation behavior

Scenario Result
Key provided and matches an entry in apikeys.json 200 — request proceeds
Key provided but does not match any entry 401 Unauthorized — request rejected
No keys defined in apikeys.json (empty Keys array) Request proceeds (API is open)
apikeys.json missing or could not be loaded Request proceeds (API is open)

In short: if you define keys, callers must provide a valid one. If you don't define any keys, the API is open to all callers. Key comparison is case-sensitive.


Endpoint Discovery

GET /api/endpoints

Returns a JSON listing of all registered API endpoints. Endpoints gated by EnableBuilderApi are excluded from the response when that setting is disabled.

Parameters: None

Response: 200 OK — JSON object:

{
  "count": 72,
  "builderApiEnabled": true,
  "endpoints": [
    {
      "path": "/api/alarms/clear",
      "category": "Statistics",
      "description": "Clear all active alarms",
      "responseType": "json",
      "method": "GET",
      "requiresBuilderApi": false,
      "parameters": []
    },
    {
      "path": "/api/setproperty",
      "category": "Objects",
      "description": "Set a property value on a named object",
      "responseType": "html",
      "method": "GET",
      "requiresBuilderApi": false,
      "parameters": [
        { "name": "target", "type": "guid", "required": false, "description": "Object GUID" },
        { "name": "targetname", "type": "string", "required": false, "description": "Object name (must be unique)" },
        { "name": "targettype", "type": "string", "required": false, "description": "Object type name (must be unique)" },
        { "name": "property", "type": "string", "required": true, "description": "Property name (case-sensitive)" },
        { "name": "value", "type": "string", "required": true, "description": "New value (auto-converted)" }
      ]
    },
    {
      "path": "/api/input/create",
      "category": "EntityManagement",
      "description": "Create a new input",
      "responseType": "json",
      "method": "GET",
      "requiresBuilderApi": true,
      "parameters": [
        { "name": "type", "type": "string", "required": true, "description": "Input type name" },
        { "name": "name", "type": "string", "required": false, "description": "Proposed input name" }
      ]
    }
  ]
}

Endpoint reference

Project Control

  • POST /api/start — Starts Composer processing.
  • POST /api/stop — Stops Composer processing.
  • POST /api/exit — Exits the Composer application. Playback must be stopped first.
  • POST /api/quit — Exits the Composer application. Only works when playback state is Stopped.
  • GET /api/project/setproperty — Sets a property on the Project object itself. Use this for project-level settings that aren't reachable via /api/setproperty (which only targets NamedModel instances such as inputs, scenes, operators, and targets). Examples: StartAllInputsOnStart, StartAllTargetsOnStart, UseOptimizedRenderer, VideoFrameRate.
  • GET /api/project/save — Saves the current project to disk. Without parameters, overwrites the running .prj file (the one Composer was launched with). With path, performs a "Save As" to a different file without changing the running project's file association.
  • GET /api/project/getxml — Returns the raw XML content of the current project file.
  • POST /api/project/loadlatestversion — Triggers Composer to reload the project from disk if a newer version is available, or if the current project file has been modified.
  • GET /api/project/list — Lists .prj files in the directory of the currently-loaded project. Returns an empty list if the directory contains no other projects; returns 400 if no project is loaded.
  • GET /api/project/load — Loads a named .prj file from the current project's directory. The project must be stopped first (POST /api/stop); the server returns 409 Conflict if it's running.
  • POST /api/project/upload — Uploads a new .prj file into the current project's directory. The request body is the file's raw bytes (no multipart wrapping). Existing files are overwritten unless overwrite=false.
  • GET /api/project/limits — Reports the upload-related limits and current project-volume capacity. A client can query this once on entry to reject a too-big upload locally instead of streaming a 1 GiB body just to receive 413.
  • POST /api/project/asset/upload — Uploads an asset (audio / video / image / .js script) into the current project's directory. Existing files are overwritten unless overwrite=false.
  • GET /api/project/tree — Returns the loaded project's hierarchical structure: scenes, layers, operators, and per-scene targets, plus the project-level inputs collection. Designed for browser-based admin UIs that need to render a navigable tree of the project without making many flat /api/objects/list calls and reconstructing containment.

Statistics & Monitoring

  • GET /api/getstatistics — Returns a comprehensive JSON object with runtime statistics.
  • GET /api/targets/getstatistics — Returns RTMP target statistics for all scenes.
  • GET /api/lasterror/get — Returns the last 20 entries with severity Error from the in-memory log cache, oldest first. Useful for surfacing recent failures in a monitoring dashboard without parsing log files.
  • GET /api/alarms/get — Returns the current alarm state.
  • POST /api/alarms/clear — Clears all currently active alarms in one shot — equivalent to clicking the "Clear alarms" button in Composer Desktop. Idempotent: returns 200 OK even when no alarm is active.
  • GET /api/reports/getperformancereport — Generates and returns the same performance report Composer Desktop produces under Analysis → Performance Report, served as HTML. Includes application info, project info, system info, GPU info, settings snapshot, performance metrics, lifetime statistics, and per-component processing-time breakdowns. Generation runs synchronously on the calling thread and typically completes in under a second on a healthy host.
  • GET /api/performance/get
  • GET /api/systeminfo/get — Returns OS-level host hardware and platform information collected from the .NET ComputerInfo API. Available on Windows hosts (the underlying API is Windows-only); Linux hosts return 501 Not Implemented.

Capabilities

  • GET /api/capabilities — Returns static hardware and software capabilities of this Composer instance: CUDA devices, NVENC/NVDEC support, NDI runtime, DeckLink devices, fonts, disk space, and FFmpeg. Read-only, responds immediately. Useful for capacity planning, feature-gate checks, and diagnostic tooling.

Object Management

  • GET /api/objects/list — Lists all named objects (inputs, operators, targets, etc.) in the project.
  • GET /api/objects/getproperties — Returns the properties of a named object as a flat JSON object: {"PropName": value, ...}. Includes every public-getter property that is not marked [InternalProperty] (so public get / private set runtime status fields and computed read-only properties are part of the response). Property values that reference a NamedModel-derived object are rendered as a compact identity stub { "Id": ..., "Name": ..., "Type": ... } to keep the response bounded.
  • GET /api/setproperty — Sets a property value on a component.
  • GET /api/getproperty — Gets a property value from a component.
  • GET /api/invokecommand — Invokes a command on a component.

Media

  • GET /api/media/videofileinput/play — Loads a media file into a Video File Input and starts playback.
  • GET /api/cavjumptocuepoint — Jumps a CAV Player to a specific cue point.
  • GET /api/cavgetcuepoints — Returns all cue points from a CAV Player as JSON.
  • GET /api/facedetect/getimage — Returns the best face detection result as a JPEG image.
  • GET /api/image/get — Returns a single JPEG snapshot of a rendered image source — either a Scene or an AbstractInput (any input that has produced a RenderedCudaBgraImage).
  • GET /api/image/stream — Opens a long-lived MJPEG (multipart/x-mixed-replace) stream of a rendered image source. Each connection spawns its own worker thread so the VideoWorker is never blocked by the streaming loop, and each connection gets its own JPEG compressor to avoid cross-connection contention. The connection stays open until the client disconnects or the server shuts down. The source is re-resolved on every tick, so renaming or replacing the underlying NamedModel takes effect on the next frame without restarting the stream.
  • GET /api/image/preview — Serves an HTML page with an embedded MJPEG viewer, scene selector, quality/size/FPS controls, and a collapsible performance sidebar. Styled to match the Composer Desktop dark theme.

Events

  • Why SSE and not polling — A live UI or dashboard needs to know when state changes (a project loaded, an error logged, a thumbnail refreshed) — not just what the state is. Polling for that with a fast loop wastes bandwidth and adds latency proportional to the poll interval; long-polling closes and reopens a connection per event, costing a TCP/TLS handshake per cycle. SSE keeps one connection open, pushes events when they happen, and falls back to the same text/event-stream wire format MJPEG already uses through the Gateway — proven to proxy cleanly with existing infrastructure.
  • GET /api/events/subscribe — Opens a long-lived text/event-stream connection. Each event arrives as a pair of lines — an event: line naming the event kind and a data: line carrying a single-line JSON payload — separated by a blank line. The server emits a : keepalive comment every 15 s so dead connections are detected within ~30 s on both ends, and intermediate proxies / NAT mappings stay open on otherwise-quiet streams.

Files

Source

  • GET /api/source/reload — Re-applies the current SourceUrl on the target (nulls it then restores it, forcing the setter's load path — the API equivalent of Composer Desktop's Reload-media button).
  • GET /api/source/clear — Clears the target's SourceUrl (sets it to null).

Streaming & Targets

  • GET /api/inputs/get/status — Returns status for all inputs regardless of type. Common fields are always present; type-specific properties are resolved via reflection and omitted when not applicable.
  • GET /api/targets/get/status — Returns status for all targets across all scenes. Common fields are always present; type-specific properties are resolved via reflection and omitted when not applicable.
  • GET /api/inputs/get/srt — Lists all SRT inputs and their status, including both the standard SrtInput and the 16-channel-audio variant SrtInput16ChannelAudio. Inputs of any other type are omitted.
  • GET /api/targets/get/srt — Lists all SRT targets and their status, including both the standard SrtTarget and the 16-channel-audio variant SrtTarget16ChannelAudio. Targets of any other type are omitted.
  • GET /api/targets/get/rtmp — Lists all RTMP targets and their status.
  • GET /api/target/executecommand — Executes a command on a specific target within a scene.
  • GET /scene/disablerender — Enables or disables rendering for a scene at the engine level. When disabled, the scene's video compositing pipeline is skipped entirely each frame and audio is replaced with silence — any targets attached to that scene receive a black/silent feed but stay running. Render Tuning settings on the scene are bypassed while disabled.
  • GET /scene/audio/getaudiolevellastsecond — Returns audio peak levels from the last second for a scene.
  • GET /api/audio/getpeaklevels — Returns the live per-channel audio peak levels for an input or a scene, measured directly from that object's rendered audio frame.

Connectors

Layer Control

Batch Operations

  • What is a "batch"? — In Composer, a batch is a free-form tag on a layer (set via the layer's Batch property — one or more space-separated tag words). Batches let you treat a group of layers as one named bundle so a single API call can show, hide, or solo every layer carrying that tag at once.
  • GET /api/batch/ — Show, hide, or solo every layer whose Batch tag matches the given name. The match runs across all scenes by default and is applied asynchronously by the runtime — the request is queued the moment the call arrives and processed on the next frame while playback is Running.

Configuration

  • GET /api/settings/get — Returns the full Composer settings object as JSON — every public property on Settings.cs (currently ~87 fields covering audio, GPU, project management, render tuning, web API, alarms, autosave, etc.). Use this to snapshot the configured state of a running Composer for diagnostics, configuration drift detection, or to seed a backup.
  • GET /api/settings/set — Sets a Composer setting at runtime. Only settings marked with the [ApiSetting] attribute can be modified; all other settings return 403 Forbidden.
  • GET /api/settings/getjson — Identical behaviour to /api/settings/get — same JSON, same response code. Retained as an alias because some older client integrations call this URL. Prefer /api/settings/get for new code.
  • GET /api/license/get — Returns the current LicenseInformation for this Composer host as JSON — the licence key, customer, type, expiry, plug-in licences, and host-locking flags read from the licence file on disk. Returns the same payload regardless of trial / evaluation / subscription status; callers can inspect IsTrial / LicenseType / Expirydate to differentiate.
  • GET /api/license/validate — Returns the current local validation state of the licence — a snapshot of the flags Composer maintains in memory. Local check only — this endpoint does not initiate a fresh round-trip to license.vindral.com; it reads the cached state from the most recent server interaction (which Composer performs on its own schedule). Use this as a quick health probe in monitoring or readiness checks.
  • Script structure: legacy globals vs. ES6 modules — Composer's script engine (Jint) supports two modes for the project script. The mode is detected automatically from the file's contents — there is no flag or setting to toggle.
  • GET /api/scriptengine/execute — Executes a JavaScript function in the Composer Script Engine. The function's return value shapes the HTTP response using the same contract as /api/connector/trigger — string returns become text/plain, objects/arrays become application/json, and a returned object with a numeric httpStatus lets the script set the response code.

WebSocket Management

Debug & Testing

Auto-Test Control

  • GET /api/autotest/setduration — Sets the autotest duration in seconds. Minimum allowed duration is 2 seconds. Also recalculates the kill deadline to 3x the new duration from now.
  • GET /api/autotest/getduration — Returns the current autotest duration in seconds.
  • GET /api/autotest/setcompleted — Signals that the autotest has completed. The autotest timer will terminate immediately on the next tick, bypassing the remaining duration countdown.

Discovery

  • GET /api/discovery/instances — Returns the list of other Composer instances this host has discovered on the local network. Composer's discovery service announces itself via UDP broadcast and listens for peer announcements; this endpoint exposes whatever's currently in the discovered-instances cache. Useful when building a multi-instance dashboard or a control surface that needs to enumerate available Composer hosts.

Image Checksum

  • GET /api/image/checksum — Returns a perceptual hash of the current rendered frame for a scene, as a 16-character hexadecimal string. Perceptual (rather than cryptographic / pixel-perfect) so that minor codec / colour drift doesn't trip the comparison — useful for visual-regression checks where two near-identical frames should compare equal but a meaningful change should not.
  • GET /api/image/checksum/compareorstore — Compares the current rendered scene's perceptual hash against a stored reference identified by step. If no reference exists for that step name yet, the current hash is stored as the new reference (so the first call to a step is always a "store"; subsequent calls compare against it). Stored references live in-memory for the lifetime of the running Composer session.

Builder API (Entity Management)

  • GET /api/types/inputs — Lists all available input types with metadata. Uses reflection to enumerate exported types from loaded assemblies.
  • GET /api/types/targets — Lists all available target types with metadata. Mirror of /api/types/inputs — same shape, just for AbstractTarget subclasses.
  • GET /api/types/operators — Lists all available operator types with metadata. Operators return Id, Name, FullName, About plus the license-gating fields below (no Category / CanHaveAudio / CanHaveVideo).
  • GET /api/types/schema — Returns the full property schema for a given input, operator, or target type. Useful for builder UIs that need to render property editors without a running instance.
  • Input CRUD — Creates a new input by type name. The new input is added to the project root and assigned the proposed name (or an auto-generated unique name if name is omitted or collides).
  • Scene CRUD — Creates a new scene. Width and height are optional — when supplied (either or both), the scene's resolution is set to Custom; otherwise the project default is used.
  • Layer CRUD — Creates a new layer in a scene from an existing input. Initial transform and layer properties can be set inline using transform.* and layer.* query-parameter prefixes.
  • Target CRUD — Creates a new target in a scene by type name.
  • Operator CRUD — Creates a new operator on a layer. Most operator types use a parameterless constructor, but a handful expose a static factory method instead — both forms are supported.
  • Connector CRUD — Creates a new API connector at the project level. Empty connectors have no commands and no effect when triggered — add commands with /api/connector/command/add.
  • API Command CRUD (within Connectors) — API Commands are the individual property-set / command-invoke actions inside a connector. They run in order each time the connector is triggered.