AD-DA.ca, Webhook
Plugin Description
The AD-DA.ca Webhook plugin embeds a lightweight HTTP server directly inside a Q-SYS Core and exposes user-defined webhook endpoints. When an external system sends an HTTP request to a configured Path, the plugin flashes an LED, captures the request payload (JSON body and/or query string), and surfaces matching key/value pairs as Q-SYS controls so that other plugins, scripts, or design logic can react to the incoming data.
The plugin is built on a custom Express-like HTTP server module with middleware support, route parameters, JSON body parsing, Bearer-token authentication, and Host-header interface filtering. Parameters from the query string and the JSON body are merged automatically (body values take precedence on collision), allowing the same endpoint to be triggered from either GET or POST requests.
In addition to user-defined webhooks, the plugin exposes a set of built-in endpoints to read the design status and inventory, and to remotely drive Q-SYS Named Components and Named Controls. This makes the plugin a single entry point for integrating Q-SYS with external automation systems, control panels, mobile apps, and cloud services.
Key features
Passive webhook listening - The plugin exposes configurable HTTP endpoints that passively listen for incoming
GETorPOSTrequestsImmediate trigger execution - Upon receiving a webhook, the plugin instantly updates control pins based on the value and status extracted from the payload, enabling real-time control of connected applications or devices
Flexible data input - Supports data reception via query parameters (HTTP
GET) or through JSON payloads (HTTPPOST) withContent-Type: application/jsonTrigger support without parameters - Can respond to simple webhook triggers even when no parameters are provided with the
GETrequest or no data payload is received with thePOSTrequest, allowing the path to act as a pure triggerMulti-path listening - Up to 6 independent webhook paths, each with configurable key/value extraction
Extended key monitoring - Up to 32 key-value pairs can be monitored per webhook path
Hold or Pulse Mode - Per-webhook toggle to either hold the last received value or clear it after each request
Bearer Token Authentication - Optional
Authorization: Bearer <token>enforcement on all routesInterface Filtering - Bind the server to a specific network interface or accept requests on any interface
Built-in Status and Inventory Endpoints -
/statusand/inventoryreturnDesign.GetStatus()andDesign.GetInventory()as JSONNamed Component Control Endpoint -
/namedcomponentdrives any Named Component control (Trigger,SetString,SetPosition,SetValue,SetBoolean,Toggle) with optional ramp timeNamed Controls Endpoint -
/namedcontrolsdrives Named Controls using the same action setAutomatic Path Sanitization - Paths are normalized (allowed characters, collapsed slashes, leading slash forced)
Case-insensitive Routes - Endpoints match regardless of URL casing
Use cases
Integrate with a room booking system to automatically power on AV equipment via webhook
React to smart-home or building-automation events (e.g. sensors, wireless buttons) to control Q-SYS audio
Connect Q-SYS to cloud automation platforms such as Zapier, IFTTT, Home Assistant, Unifi, etc.
Trigger scenes or presets remotely via webhook calls from third-party systems
Integrating Q-SYS with external automation, BMS, or AV control systems
Exposing read-only design status and inventory to monitoring tools
Remotely driving Named Components and Named Controls without writing custom Lua
Configuration Overview
Plugin version
This document is written for the plugin :
AD-DA.ca Webhook V1.2.0.0
Release note
[2026-06] : V1.2.0.0
Migrated to Express-like HTTP server module with middleware support
Added built-in
/statusand/inventoryendpoints returningDesign.GetStatus()andDesign.GetInventory()as JSONAdded Body and Code Response Controls
Added Path sanitization and case-insensitive route matching
New UI
FixesMemory leak fixed under heavy load
[2025-07] : V1.1.0.0
Added
Data Pair CountpropertyAdded
Complete URL PathcontrolsInitial release to Asset Manager
[2025-04] : V1.0.0.0
Initial release
QDS compatibility
This plugin has been developed and tested on :
Q-SYS Designer versions
9.13.0thru10.3.0Q-SYS Designer version
10.0.X- known Emulation Mode issue with network interface address selection (works normally in Run Mode on a physical Core)
Properties
License
Type: String
Default value: Empty
Description: License key activated for the main core.
Licenses are issued on a "per core" basis, as in each core needs its own license to run as many instances of the plugin as needed on this particular core and licenses are not transferable from core to core.
License keys can be added while in Offline mode, in the Properties pane on the right. To purchase licenses, go to https://ad-da.ca.
The plugin can be emulated for free, allowing you to prepare everything without requiring you to have access to a core.
License Backup
Type: String
Default value: Empty
Description: License key activated for the backup core.
If your main Q-SYS Core fails, the backup Core automatically takes over without needing a license to function as a temporary replacement. However, if the design boots from the backup Core, a valid license is required. Additionally, if the backup Core is restarted (due to power loss or other reasons), the plugin instances cannot initialize without a valid license.
Webhook Count
Type: integer
Min: 1
Max: 6
Default Value: 1
Description: Number of independent webhook endpoints exposed by the plugin. Each webhook generates its own page with Path, URL, Hold, LED, Data, and key/value controls.
Data Pair Count
Type: integer
Min: 4
Max: 32
Default Value: 4
Description: Number of key/value rows generated per webhook. Each row extracts one named parameter from the incoming request and exposes its value as a control.
Dev
Type: string
Default Value: ""
Description: Developer/debug field reserved for internal use.
Debug Print
Type: enum
Choices: None, Tx/Rx, Tx, Rx, Function Calls, All, Debug
Default Value: None
Description: Controls verbosity of debug messages printed to the Q-SYS Designer Console. Use Tx/Rx to see HTTP traffic, Function Calls to trace plugin execution, or All/Debug for full diagnostics.
Controls
Status
Status
Controls name: Status
Type: Indicator-Text
Description: Displays the verbose current operational status of the plugin:
OK- the plugin is running correctlyMissing - [Description]- the plugin lacks something essential to function properlyFault - [Description]- a fault has occurred during execution
Webhook Page
One Webhook page is generated per configured webhook, named Webhook 1, Webhook 2, ... up to Webhook N where N is the Webhook Count property. The number of Key/Value rows on each page is determined by the Data Pair Count property.
Webhook Settings
Webhook Path
Controls name: WebhookiPath
Type: Text-Text Edit
Description: URL path the HTTP server listens on for this webhook (for example /door1). The value is auto-sanitized: only [a-zA-Z0-9-_.~/] characters are kept, repeated slashes are collapsed, any trailing slash is removed, and a leading slash is forced.
Webhook URL
Controls name: WebhookiUrl
Type: Text-ComboBox
Description: Read-only combo box listing the full URL for this webhook on every active network interface. Use it as a quick reference for the address external systems should call.
Webhook Hold
Controls name: WebhookiHold
Type: Button-Toggle
Description: When true (default), the Value controls keep the last received value until the next matching request. When false, the Value controls are cleared after each request, producing a pulse-like behavior.
Webhook LED
Controls name: WebhookiLed
Type: Indicator-Led
Description: Flashes for 0.4 s each time a request hits this webhook's Path, providing visual confirmation that the request was received.
Webhook Data
Controls name: WebhookiData
Type: Indicator-Text
Description: Pretty-printed JSON dump of the full parameter set from the most recent request (query string and JSON body merged).
Webhook Response
Controls name: WebhookiResponse
Type: Text-Text Edit
Description: Optional response body returned to the caller for every request that matches this webhook. The current value of the control at the moment the request is received is sent back synchronously - the plugin does not wait for the control to update. If the value parses as JSON, it is returned with Content-Type: application/json; otherwise it is returned as text/plain; charset=utf-8. Leave empty to return 200 OK with no body.
Webhook Response Code
Controls name: WebhookiCode
Type: Text-ComboBox
Choices: Auto, 200, 201, 202, 204, 400, 401, 403, 404, 409, 422, 429, 500, 502, 503
Description: Per-webhook HTTP status code returned to the caller. Auto (default) uses the normal behavior (200 for successful webhook response, or 200 with no body when Webhook Response is empty). Selecting any explicit code forces that status for this webhook. This applies whether Webhook Response is empty (status only) or contains a body (status + body).
Key / Value Pairs
Webhook Key
Controls name: WebhookiKeyj
Type: Text-Text Edit
Description: Key name to extract from incoming request parameters. When the incoming payload contains a matching key, its value is forwarded to the corresponding Value control.
Webhook Value
Controls name: WebhookiValuej
Type: Indicator-Text
Description: Value extracted from the most recent request for the matching Key. Behavior depends on the Hold toggle: held until next request when true, cleared after each request when false.
Setup Page
Connection
Interface
Controls name: Interface
Type: Text-ComboBox
Description: Selects which network interface (IP address) the server accepts requests on (Host-header based filtering). Any accepts requests on all interfaces. The list refreshes from Network.Interfaces().
Port
Controls name: Port
Type: Knob-Integer
Description: TCP port the HTTP server listens on. Allowed range is 8000 to 9999. Default 8001.
Token
Controls name: Token
Type: Text-Text Edit
Description: Bearer token required in the Authorization: Bearer <token> header of every incoming request. Leave blank to disable authentication.
Built-in Endpoints
Design Status Endpoint
Controls name: DesignStatus
Type: Button-Toggle
Description: Enables the built-in /status endpoint. When true (default), GET or POST requests to <ip>:<port>/status return the result of Design.GetStatus() encoded as JSON. When false, the endpoint returns 404 Not Found.
Design Inventory Endpoint
Controls name: DesignInventory
Type: Button-Toggle
Description: Enables the built-in /inventory endpoint. When true (default), GET or POST requests to <ip>:<port>/inventory return the result of Design.GetInventory() encoded as JSON. When false, the endpoint returns 404 Not Found.
Named Component Endpoint
Controls name: NamedComponent
Type: Button-Toggle
Description: Enables the built-in /namedcomponent action endpoint. When true, external systems can drive any Q-SYS Named Component control by posting Component, Controls, Action, Value, and optional RampTime parameters. This bypasses complicated schematic connections and long path addresses by interacting with another component directly through the name assigned to it in the Q-SYS Named Component library. The endpoint path is <ip>:<port>/namedcomponent.
Named Controls Endpoint
Controls name: NamedControls
Type: Button-Toggle
Description: Enables the built-in /namedcontrols action endpoint. When true, external systems can drive any Q-SYS Named Control by posting Controls, Action, Value, and optional RampTime parameters. This bypasses complicated schematic connections and long path-address patterns by interacting with the built-in Q-SYS Named Controls library. The endpoint path is <ip>:<port>/namedcontrols.
Appendix
User-defined Webhook Request Examples
POST http://<core_ip>:8001/door1 Body: {"state":"open","by":"alice"}
GET http://<core_ip>:8001/door1?state=open&by=alice
Both forms produce the same effect. If the JSON body and the query string define the same key, the body value wins.
Built-in Endpoints Reference
Statuses endpoints
GET|POST /status- returnsDesign.GetStatus()as JSON. Gated by theDesignStatustoggle (enabled by default).GET|POST /inventory- returnsDesign.GetInventory()as JSON. Gated by theDesignInventorytoggle (enabled by default).
Action endpoints
/namedcomponent- drives any control of a Q-SYS Named Component/namedcontrols- drives a Q-SYS Named Control (top-level)
Both endpoints accept the same parameter set (except Component, which is only used by /namedcomponent) and can be called with GET (query string), POST (JSON body), or a mix of both. When the same key appears in both, the JSON body wins.
Parameters
Parameter | Required | Notes |
|---|---|---|
|
| The Code Name of the target Named Component |
| yes | The name of the control inside the component, or the Named Control identifier |
| yes | One of |
| required except for | The new value to assign. Type is coerced from string based on |
| optional, only meaningful with | Seconds. Sets the control's |
Action semantics
Trigger- fires the control's trigger event. NoValuerequired.SetString- assignsValueas a string to the control.SetPosition- assignsValue(number 0.0 - 1.0) as the control's normalized position. UsesRampTimeif provided.SetValue- assignsValue(number) as the control's raw value.SetBoolean- assignsValue(trueorfalse, as string or boolean) to the control.Toggle- inverts the control's current boolean state. NoValuerequired.
Request format examples
POST with JSON body (recommended):
POST http://<core_ip>:8001/namedcomponent
Content-Type: application/json
{
"Component": "Main_Mixer",
"Controls": "input.1.gain",
"Action": "SetPosition",
"Value": "0.75",
"RampTime": "2"
}GET with query string (all parameters URL-encoded):
GET http://<core_ip>:8001/namedcomponent?Component=Main_Mixer&Controls=input.1.gain&Action=SetPosition&Value=0.75&RampTime=2More examples
Trigger a snapshot recall on a Named Component:
POST http://<core_ip>:8001/namedcomponent
{ "Component": "Snapshots", "Controls": "load.1", "Action": "Trigger" }Mute a Named Control:
POST http://<core_ip>:8001/namedcontrols
{ "Controls": "Room_Mute", "Action": "SetBoolean", "Value": "true" }Toggle a Named Control:
GET http://<core_ip>:8001/namedcontrols?Controls=Room_Mute&Action=ToggleSet a string on a Named Component control:
GET http://<core_ip>:8001/namedcomponent?Component=Signage&Controls=message&Action=SetString&Value=Hello%20WorldResponses
200 OK- the action was dispatched successfully404 Not Found- the endpoint is disabled, the component/control does not exist, or the action failed (e.g.Actionis unknown,Valueis missing or of the wrong type)401 Unauthorized- theTokenproperty is set and the request is missing or has the wrongAuthorization: Bearer <token>header
No JSON payload is returned by these action endpoints; only the HTTP status code matters.
How to Name a Component
Q-SYS Designer
9.4and lower: while in Offline mode, simply rename the component block.Q-SYS Designer
9.5and higher: while in Offline mode, set theCode Nameproperty in the Properties pane to the desired name, and make sureScript Accessis set toScriptorAll.The
Code Nameproperty is the identifier the plugin uses to reach the component.
Control Pins
PIN NAME | VALUE | STRING | POSITION | PINS AVAILABLE |
|---|---|---|---|---|
Status | - | - | - | - |
Status | 0 | (Status String) | 0 | Output |
Setup | - | - | - | - |
Interface | - | (String) | - | Input / Output |
Port | 8000-9999 | (Integer) | 0-1 | Input / Output |
Token | - | (String) | - | Input / Output |
Design Status Endpoint | 0 | false | 0 | Input / Output |
Design Inventory Endpoint | 0 | false | 0 | Input / Output |
Named Component Endpoint | 0 | false | 0 | Input / Output |
Named Controls Endpoint | 0 | false | 0 | Input / Output |
Webhook 1 | - | - | - | - |
Webhook 1 Path | - | (String) | - | Input / Output |
Webhook 1 URL | - | (String) | - | Output |
Webhook 1 Hold | 0 | false | 0 | Input / Output |
Webhook 1 LED | 0 | false | 0 | Output |
Webhook 1 Data | - | (JSON String) | - | Output |
Webhook 1 Response | - | (String) | - | Input / Output |
Webhook 1 Key 1 | - | (String) | - | Input / Output |
Webhook 1 Value 1 | - | (String) | - | Output |
Webhook 1 Key 2 | - | (String) | - | Input / Output |
Webhook 1 Value 2 | - | (String) | - | Output |
Webhook 1 Key 3 | - | (String) | - | Input / Output |
Webhook 1 Value 3 | - | (String) | - | Output |
Webhook 1 Key 4 | - | (String) | - | Input / Output |
Webhook 1 Value 4 | - | (String) | - | Output |
Additional Key/Value pin pairs (5 to N) follow the same pattern based on the Data Pair Count property (4 to 32). Additional Webhook blocks (Webhook 2 to Webhook 6) follow the same Path / URL / Hold / LED / Data / Key / Value pattern and are generated based on the Webhook Count property.
support@ad-da.ca | Copyright © 2026 AD-DA.CA