Connectors

A Connector is a project-defined HTTP trigger that bundles a saved sequence of API commands behind a named endpoint, so external systems can drive the show by name (RollSting, LowerThirdOn) rather than re-wiring individual /api/setproperty and /api/invokecommand calls. Connectors can also call an optional OnConnector{Name} script function whose return value shapes the HTTP response — see the Script return-value contract below. For the authoring workflow, see User Guide → Connectors.

GET /api/connector/list

Requires: read (viewer+)

Lists configured API connectors, optionally filtered by running state and group.

IsRunning and TimerMs are live status rather than stored settings: a connector counts as running while one of its API commands is still animating or waiting out its delay, and TimerMs is how long it has been running since it was last invoked.

Parameters:

Parameter Required Description
running No true returns only connectors that are currently running, false only idle ones. Omit for all.
group No Only connectors in this group, matched case-insensitively. Supply it with an empty value (?group=) to select the ungrouped connectors.

The two filters compose, so ?group=Stings&running=true answers "what is running in this group".

Response: 200 OK — JSON array:

[
  { "Id": "guid", "Name": "My Connector", "Group": "Stings", "IsActive": true, "IsRunning": false, "TimerMs": 0.0, "InvokeCount": 0, "Description": "" }
]
  • 400 Bad Request — running was supplied with something other than true or false

GET /api/connector/stop

Requires: control (operator+) — stopping a connector only unhooks the timers of a sequence already in flight; it runs no script and reads no settings, so it is not gated at config the way trigger is.

Stops running connectors selected by name, id or group. Stopping freezes an in-flight animation where it stands rather than jumping it to its end value, and cancels the connector's pending delayed commands.

Parameters:

Parameter Required Description
name No* Connector name, matched case-insensitively.
id No* Connector id (GUID).
group No* Group name, matched case-insensitively.

*Exactly one of name, id or group is required. Supplying none or several is rejected rather than resolved by precedence, so a malformed call cannot silently stop the wrong thing. A selector counts as supplied when its key is present, whatever its value: ?name=A&group= names two selectors and is rejected, not treated as a call on name alone. A single selector present but empty (?group=) is also rejected — unlike /api/connector/list, where ?group= deliberately means "the ungrouped connectors". There is no "stop everything ungrouped"; use /api/connector/stopall if that is what you want.

Response:

  • 200 OK — JSON: { "success": true, "matched": 3, "stopped": 2, "connectors": ["Sting"], "message": "Stopped 2 connector(s)" }. matched counts the connectors the selector found; stopped counts how many of those were actually running. The two differ when a selector matches connectors that were already idle.
  • 400 Bad Request — no selector, more than one selector key present, an empty selector, a malformed id, or nothing matched
  • 409 Conflict — several connectors share the given name. Stop by id instead.

Stopping is complete: a connector that was triggered repeatedly while a delayed or animated command was still in flight leaves nothing scheduled behind, and does not reappear in ?running=true afterwards.


GET /api/connector/stopall

Requires: control (operator+)

Stops every running connector.

Parameters: None

Response: 200 OK — the same JSON shape as /api/connector/stop, where matched is the total number of connectors in the project.


GET /api/connector/trigger

Requires: config (editor+) — a connector can run a script (OnConnector{Name}) that reads or writes settings and secrets, so it is gated at config.

Triggers one or more API connectors. If the project's script has an OnConnector{Name} function for the matching connector, its return value shapes the HTTP response (see Script return-value contract below).

Parameters:

Parameter Required Description
name No* Connector name. Trigger several at once by separating them with a literal + — ?name=ConnA+ConnB. Every name given must exist, or the call is rejected and none of them fire.
value No* Trigger value string

*At least one of name or value is required.

Additional query parameters (beyond apikey, name, value) are forwarded to the connector as parameters.

