InstantGUI API

Every board has a write token and every widget has a key. Send JSON to /api/v1/boards/<board>/widgets/<key> and every open screen updates within about a second. Creating a board returns both. If a person gave you an existing board's edit link (…/b/<board>/join?key=<edit key>), use its edit key anywhere a token is asked for — see Using an edit link.

Building with an AI agent? One-call board spec, design guide and recommended instructions →Buttons that run things on your computer — the InstantGUI Connector →

Quick start

Code
curl -X POST https://instant-gui.com/api/v1/boards/<board>/widgets/cpu \
  -H "Authorization: Bearer <write token>" \
  -H "Content-Type: application/json" \
  -d '{"value": 73}'

The token can also be sent as ?token= (only for devices that can’t set headers — URLs end up in logs, so prefer the header). Responses are JSON: {"ok": true, "widget": {...}}.

Connector install (agents)

On a shared or headless machine, install the Connector without a login service and in its own directory. Create the token first with POST /boards/<board>/connectors (edit key).

Code
curl -fsSL https://instant-gui.com/connect.sh | INSTANTGUI_HOME=/tmp/ig sh -s -- --board <board> --token <igc_…> --no-service

--no-service skips the start-at-login service (LaunchAgent, systemd user service, scheduled task) — without it the installer registers one. INSTANTGUI_HOME=<dir> puts the install and connect.yml in <dir> instead of ~/.instantgui. Then run node <dir>/bin/instantgui-connect.mjs yourself.

Tip: end a silent command with && echo "backup done: 42 files" so the board shows a summary. A command that prints nothing still logs “(no output)”, and the button still updates its last-run time and count.

Pushing data

A push body is a JSON object, sent with POST. (PUT with a type creates-or-updates the widget; PATCH with layout moves it — see agents.)

{"value": 42}Shorthand: any object without data/append/config keys is merged into the widget’s data.
{"data": {"value": 42, "previous": 40}}Shallow-merge into data. Fields you don’t send are kept.
{"append": {"cpu": 42, "mem": 71}}Append — chart points (x = now), log lines, table rows, checklist items, status updates. Old entries roll off automatically.
{"config": {"title": "CPU", "max": 200}}Change appearance: titles, colors, ranges, thresholds.

Reading controls

Buttons, toggles, sliders, inputs, selects and checklists change when people use them. Read the current state from your script:

Code
curl https://instant-gui.com/api/v1/boards/<board>/widgets/trading \
  -H "Authorization: Bearer <write token>"

# → {"ok": true, "widget": {"key": "trading", "data": {"on": true}, ...}}

GET https://instant-gui.com/api/v1/boards/<board> returns every widget at once.

GET-only push (IoT, Shortcuts, IFTTT)

For devices that can only open a URL. Every query parameter except token becomes a data field.

Code
https://instant-gui.com/api/v1/boards/<board>/widgets/temp/push?token=<write token>&value=22.5

A person can hand you an existing board as an edit link: https://instant-gui.com/b/<board>/join?key=<edit key>. No browser is needed — the <board> in the path is the board id and the key value is the edit key. Send the edit key as a Bearer token on any call: it can read, push, create widgets and change the board. Treat it as a secret.

Code
curl -X POST https://instant-gui.com/api/v1/boards/<board>/widgets/cpu \
  -H "Authorization: Bearer <edit key>" \
  -d '{"value": 73}'

# Want a narrower write token for scripts or devices? Exchange the edit key:
curl -X POST https://instant-gui.com/api/v1/boards/<board>/token -H "Authorization: Bearer <edit key>"
# → {"writeToken": "igw_..."}   (add {"rotate": true} to issue a new one)

Creating boards & widgets

Create a board without an account. Keep the editLink private — it grants edit access.

Code
curl -X POST https://instant-gui.com/api/v1/boards -d '{"title": "My bot", "template": "bot"}'

# → {"board": {"id": "...", "urls": {...}}, "editLink": "...", "writeToken": "igw_..."}

Templates: blankbotserverbusinessiot

Code
curl -X POST https://instant-gui.com/api/v1/boards/<board>/widgets \
  -H "Authorization: Bearer <write token>" \
  -d '{"type": "gauge", "key": "cpu", "config": {"title": "CPU"}, "data": {"value": 12}}'

