Skip to main content

Effects & Palettes API Reference

This page gives the REST routes for effects and palette colors. A control surface uses them to load and unload effects, and to read and switch the effects a show already has. It also uses them to read the colors of a palette, and it does not request an image. These routes work with the Browse & Inputs API behind the Stream Deck Plugin. Like those routes, they are not specific to one control surface, and any HTTP client can use them.

For the rest of the API, see the interactive REST API Reference. For setup and authentication, see the REST API guide.


Conventions

TopicDetail
Base URLhttp://<host>:<port>/api/v1 — default http://127.0.0.1:8080/api/v1.
License ProThe REST server runs only with an activated license. Without a license, the server does not start, so a client gets a connection error and not an HTTP status. See What requires a license.
AuthenticationOptional. If you set an API key, send X-API-Key: <key> or Authorization: Bearer <key> on every request.
Name matchingThe match on a name is case-insensitive. A space, an underscore, and a hyphen are equivalent, and FXCanvas ignores whitespace at the start and the end.
Error body{ "error": true, "code": "<CODE>", "message": "<text>" }, with an extra details object on ITEM_NOT_FOUND.

Two lists, two identities

This page has two different lists of effects. The most frequent mistake is to select the wrong list.

ListRouteIdentified byUse it when
The catalogGET /api/v1/effects/availableEffect typeYou build a fixed set of controls, with one key for each effect a user can select.
The chainGET /api/v1/effects1-based chain positionYou mirror the Effects panel in its current state.

Almost every control surface must use the catalog. A key bound to blur still means Blur after you change the chain order. The same key also means Blur on a machine with no chain, and this is what makes a layout you can ship. Add an effect with POST /api/v1/effects/add, and remove it with POST /api/v1/effects/remove. One press loads the effect, and the next press unloads it.

The chain is the right list for one specific slot. Two copies of the same effect at different chain positions are legal, and only the position identifies each one. toggle and enabled work on positions. They change visibility, and they do not add or remove an effect.

Three more facts are important before you build a client:

There is no single "current" effect. FXCanvas can load and enable any number of effects at once. Therefore /effects/current returns a list, and a row of keys can show several effects as active. Sources and palettes are different, because only one of them is current.

There are no effect thumbnails. An effect transforms the output of the effect before it, and it is not an image in itself. A preview needs an input image, and FXCanvas cannot invent one. Show the name of the effect and its loaded or enabled state instead.

Effect presets are separate. To load a saved effect preset, use GET /api/v1/actions and POST /api/v1/actions/{id} in the Effect Presets category. These routes do not load presets.


GET /api/v1/effects/available

This route returns every effect type this build can load. Each item also states whether the chain holds an effect of that type.

Method: GETPath: /api/v1/effects/available

This route takes no parameters. GET /api/v1/capabilities reports it as the effects-catalogue feature, so a client can identify an older FXCanvas build that does not serve this route.

Example success response

GET /api/v1/effects/available200 OK

{
"count": 4,
"inChainCount": 1,
"items": [
{ "type": "blur", "name": "blur", "inChain": true },
{ "type": "fisheye", "name": "fisheye", "inChain": false },
{ "type": "kaleidoscope", "name": "kaleidoscope", "inChain": false },
{ "type": "strobe", "name": "strobe", "inChain": false }
]
}

inChain is true when the chain holds at least one effect of that type. The enabled state does not change it. A key that shows inChain means "this effect is in my chain", and add and remove switch that state.

Error codes

StatuscodeCondition
503CHAIN_BUSYFXCanvas cannot read the chain within 1000 ms. Send the request again.

POST /api/v1/effects/add

This route loads an effect type into the chain.

Method: POSTPath: /api/v1/effects/add

FXCanvas adds the effect to the end of the chain, and the effect starts enabled. The Effects panel does the same.

Parameters

FieldTypeRequiredMeaning
typestringYesEffect type from /effects/available. FXCanvas matches the name as described in Conventions.
idempotentbooleanNo, defaults to falseWhen true, FXCanvas returns a type already in the chain unchanged, and adds no second copy.

