REST API Settings
Description
REST API allows external tools to control X-Creator using HTTP requests (including CORS support). All API requests have to be prefixed with the IP address of the X-Creator, the configured port, "api" and the API version. Example of a valid API request: http://192.168.0.1:9696/api/v1/experiences
Environment Configuration
Enable the REST API module so it is available for the Environment.
X-Creator Configuration
Enable the REST API module for one X-Creator in the Environment that should receive the REST requests and use the IP of this X-Creator when sending the requests.
Port
The port on which the requests are received
Authentication
Enables to define a Bearer Token (case sensitive) that must be added to the header of each request to access all endpoints.
'Bearer' has to be capitalized in the authorization header.
X-Web Control

Configuration
- By starting the application, a default config file is created next to the executable if no config file found
- Set values in
config.jsonbefore starting the application to start with desired configuration (IPs, ports and crestron endpoints)
Warning
Do not position the executable inside of a directory with admin rights (recommend directory e.g.: C:\Users\Public\Documents)
Config Sample File
The following sample can be used as a starting point and copy-pasted to the config.json file. It contains all default values.
{
"WEB_CONTROL_PORT": "9697",
"CREATOR_REST_API_IP": "http://192.168.0.100",
"CREATOR_REST_API_PORT": "9696",
"PIN_CODE": "9999",
"CRESTRON_IP": "http://192.168.0.200",
"CRESTRON_HOME_PATH": "/home",
"CRESTRON_X_PANEL_URL": "https://192.168.1.11/shell-template/index.html?ipId=11"
}
API Documentation
All endpoints require a valid bearer token in the Authorization header when Authentication is enabled; every response below can additionally return 401 in that case.
Error response body
Every error response (4xx/5xx) carries a JSON body with the status code and a human-readable reason, matching the shape of successful responses:
{ "status": 404, "message": "No experience with specified ID found" }
Media layer object
The layer endpoints (/slides/{id}/layers, /slides/current/layers, /media/{mediaId}/layer) describe each media layer with this object. Transform values are normalized rather than in pixels:
| Field | Type | Description |
|---|---|---|
mediaLayerId |
string | Unique ID of the layer. |
mediaId |
string | ID of the media the layer displays. |
mediaType |
string | Media type, e.g. Image, Video, Text, Web, AssetBundle, Shape. |
name |
string | Display name of the media. |
position |
{ "x", "y" } |
Normalized position. x spans the canvas width, y spans the canvas height (0–1 covers the canvas). |
size |
{ "x", "y" } |
Normalized size. Both x (width) and y (height) are relative to the canvas width. |
rotation |
number | Rotation in degrees. |
crop |
{ "x", "y", "z", "w" } |
Crop fractions (0–1) per edge: x=top, y=bottom, z=left, w=right. Also adjusts position/size to match, unless those are set in the same request. |
visible |
bool | Whether the layer is shown. |
alpha |
number | Opacity, 0–1. |
zOrder |
int | Stacking order; higher values are drawn in front. Relative only — not guaranteed 0-based or contiguous, and values differ between the active slide (normalized) and other slides (raw stored values). |
locked |
bool | Whether the layer is locked against edits. |
fixedAspectRatio |
bool | Whether width and height stay locked to the media's aspect ratio. |
fullscreen |
bool | Whether the layer fills the whole canvas. |
sectionFullscreen |
bool | Whether the layer fills its section. Mutually exclusive with fullscreen. |
backgroundColor |
{ "r", "g", "b", "a" } |
Background color behind the media, each channel 0–1. |
isStatic |
bool | Whether the layer is static (persists across every slide). Toggling this also re-maps layerGroup to/from its Static* variant. |
layerGroup |
string | Layer group: Background, Regular, Foreground, StaticBackground, StaticRegular, StaticForeground. Setting a non-static base group (e.g. Foreground) while the layer is static resolves to its Static* counterpart automatically. System-assigned groups (Widget, VideoSource, Audio) can't be set through the API. |
control |
object or null |
Media-type-specific control state snapshot, shaped per mediaType — see Media control object. null for media types with no control operations (e.g. Image, AssetBundle, VideoMatrix). |
The canvas dimensions needed to convert normalized values to pixels are returned by /experiences/current as canvasWidth and canvasHeight. Individual layer properties can be updated live with PATCH /layers/{id}; media-type-specific operations (play/pause, page navigation, etc.) are covered in Media Control Endpoints.
Media control object
Every response that includes a Media layer object nests the layer's current control state under control, shaped according to its mediaType. To read it for a single layer, use GET /layers/{id}.
mediaType |
Fields |
|---|---|
Video |
isPlaying (bool), playMode (string: Loop, ResetAfterPlay, PlayToEnd, ForwardSlideWhenFinished), volume (0–1), muted (bool), position (0–1, normalized over duration), duration (seconds) |
Audio |
isPlaying (bool), loop (bool), volume (0–1), muted (bool), position (0–1, normalized over duration), duration (seconds) |
duration is the media's total length in seconds, so position * duration gives the elapsed time — enough to show and seek to a real timecode. It is 0 when the length isn't known (media without duration metadata).
| Pdf | currentPage (int, 0-based), interaction (bool) |
| Web | webUrl (string) |
| Ndi | volume (0–1), muted (bool), colorFormat (string: BGRX_BGRA, UYVY_BGRA, RGBX_RGBA, UYVY_RGBA, Fastest), bandwidth (string: Highest, Lowest, AudioOnly) |
| Text | text (string), fontName (string), fontSize (number), fontColor ({ "r", "g", "b", "a" }), alignment (string, Unity TextAnchor member, e.g. UpperLeft), interaction (bool) |
| Shape | color ({ "r", "g", "b", "a" }) |
| everything else | null — no control operations are exposed for this media type |
Client object
The client endpoints (/clients, /clients/current, /clients/{id}) describe a connected client with this object, sourced from the server's internal client-info state rather than a separate schema per client type:
| Field | Type | Description |
|---|---|---|
clientId |
string | Unique ID of the client. |
clientName |
string | Display name of the client, or empty if unset. |
clientType |
string | Client role, e.g. Visualisation, Control. |
connectionId |
int | Internal network connection handle, mainly useful for debugging. Not stable across reconnects. |
syncEnabled |
bool | Whether this client follows another client's slide navigation. |
experienceId |
string | ID of the experience this client has joined, or empty if none. |
slideId |
string | ID of the slide this client currently has active, or empty if none. |
slideLoadState |
string | How far the client has got loading slideId, e.g. None, Loading, Settled. |
autoPlayDelayMs |
int | Configured auto-forward delay for this client in milliseconds, or 0 if auto-play is off. |
downloadProgress |
int | Media download progress, 0–100. |
ndi |
object | enabled (bool), mediaIds (array of string) — whether NDI is enabled on this client and which media it currently sources over NDI. |
hardwareInfo |
object | deviceType (string, Unity DeviceType member), deviceName (string), systemMemorySize (int, MB), processorFrequency (int, MHz), graphicsMemorySize (int, MB). |
The list is only as current as the server's own broadcast — a Control client reads the same continuously-synced copy as the host, so all three endpoints work the same regardless of which client answers the request.
/alive
GET
Description
Is the REST server alive.
Responses
| Code | Description |
|---|---|
| 200 | Successful response |
| 401 | Authentication token not valid |
/experiences
GET
Description
Returns a list of all experiences with names, IDs and if set as favorites.
Responses
| Code | Description | Schema |
|---|---|---|
| 200 | Experience documents | object |
| 401 | Authentication token not valid |
/experiences/{id}
GET
Description
Loads the experience with a given ID. If the experience already has a client with sync enabled, this client
joins with sync forced off, matching the app's own join behavior — this avoids disturbing clients already
synced to that experience.
Responses
| Code | Description |
|---|---|
| 200 | Successful response |
| 401 | Authentication token not valid |
| 404 | No experience with specified ID found |
/experiences/{id}/slides
GET
Description
Returns a list of all slides (name, ID, favorite) for the experience with the given ID, without joining it. If this X-Creator hasn't loaded that experience yet, it is fetched from X-Manager on demand. Only available on a X-Creator running the Host role.
Responses
| Code | Description | Schema |
|---|---|---|
| 200 | Slide documents | object |
| 401 | Authentication token not valid | |
| 404 | No experience with specified ID found | |
| 500 | Fetching the experience from X-Manager failed | |
| 501 | This X-Creator is not running the Host role |
/experiences/exit
GET
Description
Leave current experience. Has no effect if no experience is currently loaded.
Responses
| Code | Description |
|---|---|
| 200 | Successful response |
| 401 | Authentication token not valid |
/experiences/current
GET
Description
Returns name and ID of the current experience, plus the canvas pixel dimensions (canvasWidth, canvasHeight) used to convert normalized Media layer object values to pixels.
Responses
| Code | Description | Schema |
|---|---|---|
| 200 | Experience document (name, id, isFavorite, canvasWidth, canvasHeight) |
object |
| 401 | Authentication token not valid | |
| 404 | No experience loaded |
/clients
GET
Description
Returns every connected client as a Client object.
Responses
| Code | Description | Schema |
|---|---|---|
| 200 | Client documents | object |
| 401 | Authentication token not valid |
/clients/current
GET
Description
Returns the client answering this request as a Client object.
Responses
| Code | Description | Schema |
|---|---|---|
| 200 | Client document | object |
| 401 | Authentication token not valid |
/clients/{id}
GET
Description
Returns the client with the given ID as a Client object.
Responses
| Code | Description | Schema |
|---|---|---|
| 200 | Client document | object |
| 401 | Authentication token not valid | |
| 404 | No client with specified ID found |
/slides
GET
Description
Returns a list of all slides from the current experience.
Responses
| Code | Description | Schema |
|---|---|---|
| 200 | Slide documents (name, id, isFavorite, timerSeconds) — empty list if no experience is loaded |
object |
| 401 | Authentication token not valid |
/slides/{id}
GET
Description
Loads the slide with a given ID from the current experience.
Responses
| Code | Description |
|---|---|
| 200 | Successful response |
| 401 | Authentication token not valid |
| 404 | No slide with specified ID found in the current experience |
DELETE
Description
Deletes the slide with a given ID from the current experience. If it is the currently active slide, a neighboring slide is activated first.
Responses
| Code | Description |
|---|---|
| 200 | Successful response |
| 401 | Authentication token not valid |
| 404 | No slide with specified ID found in the current experience |
| 409 | Cannot delete the last remaining slide |
/slides/{id}/layers
GET
Description
Returns the media layers of the slide with the given ID from the current experience as Media layer objects.
Responses
| Code | Description | Schema |
|---|---|---|
| 200 | Media layer documents | object |
| 401 | Authentication token not valid | |
| 404 | No slide with specified ID found in the current experience |
/slides/next
GET
Description
Loads the next slide from the current experience. Several calls arriving in quick succession are
collected into a single move covering all of them, so the intermediate slides are skipped rather than
each being loaded in turn — see Slide navigation is a request.
Responses
| Code | Description |
|---|---|
| 200 | Successful response |
| 401 | Authentication token not valid |
| 409 | No next slide available |
/slides/previous
GET
Description
Loads the previous slide from the current experience. Several calls arriving in quick succession are
collected into a single move covering all of them, so the intermediate slides are skipped rather than
each being loaded in turn — see Slide navigation is a request.
Responses
| Code | Description |
|---|---|
| 200 | Successful response |
| 401 | Authentication token not valid |
| 409 | No previous slide available |
/slides/current
GET
Description
Returns name, ID and favorite flag of the current slide.
Responses
| Code | Description | Schema |
|---|---|---|
| 200 | Slide document (name, id, isFavorite, timerSeconds) |
object |
| 401 | Authentication token not valid | |
| 404 | No slide currently active |
/slides/current/layers
GET
Description
Returns the media layers of the currently active slide as Media layer objects.
Responses
| Code | Description | Schema |
|---|---|---|
| 200 | Media layer documents | object |
| 401 | Authentication token not valid | |
| 404 | No slide currently active |
/slides/save
POST
Description
Saves the currently active slide, capturing its current media layers and controls.
Responses
| Code | Description |
|---|---|
| 200 | Successful response |
| 401 | Authentication token not valid |
| 403 | Saving slides is disabled via X-Manager |
| 404 | No slide currently active |
/slides/{id}/rename
POST
Description
Renames the slide with the given ID. The new name is sent as a JSON body: { "name": "New name" }.
Responses
| Code | Description |
|---|---|
| 200 | Successful response |
| 400 | Missing name in request body |
| 401 | Authentication token not valid |
| 404 | No slide with specified ID found in the current experience |
/slides/{id}/timer
POST
Description
Sets how long the slide with the given ID is shown before auto-forward moves on. The duration is sent as whole seconds in a JSON body: { "seconds": 30 }. Zero removes the timer, which is what DELETE does. There is no upper bound. Setting the timer of the currently active slide restarts its countdown from the new duration.
Responses
| Code | Description |
|---|---|
| 200 | Successful response |
| 400 | seconds is negative |
| 401 | Authentication token not valid |
| 404 | No slide with specified ID found in the current experience |
DELETE
Description
Removes the timer from the slide with the given ID, so it is no longer shown for a duration of its own. The auto-forward delay still applies to it afterwards.
Responses
| Code | Description |
|---|---|
| 200 | Successful response |
| 401 | Authentication token not valid |
| 404 | No slide with specified ID found in the current experience |
/auto-forward
GET
Description
Returns the auto-forward countdown of the current experience.
The countdown does not tick over the network — it is only reported when it starts, stops, is paused or resumed. A caller wanting a live readout counts remainingMs down against its own clock from the moment it read this, exactly as the app's own timer ring does.
| Field | Type | Description |
|---|---|---|
slideId |
string | The slide the countdown is running for, empty when none is running. |
running |
bool | Whether the countdown is running rather than paused. |
durationMs |
int | How long the countdown runs in total. |
remainingMs |
int | How much was left when this was read. |
delaySeconds |
number | The auto-forward delay applied to slides without a timer of their own, 0 when auto-forward is off. Fractional when it comes from a client configuration that is not a whole number of seconds. |
Responses
| Code | Description | Schema |
|---|---|---|
| 200 | Auto-forward document | object |
| 401 | Authentication token not valid |
/auto-forward/delay
POST
Description
Sets the auto-forward delay of the current experience, which applies to every slide that carries no timer of its own. The delay is sent as whole seconds in a JSON body: { "seconds": 10 }. Zero switches auto-forward off — there is no separate enable/disable and no remembered previous value. There is no upper bound.
The delay set here overrides the one taken from client configuration for as long as the server runs; a restart falls back to client configuration, and nothing is written to any configuration file. A countdown already running for a slide without its own timer restarts from the new delay.
Responses
| Code | Description |
|---|---|
| 200 | Successful response |
| 400 | seconds is negative |
| 401 | Authentication token not valid |
| 404 | Not in an experience |
/auto-forward/pause
POST
Description
Pauses the running countdown. Nobody owns the pause: the app's own timer ring resumes it just as readily as /auto-forward/resume does. Calling it on an already-paused countdown succeeds and changes nothing.
Pausing is allowed while the presentation is frozen. Freeze already holds the countdown, and pausing on top of it is what keeps the countdown from resuming when freeze is lifted.
Responses
| Code | Description |
|---|---|
| 200 | Successful response |
| 401 | Authentication token not valid |
| 409 | No auto-forward countdown is running |
/auto-forward/resume
POST
Description
Resumes the paused countdown, which carries on from where it stopped rather than starting over. Calling it on an already-running countdown succeeds and changes nothing.
Responses
| Code | Description |
|---|---|
| 200 | Successful response |
| 401 | Authentication token not valid |
| 409 | No auto-forward countdown is running, or the presentation is frozen |
/media
GET
Description
Returns every media item known to the currently joined experience, independent of slide or layer placement.
Responses
| Code | Description | Schema |
|---|---|---|
| 200 | Media documents (mediaId, mediaType, name) |
object |
| 401 | Authentication token not valid |
/media/{mediaId}/layer
GET
Description
Creates a new media layer for the given media on the currently active slide, positioned near the center of the visible canvas, and returns the created Media layer object.
Responses
| Code | Description | Schema |
|---|---|---|
| 200 | Media layer document | object |
| 401 | Authentication token not valid | |
| 404 | No media with specified ID found, or no slide currently active |
/layers/{id}
GET
Description
Returns the media layer with the given ID on the currently active slide as a Media layer object, with its current control state nested under control. Use this to refresh a single layer — including a playing video's position — without fetching the whole slide.
Responses
| Code | Description | Schema |
|---|---|---|
| 200 | Media layer document | object |
| 401 | Authentication token not valid | |
| 404 | No slide currently active, or no media layer with specified ID found |
PATCH
Description
Updates individual properties of the media layer with the given ID on the currently active slide. The request body is a JSON object holding any subset of the writable Media layer object fields; only the fields present are applied, the rest stay untouched. Writable fields are position, size, rotation, crop, visible, alpha, zOrder, locked, fullscreen, sectionFullscreen, backgroundColor, isStatic and layerGroup. position, size and crop are sent whole (all their components). fullscreen and sectionFullscreen are mutually exclusive — setting one clears the other.
Request body sample
{
"position": { "x": 0.25, "y": 0.25 },
"size": { "x": 0.5, "y": 0.28 },
"rotation": 90,
"visible": true,
"alpha": 0.8
}
Responses
| Code | Description |
|---|---|
| 200 | Successful response |
| 400 | Request body is empty, contains no known layer properties, or layerGroup is a system-assigned or unknown group |
| 401 | Authentication token not valid |
| 404 | No slide currently active, or no media layer with specified ID found |
DELETE
Description
Deletes the media layer with the given ID from the currently active slide, including its control state.
Responses
| Code | Description |
|---|---|
| 200 | Successful response |
| 401 | Authentication token not valid |
| 404 | No slide currently active, or no media layer with specified ID found |
/shortcuts/{name}
GET
Description
Returns the current state of a shortcut that has readable state. {name} is matched case-insensitively. Only ForceWindowFocus supports this — MouseCursor and ShowWelcomeScreen are pure toggles with nothing to read back.
Response body sample
{ "enabled": true }
Responses
| Code | Description | Schema |
|---|---|---|
| 200 | Current state | object |
| 400 | {name} is not ForceWindowFocus |
|
| 401 | Authentication token not valid | |
| 404 | The force-focus watcher isn't active on this instance (editor, non-Windows, or server role) |
POST
Description
Fires an app-side shortcut, exactly as pressing its key combination on the X-Creator would. {name} is matched case-insensitively. Only these three shortcuts are exposed:
{name} |
Key combination | Effect |
|---|---|---|
MouseCursor |
Ctrl + M |
Shows or hides the mouse cursor. |
ShowWelcomeScreen |
Ctrl + W |
Shows or hides the welcome screen. |
ForceWindowFocus |
Alt + Shift + W |
Turns forcing focus on the X-Creator window on or off. |
MouseCursor and ShowWelcomeScreen are toggles that report no state, so this endpoint can only flip them. ForceWindowFocus is the exception — read its resulting state back with GET /shortcuts/ForceWindowFocus above. No experience needs to be joined.
Responses
| Code | Description |
|---|---|
| 200 | Successful response |
| 400 | Unknown shortcut name, or a shortcut that cannot be triggered remotely |
| 401 | Authentication token not valid |
Media Control Endpoints
All routes below are POST /v1/layers/{id}/<path>, where {id} is a mediaLayerId, and return 200 on success with no body, or the same 400/401/404 codes as other layer routes (400 when the layer's mediaType doesn't support the operation, 404 when the layer doesn't exist). To read the resulting state back, use GET /layers/{id}.
Scope — some operations apply only to the targeted layer instance ("Layer"); others apply to every layer currently showing the same media item ("Media"), e.g. muting one placement of a video mutes all of them.
Volume and mute — the video/volume, audio/volume, and ndi/volume operations also set mute, mirroring the volume slider in the app: a volume above 0 unmutes, a volume of 0 mutes. The app's slider reads as 0 for as long as mute is set, whatever volume is behind it, so a volume change that left mute untouched would not be visible there. Send */mute after */volume if the two need to be set independently.
Video (all Media-scoped)
| Path | Body | Description |
|---|---|---|
video/play |
{ "isPlaying": bool } |
Play or pause at the media's current position; never seeks. |
video/seek |
{ "position": number } |
Seek without changing play state. 0–1, normalized over the media's duration. |
video/mode |
{ "playMode": string } |
Loop, ResetAfterPlay, PlayToEnd, or ForwardSlideWhenFinished. |
video/volume |
{ "volume": number } |
0–1. Also unmutes, or mutes at 0. |
video/mute |
{ "mute": bool } |
Audio (all Layer-scoped)
| Path | Body | Description |
|---|---|---|
audio/play |
{ "play": bool } |
Play or pause at the media's current position; never seeks. |
audio/position |
{ "position": number } |
Seek. 0–1, normalized over the media's duration. |
audio/loop |
{ "loop": bool } |
|
audio/volume |
{ "volume": number } |
0–1. Also unmutes, or mutes at 0. |
audio/mute |
{ "mute": bool } |
Pdf (all Layer-scoped)
| Path | Body | Description |
|---|---|---|
pdf/page |
{ "page": int } |
Jump to a 0-based page number. |
pdf/next-page |
none | Advance one page, clamped to the last page. |
pdf/previous-page |
none | Go back one page, clamped to page 0. |
pdf/first-page |
none | Jump to page 0. |
pdf/last-page |
none | Jump to the last page. |
pdf/interaction |
{ "interaction": bool } |
Toggles direct interaction (scrolling) with the PDF on the layer. |
pdf/enable-scrolling |
none | Re-enables dispatching the current page while scrolling manually. |
Web (Layer-scoped)
| Path | Body | Description |
|---|---|---|
web/url |
{ "url": string } |
Loads a new URL. |
web/navigate |
{ "direction": string } |
Back, Forward, or Reload. |
Ndi (all Media-scoped)
| Path | Body | Description |
|---|---|---|
ndi/volume |
{ "volume": number } |
0–1. Also unmutes, or mutes at 0. |
ndi/mute |
{ "mute": bool } |
|
ndi/color-format |
{ "colorFormat": string } |
BGRX_BGRA, UYVY_BGRA, RGBX_RGBA, UYVY_RGBA, or Fastest. |
ndi/bandwidth |
{ "bandwidth": string } |
Highest, Lowest, or AudioOnly. |
Text
| Path | Scope | Body | Description |
|---|---|---|---|
text/text |
Media | { "text": string } |
|
text/font |
Layer | { "fontName": string } |
|
text/font-size |
Layer | { "fontSize": number } |
|
text/font-color |
Layer | { "fontColor": { "r", "g", "b", "a" } } |
|
text/alignment |
Layer | { "alignment": string } |
Unity TextAnchor member, e.g. UpperLeft, MiddleCenter. |
text/interaction |
Layer | { "interaction": bool } |
Shape (Layer-scoped)
| Path | Body | Description |
|---|---|---|
shape/color |
{ "color": { "r", "g", "b", "a" } } |
Not exposed: freeze (any media type), NDI PTZ (ndi/ptz/*) and camera presets, Web scale/interaction/interaction-authority, and AssetBundle/VideoMatrix controls entirely.
Samples
Load next slide:http://192.168.0.1:9696/api/v1/slides/next
Request all experiences:http://192.168.0.1:9696/api/v1/experiences
Request the media layers of the current slide:http://192.168.0.1:9696/api/v1/slides/current/layers
Update a media layer's opacity (PATCH with a JSON body { "alpha": 0.5 }):http://192.168.0.1:9696/api/v1/layers/<layerId>
Tools
Built-in Test Console
Opening http://<ip>:<port>/ (the same host and port as the API) in a browser serves a built-in interactive console for sending requests and inspecting responses without any external tooling.
Troubleshooting
Response Code 400 - Bad Request
If a required field is missing from the request (e.g. name when renaming a slide), the status code "400 Bad Request" is returned.
Response Code 401 - Unauthorized
If Authentication is enabled and the request is missing a valid Authorization: Bearer <token> header, the status code "401 Unauthorized" is returned.
Response Code 404 - Not Found
If a non-existent endpoint is requested, or the requested experience/slide does not exist (or is not currently loaded), the status code "404 Not Found" is returned.
Response Code 403 - Forbidden
If saving slides has been disabled via X-Manager, the status code "403 Forbidden" is returned.
Response Code 409 - Conflict
If the requested slide navigation cannot be performed in the current situation (e.g. no next/previous slide available, or attempting to delete the last remaining slide), the status code "409 Conflict" is returned.
Slide navigation is a request
Slide navigation (/slides/next, /slides/previous, /slides/{id}/activate) asks the server of the shared experience to change the active slide, so that all clients of that experience show the same slide. A "200" response confirms that the request was accepted and passed on, not that the slide has already changed.
/slides/next and /slides/previous calls that arrive close together are collected into a single move covering all of them — moving three slides ahead by calling /slides/next three times in quick succession loads only the slide arrived at, not each one passed on the way. /slides/{id}/activate is never collected like this, since it already names the exact slide it wants.
The server can still decide not to carry a request out, for example when it is superseded by another activation before it is applied. No slide change happens then, and the response is still "200". Read /slides/current to find out which slide is active now.
Response Code 500 - Internal Server Error
If this error occurs please contact the administrator. The status code "500 Internal Server Error" is returned.
Response Code 501 - Not Implemented
Returned by endpoints that require this X-Creator to be running the Host role (e.g. looking up slides of an experience without joining it) when it isn't.