curl -X DELETE https://instant-gui.com/api/v1/boards/<board>/widgets/cpu -H "Authorization: Bearer <write token>"

Machine-readable schemas for every widget: /api/v1/widgets

For agents: /llms.txt (short guide), /llms-full.txt and the OpenAPI spec

Changing a board in place

Rename it, move a widget, pause a button, embed it: one call each on the board you already built. No need to recreate it or resend the spec.

Code
# Rename the board
curl -s -X PATCH https://instant-gui.com/api/v1/boards/<board> -H 'Authorization: Bearer <credential>' -d '{"title":"Shop live (EU)"}'
# Move or resize a widget (only the fields you send change)
curl -s -X PATCH https://instant-gui.com/api/v1/boards/<board>/widgets/revenue -H 'Authorization: Bearer <credential>' -d '{"layout":{"x":0,"y":0,"w":6,"h":3}}'
# Pause a control: viewers can no longer press it (editors still can). Turn it back on with true
curl -s -X POST https://instant-gui.com/api/v1/boards/<board>/widgets/ads -H 'Authorization: Bearer <credential>' -d '{"config":{"viewersCanUse":false}}'
# Embed a private board: give the site a view token (revocable, read-only)
curl -s -X POST https://instant-gui.com/api/v1/boards/<board>/view-tokens -H 'Authorization: Bearer <credential>' -d '{"label":"Website"}'

Pausing sets config.viewersCanUse to false; editors can still press the control. Embedding a private board needs the view token from the last call.

Pressing a control you just wired

Test a button the way a person would: press it as the editor, then read the result back. Use the action name from GET …/actions.

Code
# 1. Press it as the editor (edit key or write token). Name = <widget key> or <widget key>/<button id>; list the valid names with GET https://instant-gui.com/api/v1/boards/<board>/actions
curl -s -X POST https://instant-gui.com/api/v1/boards/<board>/actions -H 'Authorization: Bearer <credential>' -d '{"action":"backup/run"}'
# → 202 {"ok":true,"event":{"id":"<event id>","action":"backup/run","status":"pending"},"result":"…/actions?events=<event id>"}
# 2. Read the result (poll until status is "done" or "error"; "result" holds the command's output)
curl -s https://instant-gui.com/api/v1/boards/<board>/actions?events=<event id> -H 'Authorization: Bearer <credential>'
# → {"ok":true,"events":[{"id":"<event id>","action":"backup/run","status":"done","result":"backup ok",…}],…}

Viewers can press a control only if its config.viewersCanUse is true; the edit key and write token always can.

Annotations, variables & export

Mark a moment on a widget (e.g. from CI after a deploy) — it shows as a marker on line charts:

Code
curl -X POST https://instant-gui.com/api/v1/boards/<board>/widgets/<key>/annotations \
  -H "Authorization: Bearer <write token>" \
  -d '{"text": "Deployed v2.4"}'

Change a board variable (sources using {{name}} re-fetch immediately):

Code
curl -X PUT https://instant-gui.com/api/v1/boards/<board>/variables/region \
  -H "Authorization: Bearer <write token>" \
  -d '{"value": "eu"}'

GET https://instant-gui.com/api/v1/boards/<board>/widgets/<key>/export downloads a widget’s data as CSV.

Click to filter

Click a bar (anywhere in its column), a pie slice, a line, or a text cell in a table, and the whole page filters by that value — on the live board, in the editor and in embeds. Charts highlight the matching category, slice or series; tables and logs narrow to the rows and lines that contain it; widgets without that value are left alone. The active filters show in a bar at the bottom of the screen: click a value again, press its ✕, or press Esc to clear. Filters are yours alone — nothing is saved and other viewers don’t see them.

Tip: use the same labels everywhere (bar categories, slice names, table cells) so widgets filter each other. In the editor, a widget’s settings open from the settings button in its toolbar (or Enter on the focused card) — clicking the widget uses it.

AI agents (MCP)

InstantGUI is a remote MCP server at https://instant-gui.com/api/mcp (Streamable HTTP). Tools: apply_board_spec, create_board, get_board, add_widget, push_data, update_widget_layout, update_board, lint_board, get_write_token, create_view_token, delete_widget, list_widget_types, get_widget_type, get_design_guide. Guide: /docs/agents.

