Docs / Open API & Integrations / Actions API Reference

Actions API Reference

actions.proto, service ActionsService. This is the recommended default surface for integrations — see Overview & Setup if you haven't read that yet (connection details, auth, and the h2c cleartext requirement all apply here).

ActionsService mirrors Aura Mixer's internal Action Registry — the same catalog Hotkeys and Automation rules bind to. Every action is addressed by a stable, namespaced string ID (e.g. mixer.setMuted), never by a raw index, so your integration doesn't need to know anything about how channels/buses are laid out internally.

Target IDs

Actions that operate on a specific entity (a channel, bus, group, or the main bus) take a project-local ID — an opaque string like ch_53f465c2, stable for the lifetime of that entity but not predictable or guessable. Get real IDs from StreamState (which pairs every ID with its current display name) — don't hardcode them.

If an ID doesn't resolve to anything (the entity was deleted since you last looked it up), InvokeAction returns ok: false rather than throwing — it never guesses.

RPCs

ListActions

rpc ListActions(google.protobuf.Empty) returns (ActionList);

message ActionDefinition {
    string id = 1;                        // e.g. "mixer.setMuted"
    string display_name = 2;               // e.g. "Mute / Unmute"
    string category = 3;                   // e.g. "Mixer", "Routing", "Scenes", "Engine"
    bool requires_target = 4;               // needs target_id to do anything
    string target_kind = 5;                 // "mixable" | "bus" | "channel" — see below
    bool requires_secondary_target = 6;     // needs secondary_target_id too (two-entity actions)
    bool uses_value = 7;                    // reads an absolute numeric value
    bool uses_delta = 8;                    // reads a relative step
    bool supports_momentary = 9;            // has a natural on/off (fire true on press, false on release)
}
message ActionList { repeated ActionDefinition actions = 1; }

Call this once at startup to build your own picker — don't hardcode the action catalog, it can grow. target_kind tells you what a target_id for that action must reference: "mixable" (any channel, group, output bus, or the main bus — anything with mute/solo/fader), "bus" (output buses and the main bus only), or "channel" (input channels only) — plus four narrower kinds for type-specific transport, each restricted to exactly that channel/bus type so a picker can't offer, say, a microphone channel for a Player action: "playerChannel", "generatorChannel", "soundboardChannel", and "recorderBus" (which, unlike plain "bus", never includes the main bus — it can never be a Recorder).

InvokeAction

rpc InvokeAction(InvokeActionRequest) returns (InvokeActionResponse);

message InvokeActionRequest {
    string action_id = 1;
    string target_id = 2;               // required if the action's requires_target is true
    string secondary_target_id = 3;     // required if requires_secondary_target is true
    optional float value = 4;           // for actions with uses_value
    optional float delta = 5;           // for actions with uses_delta
    optional bool flag = 6;             // explicit on/off; omit to toggle (for actions that support it)
}
message InvokeActionResponse {
    bool ok = 1;
    string error = 2;   // human-readable, empty when ok
}

InvokeActionResponse.ok is your real success signal — check it. ok: false happens for an unknown action_id, or a requires_target action called without a target_id; it is not a gRPC-level error, so a try/catch around the call alone won't catch it.

flag matters for actions that supports_momentary: pass flag: true on button-down and flag: false on button-up for a press-and-hold behavior (e.g. push-to-mute); omit flag entirely for a simple toggle-on-press.

StreamState

rpc StreamState(google.protobuf.Empty) returns (stream MixerStateSnapshot);

message MixerEntityState {
    string id = 1;
    string name = 2;          // current display name — cache this for your UI, don't re-resolve per-call
    string kind = 3;           // "channel" | "group" | "output" | "mainBus"
    bool muted = 4;
    bool soloed = 5;
    float fader_db = 6;
}
message MixerStateSnapshot { repeated MixerEntityState entities = 1; }

Opens a long-lived stream. You get one snapshot immediately on connect (covering every channel/group/output/main-bus currently in the project), then a fresh full snapshot every time anything changes — not a delta. This is the right way to:

  • Discover valid target_ids (paired with their current names) instead of guessing.
  • Drive a button icon's mute/solo/fader-level indicator live.

If you only care about specific entities, just filter the snapshot client-side — the list is small (typically well under a hundred entities) and this keeps the protocol simple in both directions.

Built-in action catalog

As of this writing, ListActions returns these 24 actions (call it yourself for the authoritative, current list — this table is a snapshot):

IDDisplay nameCategoryTargetValue/DeltaMomentary
mixer.setMutedMute / UnmuteMixermixable
mixer.setSoloedSolo / UnsoloMixermixable
mixer.setFaderDbSet Fader (absolute)Mixermixablevalue (dB)
mixer.adjustFaderDbAdjust Fader (relative)Mixermixabledelta (dB)
mixer.clearAllSoloClear All SoloMixer
player.playPlayer: PlayMixerplayerChannel
player.pausePlayer: PauseMixerplayerChannel
player.stopPlayer: StopMixerplayerChannel
player.togglePlayPausePlayer: Play / PauseMixerplayerChannel
player.nextPlayer: Next TrackMixerplayerChannel
player.previousPlayer: Previous TrackMixerplayerChannel
player.cycleRepeatModePlayer: Cycle Repeat Mode (Off → All → One)MixerplayerChannel
player.toggleShufflePlayer: Toggle ShuffleMixerplayerChannel
generator.cycleWaveformGenerator: Cycle Waveform (Sine → Pink → White → Click)MixergeneratorChannel
soundboard.stopChannelSoundboard: StopMixersoundboardChannel
bus.startRecordingBus: Start RecordingRecorderrecorderBus
bus.stopRecordingBus: Stop RecordingRecorderrecorderBus
bus.toggleRecordingBus: Start / Stop RecordingRecorderrecorderBus
bus.setRouteActiveBus Route On/OffRoutingbus + secondary bus
channel.setSendActiveChannel→Bus Send On/OffRoutingchannel + secondary bus
channel.setSendDbChannel→Bus Send LevelRoutingchannel + secondary busvalue (dB)
scene.recallRecall SceneScenesvalue (scene index)
engine.toggleRunningStart / Stop EngineEngine

mixer.adjustFaderDb's result is clamped to [-96, +12] dB server-side, so repeated deltas (e.g. from a held key) can't run a fader out of range.

soundboard.triggerPad (trigger a specific pad, requires_secondary_target: true — the pad's own id, supports_momentary: true for Hold-to-play pads) exists in the engine and ListActions does return it, but it's not practical to drive from an integration today: a pad's id only exists inside one specific Soundboard channel's own pad list, and neither StreamState nor the Mixer API currently exposes pad ids or names — there's no way to discover a valid secondary_target_id remotely. soundboard.stopChannel (no secondary target, listed above) is the one Soundboard action that's actually usable over the API right now.

Example call sequence

  1. ListActions once, at startup — build your picker / cache the catalog.
  2. StreamState — keep it open for the life of your integration; use it to resolve names → IDs and to keep any live indicators (button icon state) current.
  3. InvokeAction on whatever triggers your integration (button press, etc.) — check ok.

See the worked example for this end-to-end in Node.js.

stuck? ask on Discord
An unhandled error has occurred. Reload 🗙

Rejoining the server...

Rejoin failed... trying again in seconds.

Failed to rejoin.
Please retry or reload the page.

The session has been paused by the server.

Failed to resume the session.
Please retry or reload the page.