# Effects Server API

The Effects Server runs on `http://localhost:3001` and exposes REST endpoints and a WebSocket for real-time GPU shader control.

## Base URL

```
http://localhost:3001
```

***

## Effects

### Apply an Effect

```
POST /effects/apply
```

**Request body**

```json
{
  "effectId": "colorkey",
  "params": {
    "keyColor": "#00FF00",
    "tolerance": 0.3,
    "edgeSoftness": 0.05
  }
}
```

**Response** `200 OK`

```json
{ "status": "applied", "effectId": "colorkey" }
```

### Clear All Effects

```
POST /effects/apply
```

**Request body**

```json
{ "clear": true }
```

***

## Color Keying

### Apply Color Key

```
POST /effects/colorkey
```

**Request body**

| Field          | Type   | Description                      |
| -------------- | ------ | -------------------------------- |
| `keyColor`     | string | Hex colour to remove (`#RRGGBB`) |
| `tolerance`    | float  | Match tolerance 0–1              |
| `edgeSoftness` | float  | Edge blend softness 0–1          |

### Remove Color Key

```
DELETE /effects/colorkey
```

***

## Luminance

### Apply Luminance Adjustment

```
POST /effects/luminance
```

**Request body**

| Field        | Type  | Range       | Default |
| ------------ | ----- | ----------- | ------- |
| `brightness` | float | -1.0 to 1.0 | 0.0     |
| `contrast`   | float | -1.0 to 1.0 | 0.0     |
| `gamma`      | float | 0.1 to 4.0  | 1.0     |

### Remove Luminance

```
DELETE /effects/luminance
```

***

## Shader Uniforms

### Set a Uniform Value

```
POST /uniform
```

**Request body**

```json
{
  "effectId": "myShader",
  "uniform": "uIntensity",
  "value": 0.75
}
```

Sets a named GLSL uniform on the specified effect. The engine applies the value on the next render frame.

***

## Data Tracks

### List Data Tracks

```
GET /datatrack
```

### Create / Update a Data Track

```
POST /datatrack
```

**Request body**

```json
{
  "id": "dimmer1",
  "name": "Dimmer 1",
  "outputType": "osc",
  "destination": "192.168.1.10:8000",
  "oscAddress": "/fixture/1/dimmer",
  "interpolation": "linear",
  "keyframes": [
    { "time": 0, "value": 0 },
    { "time": 5, "value": 255 },
    { "time": 10, "value": 0 }
  ]
}
```

### Delete a Data Track

```
DELETE /datatrack/:trackId
```

### Calculate Value at Frame

```
POST /datatrack/:trackId/value
```

**Request body**

```json
{ "frame": 150, "fps": 30 }
```

***

## WebSocket Connections

### Effect State Sync

```
ws://localhost:3001/effects
```

All connected clients receive a message whenever the effect state changes:

```json
{
  "type": "effectsUpdate",
  "effects": { "colorkey": { ... }, "luminance": { ... } }
}
```

### Data Track Updates

```
ws://localhost:3001/datatrack
```

Broadcasts the current value of all data tracks on every frame.

***

## Property Keyframes

### Get All Keyframes

```
GET /property-keyframes
```

Returns all keyframes across all tracks and properties.

### Add or Update Keyframes

```
POST /property-keyframes
```

**Request body**

```json
{
  "trackId": "clip_uid_opacity",
  "property": "opacity",
  "keyframes": [
    { "time": 0.0, "value": 0.0, "interpolation": "linear" },
    { "time": 2.0, "value": 1.0, "interpolation": "ease-out" }
  ]
}
```

**Interpolation types:** `linear`, `ease-in`, `ease-out`, `ease-in-out`, `step`

**Response** `200 OK`

```json
{ "status": "saved", "trackId": "clip_uid_opacity", "count": 2 }
```

### Delete Keyframes for a Track

```
DELETE /property-keyframes/:trackId
```

Removes all keyframes for the given track ID.

***

## Preview

### Get Preview Settings

```
GET /preview
```

### Configure Preview

```
POST /preview
```

**Request body**

```json
{
  "compositionId": "comp_main",
  "enabled": true,
  "width": 480,
  "height": 270
}
```

### Disable Preview

```
DELETE /preview/:compositionId
```

***

## Monitor

### Get Active Connections

```
GET /monitor/connections
```

Returns a list of all active HTTP and WebSocket connections with type, remote address, status, and duration.

### Get Host Information

```
GET /monitor/host
```

Returns hostname, platform, Node.js version, and all network interface addresses.

**Response sample**

```json
{
  "hostname": "SHOW-PC-01",
  "platform": "win32",
  "interfaces": {
    "Ethernet": [{ "address": "192.168.1.5", "family": "IPv4" }]
  }
}
```

### Add Monitor Event

```
POST /monitor/events
```

**Request body**

```json
{
  "type": "custom",
  "message": "External trigger received",
  "source": "192.168.1.100"
}
```

***

## Project Export

### Export Project to ZIP

```
POST /project/export
```

Packages the current project and all referenced media into a ZIP archive.

**Rate limit:** 5 requests per minute.

**Response:** `application/zip` binary stream — the browser downloads it automatically.

**Error responses:**

| Status | Meaning                               |
| ------ | ------------------------------------- |
| `429`  | Rate limit exceeded — wait 60 seconds |
| `404`  | No project is currently loaded        |
| `500`  | Export failed — check server log      |


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.exaplay.one/v3/developer-reference/effects-server-api.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
