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).
  • Subscribe to live events — a Server-Sent Events stream (GET /api/events/subscribe) pushes project-lifecycle, log, 1 Hz performance, source-change, and switcher-state events so dashboards and integrations react without polling.
  • 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 runtime — GET /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 the Authentication and API keys page for the file format and role model.

General Information

  • Base URL: http://{hostname}:{port}/api/
  • HTTPS: Optionally available at https://{fqdn}/api/ if configured
  • Method: All endpoints accept GET requests
  • Authentication & authorization: API key via apikey header or ?apikey= query parameter. Keys are validated against apikeys.json. Each key carries a role (viewer / operator / editor / admin) that determines which endpoints it may call. An unknown/invalid key returns 401 Unauthorized; a valid key whose role lacks the endpoint's required permission returns 403 Forbidden. When no keys are defined the API is open and every request runs as admin. See Authentication and API keys for the full role model.
  • 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, /api/exit, /api/discovery/*, /api/project/list, /api/project/load, /api/project/upload, /api/project/asset/upload, /api/project/limits and /api/autotest/setcompleted 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.


Endpoint Discovery

GET /api/endpoints

Requires: read (viewer+)

Returns a JSON listing of all registered API endpoints. Endpoints gated by EnableBuilderApi are excluded from the response when that setting is disabled. Each entry includes a requiredPermission field (read / control / config / builder / admin) so tooling can present the role needed to call it.

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,
      "requiredPermission": "control",
      "parameters": []
    },
    {
      "path": "/api/setproperty",
      "category": "Objects",
      "description": "Set a property value on a named object",
      "responseType": "html",
      "method": "GET",
      "requiresBuilderApi": false,
      "requiredPermission": "control",
      "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,
      "requiredPermission": "builder",
      "parameters": [
        { "name": "type", "type": "string", "required": true, "description": "Input type name" },
        { "name": "name", "type": "string", "required": false, "description": "Proposed input name" }
      ]
    }
  ]
}

Endpoint reference

Authentication and API keys

  • 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.
  • apikeys.json format — apikeys.json accepts two forms, and the two can be mixed in one file.
  • Roles & permissions — Each key maps to one of four roles — viewer, operator, editor, admin — that form a fixed ladder, where each higher role is a superset of the ones below it.
  • Validation behavior — Every request resolves to one of four outcomes, depending on whether the key is valid and whether its role covers the endpoint's required permission.
  • WebSocket authentication — The WebSocket API uses the same apikeys.json keys and the same roles. A client presents its key on the connection handshake — either as an ?apikey= query parameter on the WebSocket URL or an apikey header. When keys are defined and the RequireWebSocketAuth setting is enabled (the default), a missing or invalid key is rejected at connect time (the server sends an Error message and closes the socket). Once connected, per-message operations are gated by the connecting key's role: subscriptions require read, while the SetPropertyValueByObjectId and ExecuteCommandByObjectId messages require control. Setting RequireWebSocketAuth to false restores the pre-RBAC behaviour (any client may connect). Open mode (no keys defined) always connects as admin. See the WebSocket API for the full message-level details.

Project Control

  • POST /api/start — Starts Composer processing, playing the project currently in memory — including any
  • POST /api/stop — Stops Composer processing. The project stays loaded, so a subsequent /api/start resumes
  • 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 the statistics of every streaming target in the project, in one array per target family: RtmpTargets, SrtTargets, NdiTargets, MoQTargets. Each array is flat across scenes, and every array is present even when the project has no target of that family — an absent array would be indistinguishable from an empty one, which is what tells a caller whether the family is reported at all.
  • GET /api/decklink/metrics — Returns arrival timing and capture counters for every DeckLink input. The Desktop Windows → DeckLink manager… window reads the same measurements. Collection continues while the window is closed. Requires Read permission.
  • GET /api/inputs/getstatistics — Returns the statistics of every input in the project, in one array per input family: RtmpInputs, SrtInputs, NdiInputs, MoQInputs, and OtherInputs for everything else. This is the input counterpart of /api/targets/getstatistics, and like it every array is present even when the project has no input of that family.
  • 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.
  • GET /api/srtsync/status — Returns the live status of the SRT input synchronization group — every SRT input that has Synchronize enabled — in a single response, so a caller can see whether all genlocked sources are frame-aligned without scraping each input's statistics.

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 snapshot of a rendered image source — either a Scene or an AbstractInput (any input that has produced a RenderedCudaBgraImage). JPEG by default; format=png returns the frame losslessly.
  • 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).

Switcher

  • GET /api/switcher/program — Sets the switcher's foreground (PGM, on-air) source.
  • GET /api/switcher/preview — Sets the switcher's background (Preview, next) source. Same parameters and responses as /api/switcher/program, applied to BackgroundInputName.
  • GET /api/switcher/cut — Hard cut between foreground (PGM) and background (Preview).
  • GET /api/switcher/crossfade — Crossfade between foreground and background over the configured crossfade duration.
  • GET /api/switcher/fadetoblack — Fade the switcher output to or from black (FTB).
  • GET /api/switcher/tally — Reads the live tally status — which sources are on air, queued, or being used by an overlay. Unlike the control routes above, omitting the selector is not an error: with no target / targetname / targettype every switcher in the project is reported, so a tally display can poll one URL without knowing how many switchers exist.
  • Examples — All examples assume the host localhost:44433; add ?apikey=<key> (or an apikey header) if your instance requires one.

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. This works while the project is stopped too, including when DisableWebApiWhenNotRunning is on.

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/pixel — Reads the rendered colour at a point: the mean of a small patch centred on x,y, plus that patch's per-channel minimum and maximum. Answers "what does the frame look like here", which neither /api/image/get (an encoded image you have to decode yourself) nor the checksum endpoints (equal / not equal) can.
  • GET /api/image/grain — Measures how grainy a region is: the mean absolute difference between each pixel's luma and the median luma of the 3×3 neighbourhood around it. High-frequency variation scores; a smooth gradient or a hard edge does not — a median is unmoved by a single outlier, so a lone bright pixel counts as grain while a step between two flat regions counts as almost nothing. That is what makes it a noise metric rather than a contrast one.
  • GET /api/image/sharpness — Measures how sharp an edge is: the 10-90% rise distance across the strongest transition in the patch, in pixels. 1-2 px is a hard edge; tens of pixels is a soft one. The counterpart to /api/image/grain - that measures unwanted high-frequency variation, this measures wanted high-frequency structure. Neither is reachable with /api/image/pixel, which reports a patch mean.
  • 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.
  • GET /api/image/reference/compareorstore — Pixel-compares the current rendered scene against the project's reference image — {ProjectName}-reference.png, next to the loaded .prj. If that file does not exist yet, the current frame is stored as the reference (a lossless PNG) and the call reports stored: true; otherwise it returns the percentage of differing pixels. This is a stricter, pixel-accurate alternative to /api/image/checksum/compareorstore (which uses a tolerant perceptual hash): use it when you want to catch subtle rendering changes and keep a human-reviewable golden image under version control.

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.