No token needed to connect — each board you create gets its own write token.

Code
{
  "mcpServers": {
    "instantgui": {
      "url": "https://instant-gui.com/api/mcp"
    }
  }
}

Claude Code: claude mcp add --transport http instantgui https://instant-gui.com/api/mcp

Calling it with plain HTTP? Send both Content-Type: application/json and Accept: application/json, text/event-stream — without that Accept header the server answers 406 and names the missing header. The reply is a server-sent event: a line 'event: message' followed by a line starting 'data: ' that holds the JSON-RPC response; read the JSON from that data line.

MCP over plain HTTP
curl -X POST https://instant-gui.com/api/mcp \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'

Embedding a board

Any board can live inside another site: https://instant-gui.com/e/<board> shows it read-only, live and without app chrome. Private boards need a view token — create one under Share → Embed or with the API (edit key or write token):

Code
curl -X POST https://instant-gui.com/api/v1/boards/<board>/view-tokens -H "Authorization: Bearer <edit key>" -d '{"label": "Website"}'

# → {"embedUrl": "https://instant-gui.com/e/<board>?token=<view token>", "iframe": "<iframe …>", "id": "…"}
HTML
<iframe src="https://instant-gui.com/e/<board>?token=<view token>" style="width:100%;height:640px;border:0" loading="lazy" title="Dashboard"></iframe>
<!-- optional: grow the iframe to its content -->
<script>addEventListener("message", e => { if (e.data?.type === "instantgui:resize") for (const f of document.querySelectorAll("iframe")) if (f.contentWindow === e.source) f.style.height = e.data.height + "px" })</script>

Other options: page=<page title>. The embed posts {type: "instantgui:resize", height} to the parent whenever its height changes (its layout never depends on the frame's height, so auto-sizing can't loop). Revoke a token with DELETE https://instant-gui.com/api/v1/boards/<board>/view-tokens/<id> — the embed stops at once; a wrong or revoked token is always refused.

Make it match your site

The easiest way is the helper script: it sizes the iframe to the board, sends your page's colors and font, and follows your light/dark switch.

HTML
<div data-instantgui-board="<board>" data-token="<view token>" data-inherit-theme></div>
<script src="https://instant-gui.com/embed.js" async></script>

<!-- or, mapping your own design tokens (any CSS color or var(--…), resolved on your page): -->
<div id="board"></div>
<script src="https://instant-gui.com/embed.js"></script>
<script>
  InstantGUI.mount("#board", {
    board: "<board>", token: "<view token>",
    transparent: true, density: "compact", radius: "var(--radius)", font: "inherit",
    colors: { background: "var(--surface)", foreground: "var(--text)", border: "var(--border)",
              primary: "var(--accent)", mutedForeground: "var(--text-muted)" },
  });
</script>

data-inherit-theme / inheritTheme: true reads the page's background (the first non-transparent one behind the mount element), text color, font and common variables (--primary/--accent, --border, --muted-foreground, --radius…) and makes the board transparent. mount() returns {iframe, update(options), refreshTheme(), destroy()}.

Without the script, the same look works as URL parameters (every value is validated — anything else is ignored):