Set idempotent for a client that can repeat a request. Examples are a repeated press, or two presses at the same time. The result is then "this effect is loaded", and not a second copy in the chain.

Example success response

POST /api/v1/effects/add with { "type": "kaleidoscope", "idempotent": true }200 OK

{
"success": true,
"index": 2,
"name": "Kaleidoscope",
"type": "kaleidoscope",
"enabled": true,
"presetId": ""
}

The response describes the chain slot of the new effect. A caller that also shows the chain does not need to read the chain again.

Error codes

StatuscodeCondition
400INVALID_REQUESTThe body is not JSON, or carries no type.
403EFFECT_LIMIT_REACHEDThe chain is at the effect ceiling for this license tier. FXCanvas added nothing.
404ITEM_NOT_FOUNDNo effect type of that name is installed. details.available lists the installed types.
500EFFECT_LOAD_FAILEDThe type is installed, but FXCanvas cannot create the effect.
503CHAIN_BUSYFXCanvas cannot update the chain within 1000 ms. Nothing changed. Send the request again.

POST /api/v1/effects/remove

This route unloads an effect from the chain.

Method: POSTPath: /api/v1/effects/remove

Parameters

Send exactly one of these in a JSON body:

FieldTypeMeaning
typestringEffect type. FXCanvas removes the first effect of that type. A chain with two of them keeps the second.
indexintegerChain position, 1-based. Use this field for one specific slot in the chain.

If you send both fields, type wins.

Example success response

POST /api/v1/effects/remove with { "type": "kaleidoscope" }200 OK

{
"success": true,
"removed": {
"index": 2,
"name": "Kaleidoscope",
"type": "kaleidoscope",
"enabled": true,
"presetId": ""
}
}

removed describes the effect before FXCanvas removed it. Every position after it moves down by one, as in the Effects panel.

Error codes

StatuscodeCondition
400INVALID_REQUESTThe body is not JSON, or carries neither type nor index.
404ITEM_NOT_FOUNDThe chain holds no effect of that type, or nothing is at that position.
503CHAIN_BUSYFXCanvas cannot update the chain within 1000 ms. Nothing changed. Send the request again.

GET /api/v1/effects

This route returns every effect in the chain, in chain order.

Method: GETPath: /api/v1/effects

This route takes no parameters. One request gives everything for a whole row of keys: the label from name, and the active indicator from enabled. A client does not need one request for each effect.

Example success response

GET /api/v1/effects200 OK

{
"count": 3,
"enabledCount": 2,
"items": [
{
"index": 1,
"name": "Blur",
"type": "blur",
"enabled": true,
"presetId": ""
},
{
"index": 2,
"name": "Fisheye",
"type": "fisheye",
"enabled": false,
"presetId": ""
},
{
"index": 3,
"name": "Warm Trails",
"type": "trail",
"enabled": true,
"presetId": "effect-preset-7"
}
]
}

name is the display name of the effect, and type is its lowercase type identifier. A response gives "name": "Blur" with "type": "blur". Both values work where a route asks for a name.

items is always an array. A show with no effects returns [], and count and enabledCount are both 0. presetId has a value only for an effect that comes from a saved preset.

Error codes

StatuscodeCondition
503CHAIN_BUSYFXCanvas cannot read the chain within 1000 ms. FXCanvas reads and edits the chain on the render thread, so a read cannot race an edit in the Effects panel. A heavy frame can delay a read. Send the request again.

GET /api/v1/effects/current

This route returns the effects in the chain that are enabled.

Method: GETPath: /api/v1/effects/current

This route takes no parameters. The response has the same shape as GET /api/v1/effects, with the enabled effects only. Each item keeps its position in the full chain, so the index values can have gaps.

Example success response

GET /api/v1/effects/current200 OK

