useLumioAction
Execute a Lumio service action — a named operation on the host platform such as sending a chat message, changing an OBS scene, or emitting a custom event.
Signature
const { execute, data, isLoading, error } = useLumioAction(actionType: LumioActionType);
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
actionType | LumioActionType | Yes | The action type to execute (e.g. "chat:send") |
Return value
| Property | Type | Description |
|---|---|---|
execute | (payload: unknown) => Promise<void> | Call this to trigger the action |
data | unknown | null | Response data from the last execution |
isLoading | boolean | true while the action is in progress |
error | string | null | Error message if the last execution failed |
Supported action types
Chat
| Action type | Required permission | Payload |
|-------------|--------------------|---------||
| "chat:send" | chat:send | { message: string } |
| "chat:delete" | chat:delete | { messageId: string } |
| "chat:ban" | chat:ban | { userId: string; reason?: string } |
| "chat:unban" | chat:ban | { userId: string } |
| "chat:timeout" | chat:ban | { userId: string; durationSeconds: number; reason?: string } |
OBS
| Action type | Required permission | Payload |
|-------------|--------------------|---------||
| "obs:set_scene" | obs:control | { scene: string } |
| "obs:set_source_visible" | obs:control | { source: string; visible: boolean } |
| "obs:start_stream" | obs:control | {} |
| "obs:stop_stream" | obs:control | {} |
| "obs:start_recording" | obs:control | {} |
| "obs:stop_recording" | obs:control | {} |
Spotify
| Action type | Required permission | Payload |
|-------------|--------------------|---------||
| "spotify:play" | spotify:control | {} |
| "spotify:pause" | spotify:control | {} |
| "spotify:skip" | spotify:control | {} |
| "spotify:seek" | spotify:control | { positionMs: number } |
| "spotify:volume" | spotify:control | { volume: number } |
| "spotify:shuffle" | spotify:control | { enabled: boolean } |
| "spotify:repeat" | spotify:control | { mode: "off" \| "track" \| "context" } |
| "spotify:queue_add" | spotify:control | { uri: string } |
Events
| Action type | Required permission | Payload |
|-------------|--------------------|---------||
| "events:emit" | events:write | { type: string; data: unknown } |
Overlay
| Action type | Required permission | Payload |
|-------------|--------------------|---------||
| "overlay:update_layer" | overlays:edit | { layerId: string; visible: boolean } |
Example: Send a chat message
import { Lumio, CompactView, Button, TextField, useLumioAction } from "@zaflun/lumio-sdk";
import { useState } from "react";
function ChatPanel() {
const { execute: sendMessage, isLoading, error } = useLumioAction("chat:send");
const [message, setMessage] = useState("");
const handleSend = async () => {
await sendMessage({ message });
setMessage("");
};
return (
<CompactView title="Send to chat">
<TextField
label="Message"
value={message}
onChange={setMessage}
/>
{error && <Text content={error} variant="muted" />}
<Button
label={isLoading ? "Sending..." : "Send"}
onClick={handleSend}
disabled={isLoading || !message.trim()}
/>
</CompactView>
);
}
Lumio.render(<ChatPanel />, { target: "editor" });
Example: Switch OBS scene
import { Button, Dropdown, useLumioAction } from "@zaflun/lumio-sdk";
import { useState } from "react";
function SceneSwitcher() {
const { execute: setScene, isLoading } = useLumioAction("obs:set_scene");
const [scene, setSceneValue] = useState("Main");
return (
<>
<Dropdown
label="Scene"
value={scene}
options={[
{ value: "Main", label: "Main" },
{ value: "BRB", label: "Be Right Back" },
{ value: "Ending", label: "Ending screen" },
]}
onChange={setSceneValue}
/>
<Button
label="Switch scene"
onClick={() => setScene({ scene })}
disabled={isLoading}
/>
</>
);
}
Declaring permissions
Actions require declaring the corresponding permission in lumio.config.json. Undeclared permissions are rejected at runtime:
{
"permissions": ["chat:send", "obs:set_scene"]
}
Declared permissions are shown to the user during installation, and they must grant consent before the extension can use them.
Notes
- Actions can only be called from the editor surface — not from the layer surface (read-only) and not from the interactive surface (audience-facing)
- The
errorproperty contains a human-readable message when an action fails (e.g., OBS is not connected) - Each action call creates a new entry in the audit log, visible in the extension dashboard