theme
auto (follows the viewer's light/dark), light, dark or a theme id
bg
transparent — no page background or outer padding; the board sits on your card. Or a color.
accent
Buttons, links, focus rings and the first chart series (hex without # works: accent=2557d6)
radius
Widget card corner radius in px, 0–32
density
compact — tighter card padding, no outer padding
font
system, serif, mono or a font-family list your page already loads
c.<token>
One color: background, foreground, card, cardForeground, border, input, primary, primaryForeground, muted, mutedForeground, success, warning, danger, info, chart2…chart6. Unset ones are derived from foreground/background.
defaults=0
Ignore the board's saved embed look (set in Share → Embed → Save as board default, or PATCH https://instant-gui.com/api/v1/boards/<board> with {"embedStyle": {...}})

Retheme live from your page — any subset of the same fields (vars holds the colors; reset: true drops earlier messages first):

Code
iframe.contentWindow.postMessage({
  type: "instantgui:theme", reset: true,
  theme: "dark", bg: "transparent", radius: 14, density: "compact", font: "system",
  vars: { background: "#161a20", foreground: "#eef1f5", border: "#2a313b", primary: "#6d9bff" },
}, "https://instant-gui.com");

The embed posts {type: "instantgui:ready"} when it's listening (send your theme then), {type: "instantgui:resize", height} and {type: "instantgui:scheme", scheme: "light"|"dark"} — with a transparent embed, set the iframe's style.colorScheme to that value, or browsers paint an opaque backdrop behind it (embed.js does this).

The other direction — make your page look like InstantGUI: <link rel="stylesheet" href="https://instant-gui.com/theme.css"> gives you every theme's tokens as --ig-* variables (--ig-background, --ig-card, --ig-primary…), following light/dark or pinned with <html data-ig-theme="midnight">, plus .ig-page, .ig-card and .ig-button.

Embeds that can use controls

Embeds are view-only by default: buttons and toggles show as inactive with a link to the board. For an embed on a page only you can reach (an internal admin tool, your own console), create its token with canUseControls (edit key only) — or switch on Let this embed use controls in the Embed dialog (board owner):

Code
curl -X POST https://instant-gui.com/api/v1/boards/<board>/view-tokens -H "Authorization: Bearer <edit key>" \
  -d '{"label": "Ops console", "canUseControls": true}'
# → {"viewToken": "…", "canUseControls": true, "embedUrl": "https://instant-gui.com/e/<board>?token=…", …}

Presses through that embed act like an editor's on the board's controls — same rate limits, Connector routing and "tap again to confirm" — and are attributed "by embed: Ops console" on the result and in the activity log. Anyone who can load the page with that token can press them, so don't put it on a public page; revoking the token stops it at once.

Webhooks

Set a Webhook URL (https) on any control. When someone uses it we POST:

Code
{
  "event": "widget.interaction",
  "board": "<board>",
  "widget": { "key": "restart", "type": "button" },
  "data": { "presses": 4, "lastPressedAt": 1767225600000 },
  "at": "2026-10-09T12:00:00.000Z"
}

Errors & limits

  • 422 — the body doesn’t fit the widget; details lists each field and what’s wrong.
  • 403 missing or wrong token · 404 unknown board, key or route (always JSON) · 429 slow down. Every error message says what to do next.
  • Up to 150 widgets per board, 20 pages, 256 KB of data per widget, 500 KB per request.

Widget reference

KPI

kpi

A headline number with change vs. previous value and a trend sparkline.

Set the value{"value":48320}
Set value and comparison{"value":48320,"previous":45910}
Data & config fields

Data

FieldTypeDefault
valuenumber | string | null—
previousnumber | string | null—
historynumber[][]
pointsany[][][]

Config

FieldTypeDefault
title
Title
string""
staleAfter
0 = never. Dims the widget and says Stale when no push arrives in time.
integer0
icon
lucide icon name, e.g. wallet, users, cpu
string""
prefix
e.g. $
string""
suffix
e.g. %, ms, users
string""
decimals
Decimals
integer0
compact
Show 12.3K instead of 12,300
booleantrue
higherIsBetter
Higher is better
booleantrue
compareTo
previous push, or the value 1 hour / 1 day / 1 week earlier
"previous" | "1h" | "1d" | "7d""previous"
showSparkline
Show trend
booleantrue
caption
Caption
string""
thresholds
Color thresholds
object[][]

Stat list

stats

Several small numbers side by side, each with an optional change.

Replace all items{"items":[{"label":"Visitors","value":12840,"change":8.1},{"label":"Signups","value":342}]}
Data & config fields

Data

FieldTypeDefault
itemsobject[][]

Config

FieldTypeDefault
title
Title
string""
staleAfter
0 = never. Dims the widget and says Stale when no push arrives in time.
integer0
layout
Layout
"row" | "grid" | "list""row"

Gauge

gauge

A dial for a value within a range — CPU, temperature, utilisation.

Set the value{"value":63}
Data & config fields

Data

FieldTypeDefault
valuenumber | string | null—

Config

FieldTypeDefault
title
Title
string""
staleAfter
0 = never. Dims the widget and says Stale when no push arrives in time.
integer0
min
Min
number0
max
Max
number100
suffix
Suffix
string"%"
decimals
Decimals
integer0
thresholds
Color thresholds
object[][{"above":70,"tone":"warning"},{"above":90,"tone":"danger"}]

Progress

progress

Progress toward a goal, as a bar or ring.

Update progress{"value":27}
Data & config fields

Data

FieldTypeDefault
valuenumber | string—
labelstring""

Config

FieldTypeDefault
title
Title
string""
staleAfter
0 = never. Dims the widget and says Stale when no push arrives in time.
integer0
style
Style
"bar" | "ring""bar"
goal
Goal
number100
unit
Unit
string""
tone
Color
"default" | "success" | "warning" | "danger" | "info""info"

Line chart

lineappend

One or more series over time. Push points and the chart scrolls live.

Append a point to each series (x = now){"append":{"api":912,"web":455}}
Append with an explicit timestamp{"append":{"api":[1767225600000,912]}}
Data & config fields

Data

FieldTypeDefault
series
Usually pushed from code with {"append": {...}}; x values are ms timestamps.
object[][]

Config

FieldTypeDefault
title
Title
string""
staleAfter
0 = never. Dims the widget and says Stale when no push arrives in time.
integer0
xAxis
time = timestamps
"time" | "category""time"
yLabel
Y axis label
string""
maxPoints
Keep last N points
integer200
showLegend
Legend
booleantrue
area
Fill area
booleantrue
smooth
Smooth lines
booleantrue
stacked
Stacked
booleanfalse

Bar chart

bar

Compare values across categories. Vertical or horizontal, grouped or stacked.

Replace the data{"categories":["Mon","Tue","Wed"],"series":[{"name":"Orders","values":[12,19,7]}]}
Data & config fields

Data

FieldTypeDefault
categoriesstring[][]
seriesobject[][]

Config

FieldTypeDefault
title
Title
string""
staleAfter
0 = never. Dims the widget and says Stale when no push arrives in time.
integer0
horizontal
Horizontal
booleanfalse
stacked
Stacked
booleanfalse
yLabel
Value axis label
string""
showLegend
Legend
booleantrue
showValues
Show values on bars
booleanfalse

Pie / donut

pie

Share of a whole across a few categories.

Replace slices{"slices":[{"name":"Yes","value":62},{"name":"No","value":38}]}
Data & config fields

Data

FieldTypeDefault
slicesobject[][]

Config

FieldTypeDefault
title
Title
string""
donut
Donut
booleantrue
showLegend
Legend
booleantrue
showPercent
Show percentages
booleantrue

Scatter

scatterappend

Correlation between two measures, with an optional linear trend line.

Append a point{"append":{"Campaigns":[820,74]}}
Data & config fields

Data

FieldTypeDefault
seriesobject[][]

Config

FieldTypeDefault
title
Title
string""
xLabel
X axis label
string""
yLabel
Y axis label
string""
trendLine
Trend line
booleantrue
maxPoints
Keep last N points
integer1000

Radar

radar

Compare a few profiles across the same set of dimensions.

Set axes and values{"indicators":[{"name":"Tests","max":100},{"name":"Docs","max":100},{"name":"Perf","max":100},{"name":"Security","max":100},{"name":"UX","max":100}],"series":[{"name":"v2.0","values":[95,72,85,88,80]}]}
Data & config fields

Data

FieldTypeDefault
indicatorsobject[][]
seriesobject[]—

Config

FieldTypeDefault
title
Title
string""
showLegend
Legend
booleantrue

Tree / org chart

tree

Hierarchies: org charts, file trees, decision trees.

Replace the tree{"root":{"name":"Root","children":[{"name":"A"},{"name":"B"}]}}
Data & config fields

Data

FieldTypeDefault
rootobject | nullnull

Config

FieldTypeDefault
title
Title
string""
orientation
TB = top→bottom, LR = left→right
"TB" | "LR""TB"
expandDepth
Initially expanded levels
integer3

Table

tableappend

Rows of data with sorting and search. Append rows from scripts.

Append a row{"append":{"Order":"#1046","Customer":"Ken T.","Total":77,"Status":"Paid"}}
Replace all rows{"rows":[{"Order":"#1047","Customer":"Ada L.","Total":54,"Status":"Paid"}]}
Data & config fields

Data

FieldTypeDefault
columns
Each name is a key in the rows. Renaming one here renames it in every row.
string[][]
rows
Stored oldest → newest (the board can show newest first).
object[][]

Config

FieldTypeDefault
title
Title
string""
staleAfter
0 = never. Dims the widget and says Stale when no push arrives in time.
integer0
searchable
Search box
booleantrue
maxRows
Keep last N rows
integer500
newestFirst
Newest rows on top
booleantrue

Live log

logappend

A scrolling feed of events — perfect for bots, jobs and deploys.

Append a line{"append":"Deploy finished in 42s"}
Append with level{"append":{"text":"Disk at 91%","level":"warning"}}
Data & config fields

Data

FieldTypeDefault
entriesobject[][]

Config

FieldTypeDefault
title
Title
string""
staleAfter
0 = never. Dims the widget and says Stale when no push arrives in time.
integer0
maxEntries
Keep last N entries
integer200
showTime
Show timestamps
booleantrue
monospace
Monospace
booleantrue

Checklist

checklistappendinteractive

A shared to-do list. Viewers can tick items when allowed.

Add an item{"append":"Rotate API keys"}
Data & config fields

Data

FieldTypeDefault
itemsobject[][]

Config

FieldTypeDefault
title
Title
string""
viewersCanEdit
Viewers can tick items
booleanfalse
showProgress
Show progress
booleantrue

Kanban board

kanbanappendinteractive

Cards in columns — drag them along as work moves. Scripts can add cards.

Add a card to the first column{"append":"Fix login redirect"}
Add a card to a column{"append":{"title":"Ship v2.1","column":"doing","tag":"release"}}
Data & config fields

Data

FieldTypeDefault
columnsobject[][{"id":"todo","title":"To do"},{"id":"doing","title":"Doing"},{"id":"done","title":"Done"}]
cardsobject[][]

Config

FieldTypeDefault
title
Title
string""
viewersCanEdit
Viewers can move cards
booleanfalse

Timeline

timelineappend

Milestones and events in order — releases, incidents, project history.

Add an event (dated now){"append":"Deployed v2.1"}
Add an event with details{"append":{"title":"Incident resolved","date":"2026-10-09","tone":"success"}}
Data & config fields

Data

FieldTypeDefault
eventsobject[][]

Config

FieldTypeDefault
title
Title
string""
newestFirst
Newest first
booleantrue
maxEvents
Keep last N events
integer100

Team

peopleappend

Who's on the team and who's around — on-call, shifts, presence.

Update one person{"append":{"name":"Maya Cohen","status":"away"}}
Data & config fields

Data

FieldTypeDefault
peopleobject[][]

Config

FieldTypeDefault
title
Title
string""
showOffline
Show offline people
booleantrue

Status board

statusappend

Health of several services at a glance. Update one service at a time.

Update one service{"append":{"name":"API","status":"down","detail":"502 from upstream"}}
Data & config fields

Data

FieldTypeDefault
servicesobject[][]

Config

FieldTypeDefault
title
Title
string""
staleAfter
0 = never. Dims the widget and says Stale when no push arrives in time.
integer0
showSummary
Show summary
booleantrue

Indicator

indicator

One big status light: is the bot running? Is the door open?

Heartbeat{"status":"up","label":"Running"}
Report a failure{"status":"down","label":"Exchange API unreachable"}
Data & config fields

Data

FieldTypeDefault
status"up" | "degraded" | "down" | "unknown" | "maintenance""unknown"
labelstring""

Config

FieldTypeDefault
title
Title
string""
pulse
Pulse when up
booleantrue
staleAfter
0 = never. Great as a heartbeat.
integer0

Button

buttoninteractive

Trigger something: restart a bot, run a job, send a message.

Reset counter{"presses":0}
Data & config fields

Data

FieldTypeDefault
pressesinteger0
lastPressedAtnumber | nullnull

Config

FieldTypeDefault
title
Title
string""
viewersCanUse
Otherwise only editors
booleanfalse
webhookUrl
We POST the new value here (https only)
string""
label
Button label
string"Run"
tone
Color
"default" | "success" | "warning" | "danger" | "info""default"
confirm
Ask for confirmation
booleanfalse

Action buttons

actionsinteractive

Several buttons in one panel — restart, deploy, pause, clear cache.

Reset counters{"counts":{},"lastAction":null,"lastAt":null}
Data & config fields

Data

FieldTypeDefault
lastActionstring | nullnull
lastAtnumber | nullnull
countsobject{}
selectedstring[] | nullnull
statesobject{}
runobject | nullnull

Config

FieldTypeDefault
title
Title
string""
viewersCanUse
Otherwise only editors
booleanfalse
webhookUrl
We POST the new value here (https only)
string""
buttons
Buttons
object[][{"id":"start","label":"Start","tone":"success"},{"id":"stop","label":"Stop","tone":"danger"}]
toggles
Toggles
object[][]

Toggle

toggleinteractive

An on/off switch your script reads — feature flags, pause trading, lights.

Turn on{"on":true}
Data & config fields

Data

FieldTypeDefault
onbooleanfalse

Config

FieldTypeDefault
title
Title
string""
viewersCanUse
Otherwise only editors
booleanfalse
webhookUrl
We POST the new value here (https only)
string""
onLabel
On label
string"On"
offLabel
Off label
string"Off"

Slider

sliderinteractive

Pick a number in a range — thresholds, volume, risk level.

Set value{"value":40}
Data & config fields

Data

FieldTypeDefault
valuenumber50

Config

FieldTypeDefault
title
Title
string""
viewersCanUse
Otherwise only editors
booleanfalse
webhookUrl
We POST the new value here (https only)
string""
min
Min
number0
max
Max
number100
step
Step
number1
suffix
Suffix
string""

Text input

inputinteractive

Send a line of text or a number to your script.

Set value{"value":"hello"}
Data & config fields

Data

FieldTypeDefault
valuestring | number""
submittedAtnumber | nullnull

Config

FieldTypeDefault
title
Title
string""
viewersCanUse
Otherwise only editors
booleanfalse
webhookUrl
We POST the new value here (https only)
string""
placeholder
Placeholder
string"Type a value…"
inputType
Type
"text" | "number""text"
submitLabel
Button label
string"Send"

Select

selectinteractive

Choose one option from a list — mode, environment, strategy.

Select an option{"value":"Aggressive"}
Data & config fields

Data

FieldTypeDefault
valuestring""

Config

FieldTypeDefault
title
Title
string""
viewersCanUse
Otherwise only editors
booleanfalse
webhookUrl
We POST the new value here (https only)
string""
options
Options
string[]["Option A","Option B"]
style
Style
"dropdown" | "buttons""buttons"

Text

markdown

Headings, notes and links, written in Markdown.

Replace text{"text":"# Deploy status\nAll green ✅"}
Data & config fields

Data

FieldTypeDefault
text
Markdown
string""

Config

FieldTypeDefault
title
Title
string""
align
Alignment
"left" | "center""left"
size
Text size
"sm" | "md" | "lg""md"

FAQ / accordion

accordionappend

Questions and answers that expand on click — runbooks, FAQs, notes.

Add an item{"append":{"q":"Who owns this board?","a":"The platform team."}}
Data & config fields

Data

FieldTypeDefault
itemsobject[][]

Config

FieldTypeDefault
title
Title
string""
openFirst
Open the first item
booleantrue

Image

image

Show an image or a camera snapshot that refreshes on a timer.

Change image{"url":"https://example.com/cam.jpg"}
Data & config fields

Data

FieldTypeDefault
url
Image URL
string""

Config

FieldTypeDefault
title
Title
string""
fit
Fit
"cover" | "contain""cover"
refreshSeconds
0 = off
integer0
alt
Alt text
string""

Embed

embed

Embed a web page, video or form (YouTube, Google Docs, Loom…).

Change URL{"url":"https://example.com"}
Data & config fields

Data

FieldTypeDefault
url
Page URL
string""

Config

FieldTypeDefault
title
Title
string""

Clock

clock

Current time in any time zone.

Data & config fields

Data

No fields.

Config

FieldTypeDefault
title
Title
string""
timeZone
e.g. Asia/Jerusalem. Empty = viewer's
string""
hour12
12-hour
booleanfalse
showSeconds
Seconds
booleantrue
showDate
Date
booleantrue

Countdown

countdown

Days, hours and minutes until a launch, deadline or event.

Set target{"target":"2026-12-31T23:59:00Z"}
Data & config fields

Data

FieldTypeDefault
target
Target date & time
string""

Config

FieldTypeDefault
title
Title
string""
doneText
Text when finished
string"It's time! 🎉"