{
"count": 2,
"items": [
{ "index": 1, "name": "Blur", "type": "blur", "enabled": true, "presetId": "" },
{ "index": 3, "name": "Warm Trails", "type": "trail", "enabled": true, "presetId": "effect-preset-7" }
]
}

Error codes

StatuscodeCondition
503CHAIN_BUSYFXCanvas cannot read the chain within 1000 ms. Send the request again.

POST /api/v1/effects/toggle

This route inverts the visibility of one loaded effect.

Method: POSTPath: /api/v1/effects/toggle

FXCanvas adds no effect and removes no effect. Only the enabled state of the effect changes.

Parameters

Send exactly one of these in a JSON body:

FieldTypeRangeMeaning
indexinteger1 to the number of loaded effectsChain position.
namestringFXCanvas matches this value against the display name of the effect first, then against the effect type. Both "Blur" (the display name) and "blur" (the type) work.

If you send both fields, name wins.

Example success response

POST /api/v1/effects/toggle with { "index": 2 }200 OK

{
"success": true,
"current": {
"index": 2,
"name": "Fisheye",
"type": "fisheye",
"enabled": true,
"presetId": ""
}
}

current reports the state after the change. A caller does not need a second request to see the result.

Error codes

StatuscodeCondition
400INVALID_REQUESTThe body is not JSON, or carries neither index nor name.
404ITEM_NOT_FOUNDNo effect is at that position, or no loaded effect has that name. For a name miss, details.available lists the loaded effect names. For an index miss, details.min and details.max give the range.
503CHAIN_BUSYFXCanvas cannot update the chain within 1000 ms. Nothing changed. Send the request again.

POST /api/v1/effects/enabled

This route sets the visibility of one loaded effect.

Method: POSTPath: /api/v1/effects/enabled

This route is idempotent. It is the right route for a control surface that syncs its keys again at intervals. The route sets the state you send, so it cannot invert an effect by accident. A repeated toggle can.

Parameters

FieldTypeRequiredMeaning
enabledbooleanYesThe state to set.
indexintegerOne of the twoChain position, 1-based.
namestringOne of the twoDisplay name or effect type. FXCanvas matches it in the same way.

Example success response

POST /api/v1/effects/enabled with { "name": "Blur", "enabled": false }200 OK

{
"success": true,
"current": {
"index": 1,
"name": "Blur",
"type": "blur",
"enabled": false,
"presetId": ""
}
}

Error codes

StatuscodeCondition
400INVALID_REQUESTThe body is not JSON, has no boolean enabled field, or carries neither index nor name.
404ITEM_NOT_FOUNDNo effect is at that position, or no loaded effect has that name.
503CHAIN_BUSYFXCanvas cannot update the chain within 1000 ms. Nothing changed. Send the request again.

Palette colors

GET /api/v1/palettes and GET /api/v1/palettes/current both report the colors of a palette. A control surface can then draw its own swatches, and it does not request an image.

Method: GETPath: /api/v1/palettes/current

Example success response

GET /api/v1/palettes/current200 OK

{
"index": 3,
"id": "palette-ocean",
"name": "Ocean Blues",
"colors": ["#0B2C4A", "#1B6AC9", "#3FA9F5", "#A9DCF7"]
}

colors is in palette order, as #RRGGBB strings. The response gives no alpha value, because palette swatches are opaque.

Error codes

StatuscodeCondition
404NO_CURRENT_PALETTENo palette is selected.

When to use the rendered preview instead

GET /api/v1/thumbnails/palette/{id} returns a rendered image of the same palette. The size is 32–512 pixels, as png or jpg. The ETag follows the content version of the palette, so an edit invalidates every cached copy. Use colors for your own key image, and the thumbnail for the image that FXCanvas renders. For the parameters, see the thumbnail routes.


  • Browse & Inputs API Reference — How to walk content as folders, and how to activate an item
  • REST API — How to enable the server, authentication, and name matching
  • Stream Deck Plugin — The control surface that these routes serve
  • Effects — What the effects chain is, and how the Effects panel works
  • Palettes — How to create and edit palettes