2023.2 EN DE

    Show / Hide Table of Contents

    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

    width75

    Configuration

    • By starting the application, a default config file is created next to the executable if no config file found
    • Set values in config.json before 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.
    address string Address this client can be reached at, as the host observes it on its connection. Empty on a client that has not registered with a host yet. Together with restPort this is what lets a caller address another client's own API without being told where it runs.
    restPort int Port this client serves its REST API on, or 0 when the REST API is switched off for it (or has not started yet).
    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.

    Chapter object

    The chapter endpoints (/chapters, /chapters/{id}, /experiences/{id}/chapters) describe a chapter with this object. A chapter is an ordered group of slides; every slide in an experience belongs to exactly one chapter.

    Field Type Description
    name string Display name of the chapter.
    id string Unique ID of the chapter.
    slides array The chapter's slides, in order, each as { "name", "id", "isFavorite" } (same shape as /slides, without timerSeconds).

    X-Manager object

    The /x-manager endpoint describes the X-Manager this X-Creator is connected to with this object:

    Field Type Description
    url string Address of the X-Manager as configured in X-Creator, a full base URL with scheme, host and port (e.g. https://x-manager.example.com:3001) rather than a bare IP.
    version string Release version of the X-Manager, e.g. 2023.2.279 (develop). Empty until the X-Manager has been reachable at least once.
    publicFeatureEnabled bool Whether the public feature is enabled on the X-Manager. Read from the X-Manager's own settings, not inferred from whether X-Creator currently holds a public token. false until the X-Manager has been reachable at least once.

    version and publicFeatureEnabled are read from the X-Manager when the backend connection comes up and re-read on every reconnect, so a setting changed on the X-Manager is picked up without restarting X-Creator. Every X-Creator reads them for itself, so the answer does not depend on which instance is asked.

    Version object

    The /version endpoint describes the running build with this object:

    Field Type Description
    version string Application version including the build number, e.g. 2023.2.279.
    branch string Branch the build came from, e.g. develop or staging. Empty for a production build, and for a locally made build, which carries no build manifest.
    commit string Commit the build came from. Empty when no build manifest is present.
    buildTime string When the build was made. Empty when no build manifest is present.
    buildKind string production, or agent-api for a build carrying the extra unauthenticated agent interface. Decided at compile time, so a production build answers this too rather than the question only being answerable where that interface exists.

    Config object

    The /config endpoint describes the X-Creator configuration this instance runs under with this object. Everything here is per instance: each X-Creator is served its own configuration, so ask the instance you mean rather than the host.

    Field Type Description
    configId string ID of the X-Creator configuration, as registered on the X-Manager. Reflects whatever was last selected (welcome screen or POST /config), not re-fetched by this endpoint.
    configName string Name of that configuration. This is the same value the Client object reports as clientName. Same caveat as configId.
    environmentId string ID of the environment the configuration belongs to.
    environmentName string Name of that environment. Empty until the X-Manager has served this instance its client info at least once, since only the X-Manager knows the name behind the id.
    source string Whether environmentId/environmentName came from the X-Manager this run: x-manager when it served them, cached when it could not be reached and the previous run's values were kept, unknown before either has happened. Does not describe configId/configName, which this endpoint never re-fetches.

    source is worth reading before trusting the environment fields: startup deliberately carries on with the previous run's environment info when the X-Manager is unreachable, and it looks no different from a freshly-served value once in place. Since both requests are keyed only by client id, resolved independently server-side, a cached environment is not just possibly stale but possibly wrong for what this instance is actually running — the X-Manager can have reassigned this client to a different environment in the meantime, and the license/config the app is running under would already reflect that even though environmentName here still doesn't.

    Config entry object

    The /configs endpoint describes each X-Creator configuration the connected X-Manager offers with this object. Unlike the Config object this says nothing about what the asked instance is running — it is the list to pick from, not a report about the instance.

    Field Type Description
    configId string ID of the X-Creator configuration, as registered on the X-Manager. Not accepted by POST /config, and not stable across a reimport.
    configName string Name of that configuration. This, paired with environmentName, is what POST /config selects by.
    environmentId string ID of the environment the configuration belongs to.
    environmentName string Name of that environment. Needed alongside configName to address a configuration, since names are only unique within one environment.

    Environment entry object

    The /environments endpoint describes each environment the connected X-Manager holds with this object. It exists so an environment name can be turned into the id the administrator operations take.

    Field Type Description
    environmentId string ID of the environment on the X-Manager. Not stable across a reimport of its content.
    environmentName string Name of that environment.

    This is not the same set as the environments appearing in GET /configs: that only reaches environments which already have a configuration, and an environment with none is exactly what a configuration is usually moved to.

    License object

    The /licenses/{licenseId}/environment endpoint describes the license it changed with this object. It is deliberately a small part of what the X-Manager holds about a license: the key and the hardware id it is bound to stay on the X-Manager and are never served here.

    Field Type Description
    licenseId string ID of the license on the X-Manager.
    licenseName string Name of that license.
    environmentId string ID of the environment the license now applies to.
    environmentName string Name of that environment. Looked up separately when the license document does not carry it, and null if that lookup failed.
    isValid boolean Whether the license covers the environment it now belongs to. false does not mean the change failed — the move succeeds either way, but an X-Creator on that environment then fails to start with an invalid-license error.

    Log manifest object

    The /logs endpoint answers with a zip rather than JSON, and writes this object into it as manifest.json. Its point is that triage can tell a complete bundle from one with a gap: which machine the logs came from, which window was asked for, and which files answered it — rather than working with whatever files happen to be in the archive.

    Field Type Description
    clientId string ID of the X-Creator configuration the exporting instance runs under, so a bundle stays identifiable once it is off the test network.
    clientName string Name of that configuration.
    generatedAt string When the bundle was produced, ISO 8601 in UTC — as is every other time in this object, whatever the request used.
    windowFrom string Start of the requested window, null when none was given.
    windowTo string End of the requested window, null when none was given.
    limit integer The requested file limit, 0 when none was given.
    fileCount integer Number of files listed.
    totalSizeBytes integer Their combined size on disk.
    files array One entry per selected file, oldest first.

    Each entry in files:

    Field Type Description
    name string File name, which is also its name inside the zip.
    startTime string When the run that wrote the file started, read from the file name. null if the name does not carry one.
    lastWriteTime string When the file was last written to. This, not startTime, is what says how far into the window the file reaches.
    sizeBytes integer Size on disk at selection time.
    stillOpen boolean true for the file the application is writing to right now — the most interesting file in a bundle, and the only one that can still grow after the export.
    error string Why a listed file is not in the zip, for instance because log rotation replaced it while the bundle was being built. null for every file that made it in.

    A file listed with an error is the case the manifest exists for: the bundle is short one file and says so, instead of looking complete.

    Administrator operations

    Two endpoints — POST /configs/{configId}/environment and POST /licenses/{licenseId}/environment — do not change this instance but the X-Manager's own records, so that an automated setup can move an X-Creator between environments without anyone opening the X-Manager UI.

    Because of that they need more than this API's bearer token: the X-Creator forwards them to the X-Manager under the credential of the user logged in on this instance, and the X-Manager only accepts them from a member of its Administrators group. There is no second credential to fall back on, so an instance that is not logged in as such a user answers 403 and names which of these applies:

    • it accesses the X-Manager with an API token, which is minted without administrator rights,
    • no X-Manager user is logged in on it — including when it runs in public mode,
    • or the logged-in user is not in the Administrators group.

    A 403 can also come back from the X-Manager itself after that check passed, for instance when the user's group membership changed since the login.

    /alive

    GET

    Description
    Is the REST server alive.

    Responses

    Code Description
    200 Successful response
    401 Authentication token not valid

    /x-manager

    GET

    Description
    Returns the X-Manager this X-Creator is connected to as an X-Manager object.

    Responses

    Code Description Schema
    200 X-Manager document object
    401 Authentication token not valid

    /version

    GET

    Description
    Returns the running build as a Version object. Answers which of several installed builds is actually running on this machine, which cannot be told from the outside once a production and an agent-API build of the same version sit side by side.

    Responses

    Code Description Schema
    200 Version document object
    401 Authentication token not valid

    /config

    GET

    Description
    Returns the X-Creator configuration this instance runs under as a Config object.

    Responses

    Code Description Schema
    200 Config document object
    401 Authentication token not valid

    POST

    Description
    Selects the X-Creator configuration this instance runs under, taking effect on the next start. Returns the resulting Config object.

    Selection is by name, not by id, because the X-Manager mints new ids whenever its content is reimported while names stay put. environmentName is required as well, since configuration names are only unique within one environment. The name pair is resolved against the X-Manager's own list, so this needs the X-Manager to be reachable — a 500 means it was not, and is a different problem from the 404 that says the name does not exist there.

    This endpoint deliberately does not restart the application. Nothing is torn down at the moment of the call; the caller decides when the restart happens. Until it does, the instance keeps running under its previous configuration while reporting the new one.

    Request body

    { "configName": "Visualisation Left", "environmentName": "Showroom" }
    

    Responses

    Code Description Schema
    200 Config document, as resolved object
    400 configName or environmentName missing
    401 Authentication token not valid
    404 No configuration with that name in that environment on this X-Manager
    500 The configuration list could not be read from the X-Manager

    /configs

    GET

    Description
    Returns every X-Creator configuration the connected X-Manager offers, as a list of Config entry objects — the names POST /config can be given.

    The list comes from the X-Manager itself rather than from anything held locally, so this needs it to be reachable and a 500 means it was not. It describes what this X-Manager offers, not what any instance is running; use GET /config for the latter.

    Responses

    Code Description Schema
    200 Config entry documents object
    401 Authentication token not valid
    500 The configuration list could not be read from the X-Manager

    /environments

    GET

    Description
    Returns every environment the connected X-Manager holds, as a list of Environment entry objects — where the environmentId for POST /configs/{configId}/environment and POST /licenses/{licenseId}/environment comes from.

    Unlike those two this is a plain read and needs no administrator credential, only whatever the X-Manager itself requires to list environments; a 403 means it refused the read.

    Responses

    Code Description Schema
    200 Environment entry documents object
    401 Authentication token not valid
    403 The X-Manager refused to serve the environment list
    500 The environment list could not be read from the X-Manager

    /licenses

    GET

    Description
    Returns every license the connected X-Manager holds, as a list of License objects — where the licenseId for POST /licenses/{licenseId}/environment comes from, and which shows which environment is currently licensed.

    Like GET /environments this is a plain read and needs no administrator credential. License keys are not part of the response.

    Responses

    Code Description Schema
    200 License documents object
    401 Authentication token not valid
    403 The X-Manager refused to serve the license list
    500 The license list could not be read from the X-Manager

    /configs/{configId}/environment

    POST

    Description
    Moves an X-Creator configuration to another environment on the X-Manager, so that instances running this configuration are served the new environment's settings from their next start. Returns the updated Config entry object.

    This is an administrator operation. Unlike POST /config it does not change what the asked instance runs — it changes a record on the X-Manager, which every instance on that configuration then follows.

    Addressing is by id rather than by name, because a configuration and an environment are each identified by id in the X-Manager's own records. Read the configuration ids from GET /configs and the environment ids from GET /environments; neither survives a reimport of the X-Manager's content.

    A configuration belongs to exactly one environment, which is why this is a separate operation rather than a field on POST /config. The environment must already be licensed, or an X-Creator moved onto it fails to start — see POST /licenses/{licenseId}/environment.

    environmentName in the response is resolved separately, because the X-Manager's answer to this call names the environment by id only. It is null if that lookup failed — the move itself has already happened by then and is not reported as failed over it.

    Request body

    { "environmentId": "6634f1b2c8a94d0012ab34cd" }
    

    Responses

    Code Description Schema
    200 Config entry document, as updated object
    400 configId or environmentId missing
    401 Authentication token not valid
    403 No X-Manager administrator credential on this instance, or the X-Manager refused the change
    404 No configuration with that id on this X-Manager
    500 The X-Manager could not be reached, or answered unreadably

    /licenses/{licenseId}/environment

    POST

    Description
    Moves a license to another environment on the X-Manager. Returns the updated License object.

    This is an administrator operation. An environment without a license cannot be started on: an X-Creator moved to it fails during startup with an invalid-license error rather than a configuration error.

    A license record carries one environment, so this re-points it rather than copying it: the environment it was on loses this license. Whether that environment ends up unlicensed depends on whether another license still covers it — an installation can hold several. A trial is the exception: there is only one per installation, so it cannot cover two environments and has to be moved between them.

    The license does not have to be deactivated first — posting the new environment id is enough, and the license comes back valid. The license key is never part of the request or the response.

    Request body

    { "environmentId": "6634f1b2c8a94d0012ab34cd" }
    

    Responses

    Code Description Schema
    200 License document, as updated object
    400 licenseId or environmentId missing
    401 Authentication token not valid
    403 No X-Manager administrator credential on this instance, or the X-Manager refused the change
    404 No license with that id on this X-Manager
    500 The X-Manager could not be reached, or answered unreadably

    /logs

    GET

    Description
    Returns this machine's log files for a time window as a zip, with a Log manifest object inside it as manifest.json. Meant to be called at the end of a test run, from the machine that produced the logs — by triage time they have rotated away or the machine has been reused.

    Files are selected by overlap, not by name. A log file is named for the time its run started, so a run that lasted all morning holds entries hours later than the time in its name; a file counts as in the window when it was still being written at or after from, and its run began at or before to. The file the application is currently writing to is included like any other and flagged in the manifest, and buffered entries are flushed to disk first so the last seconds before the call are in the bundle. Expect several files per machine when a test case restarts the application.

    Everything is optional: no parameters at all returns every log file the machine has kept — roughly the last 100 runs.

    Query parameters

    Name Type Description
    from string Start of the window. Either an ISO 8601 timestamp (without an offset it is read as the machine's local time) or a duration back from now: 10d, 12h, 30m, 45s. Omitted, the window is open at the start.
    to string End of the window, same formats. Omitted, the window is open at the end.
    limit integer Keep at most this many files, newest first. Omitted, every matching file is included.

    Examples

    Request Returns
    GET /logs Every retained log file.
    GET /logs?from=10d The last ten days.
    GET /logs?limit=1 The current log file only.
    GET /logs?from=2026-09-16T08:00:00&to=2026-09-16T12:00:00 Everything overlapping that morning.

    Responses

    Code Description Schema
    200 Zip archive of the selected log files plus manifest.json. A window matching nothing is still a 200 with a manifest listing no files, not a 404. binary
    400 from, to or limit not readable
    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/{id}/chapters

    GET

    Description
    Returns a list of all chapters, each with its slides, 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. See Chapter object.

    Responses

    Code Description Schema
    200 Chapter 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

    /chapters

    GET

    Description
    Returns a list of all chapters, each with its slides, from the current experience. See Chapter object.

    Responses

    Code Description Schema
    200 Chapter documents — empty list if no experience is loaded object
    401 Authentication token not valid

    /chapters/{id}

    GET

    Description
    Returns the chapter with a given ID from the current experience. See Chapter object.

    Responses

    Code Description Schema
    200 Chapter document object
    401 Authentication token not valid
    404 No chapter with specified ID found in the current experience

    /chapters/{id}/activate

    POST

    Description
    Loads the first slide of the chapter with a given ID from the current experience.

    Responses

    Code Description
    200 Successful response
    401 Authentication token not valid
    404 No chapter with specified ID found in the current experience
    409 Chapter has no slides

    /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.

    
    ☀
    ☾
    Back to top
    Generated by DocFX
    ☀
    ☾