Behavior:

  • If ConnectorRestrictions is set to WarnAndProhibit and a connector is already running, the call is rejected with 409 Conflict.
  • If ConnectorRestrictions is set to StopRunningConnectorsInSameGroup, each connector this call invokes first stops the other running connectors that share its Group. Connectors in other groups keep running, and a connector with an empty Group neither stops others nor is stopped — so grouping stays opt-in and a project that sets no groups behaves as it did before.
  • For multi-name calls (name=A+B+C), each connector's OnConnector{name} runs in turn; the first one that returns a usable value wins as the HTTP response.
  • The + is the separator, so escape it inside a name. The value is split on + first and each part is percent-decoded afterwards. A name with a space is written ?name=Connector%20%231 (one connector, Connector #1); a name that itself contains a plus is written ?name=Plus%2BNamed (one connector, Plus+Named). This is the same for a call made over HTTP and one queued from a script or the Test-connector button.
  • Connectors are dispatched in the order given, and for a value= match in the order they were created. With StopRunningConnectorsInSameGroup that decides the survivor when one call starts several connectors sharing a group: each stops the others in its group as it starts, so the last one dispatched is the one left running. This is dispatch order, not a priority setting.
  • Case-insensitive. The query parameter keys (name, value) and the connector name lookup are both matched without regard to case — ?Name=Foo, ?NAME=foo, and ?name=FOO all resolve to a connector named Foo.
  • An unusable value on an animated or plain-property command does not fail the call. Where a command animates a property, or writes one whose type is neither text nor a URL, a value that cannot be read as that type is skipped and logged as a warning; the connector's remaining commands still run and the response is unchanged. Text and URL commands are not covered by that rule and can still fail the call. Numbers are read the same way everywhere — 1820.5, with . as the decimal point and no group separator, whatever the machine's language — so a command behaves identically whether it was loaded from the project file or edited in the Desktop since the last save.

Response:

  • Custom status / body / content type — when the matching OnConnector{name} script returns a usable value (see contract below).
  • 202 Accepted — fallback text/html body Successfully dispatched connector trigger ApiTriggerName: {name}, ApiTriggerValue: {value} when no script returned anything.
  • 400 Bad Request — Missing parameters or connector not found
  • 409 Conflict — Another connector is already running (when restrictions apply)

Script return-value contract details

The same contract applies to /api/scriptengine/execute. The mapping from the JS function's return value to the HTTP response is:

Script returns HTTP response
string (non-empty) 200 OK, Content-Type: text/plain, body = string
object / array 200 OK, Content-Type: application/json, body = JSON-serialized value
object with a numeric httpStatus field, with a body field — explicit envelope { httpStatus, body, contentType? } status from httpStatus; body = body (string → text/plain, object → application/json); content type override via optional contentType (full header value, e.g. "Content-type: text/html; charset=utf-8")
object with a numeric httpStatus field, no body field — hybrid shape { ..., httpStatus } status from httpStatus; body = the remaining fields (everything except httpStatus and contentType) serialized as JSON
undefined, null, empty string, or no return statement falls back to the endpoint's default message
function not defined / script engine disabled / engine errored falls back to the endpoint's default message

Notes:

  • A non-numeric httpStatus value is treated as a regular payload field — the whole object is serialized as JSON 200 OK and a warning is logged.
  • An empty body forces the response to 204 No Content regardless of the requested status (HttpListener behavior).
  • Status codes pass through verbatim; HttpListener rejects obviously-invalid codes and the endpoint returns 400 in that case.

Examples (script function bodies):

// Plain text
function OnConnectorStartDemo() { return "Demo started"; }
// → 200 text/plain "Demo started"

// JSON 200 OK
function OnConnectorListScenes() { return Project.Scenes.map(s => s.Name); }
// → 200 application/json ["Main","Standby"]

// Hybrid: error response with custom status
function OnConnectorShowMultipliers() {
    return { result: "error", message: "Demo mode active", httpStatus: 400 };
}
// → 400 application/json {"result":"error","message":"Demo mode active"}

// Explicit envelope: HTML body with custom status
function OnConnectorStatusPage() {
    return {
        httpStatus: 200,
        body: "<h1>Composer is up</h1>",
        contentType: "Content-type: text/html; charset=utf-8"
    };
}
// → 200 text/html <h1>Composer is up</h1>

GET /api/metadata/send

Requires: control (operator+)

Sends a metadata message via a Vindral CDN Metadata Target.

Parameters:

Parameter Required Description
targetid Yes GUID of the Vindral CDN Metadata Target
message Yes Metadata message string

Example:

/api/metadata/send?targetid=guid&message=My metadata message

Response:

  • 200 OK — Metadata sent: {url}
  • 400 Bad Request — Missing parameters or target not found