← Docs

API Reference

HTML in, shareable link out. Five input formats, one endpoint.

Install as an agent skill

Works with Cursor, Claude Code, Codex, Windsurf, OpenClaw, and any agent supporting the Skills protocol.

npx skills add gui-now/skills --skill gui-now -g

Pick your path

Use the first one that fits. They all hit the same endpoint.

CLI

At a terminal, or from a script. Fastest way to a URL.

Jump to CLI →

SDK

Building canvases from inside an app, in JS or Python.

Jump to SDKs →

HTTP

Anything else. One POST, no dependencies, any language.

Jump to the API →

Agents should prefer the CLI over hand-writing HTTP — embedding a full HTML document inside a JSON string by hand is where these calls usually go wrong. See llms.txt.

CLI

Zero dependencies, Node 18+. Pipe HTML in, get a URL back.

npm install -g gui-now

Or run it without installing:

npx gui-now push index.html

Usage

gui push index.html                       # push a file
cat index.html | gui push                 # or pipe from stdin
gui push index.html --title "Dashboard"   # name it
gui push --markdown README.md             # render markdown
gui push index.html --open                # open in a browser after
gui push index.html --json                # full JSON response
gui push index.html --expires 7d          # Pro: longer expiry
gui open abc123                           # open an existing canvas

Options

FlagShortDescription
--title-tCanvas title
--expires-eExpiry: 30m, 24h, 7d (up to 365d) or never, capped by your plan
--markdown-mTreat input as markdown
--open-oOpen the URL after creating
--json-jOutput the full JSON response
--help-hShow help

Pro API key

Set it in the environment to lift the create limit to 100 an hour and unlock longer expiry:

export GUI_NOW_API_KEY=YOUR_PRO_KEY

Published as gui-now on npm. Note the JS SDK is a different package, gui-now-sdk.

Base URL

https://gui.now/api
POST

/canvas

Create a new canvas. Returns a shareable URL. Accepts HTML, Markdown, or structured components.

Request Body

FieldTypeRequiredDescription
htmlstring*Raw HTML content
markdownstring*Markdown content (server-rendered with syntax highlighting)
titlestringNoDisplay name in toolbar, OG meta, social previews
themestringNo"dark" or "light", for markdown. Omit it and the page follows each viewer's setting
framesarrayNoMulti-tab views. Each: {html, label?}
expiresstringNo"30m", "24h", "7d" (up to "365d") or "never". Past your plan's max you get the max and "expires_clamped": true; any other value is a 400.
passwordstringProPassword-protect the canvas

* One of html or markdown is required. Use <gui-*> component tags directly in either format.

Pro API Key

Pass as a header to unlock Pro limits:

x-api-key: YOUR_PRO_KEY

Examples

HTML

curl -X POST https://gui.now/api/canvas \
  -H 'Content-Type: application/json' \
  -d '{
    "title": "My Dashboard",
    "html": "<h1 style=\"color:white\">Hello World</h1>"
  }'

Markdown

curl -X POST https://gui.now/api/canvas \
  -H 'Content-Type: application/json' \
  -d '{
    "markdown": "# Sprint Report\n\nShipped **3 features** this week.",
    "title": "Sprint Report"
  }'

HTML with components

curl -X POST https://gui.now/api/canvas \
  -H 'Content-Type: application/json' \
  --data-binary @- <<'JSON'
{
  "html": "<gui-grid columns=\"2\"><gui-card title=\"Revenue\" value=\"$12,450\" change=\"+8.2%\"></gui-card><gui-chart type=\"bar\" data='[{\"label\":\"Q1\",\"value\":42}]'></gui-chart></gui-grid>",
  "title": "Dashboard"
}
JSON

Multi-frame (tabbed)

curl -X POST https://gui.now/api/canvas \
  -H 'Content-Type: application/json' \
  -d '{
    "html": "<h1>Default view</h1>",
    "frames": [
      {"html": "<h1 style=\"color:red\">Option A</h1>", "label": "Red"},
      {"html": "<h1 style=\"color:blue\">Option B</h1>", "label": "Blue"}
    ]
  }'

Response

{
  "id": "abc123xyz",
  "url": "https://gui.now/abc123xyz",
  "edit_token": "tok_...",
  "expires_at": "2026-02-28T16:00:00Z",
  "pro": false,
  "format": "html"
}
POST

/flow

Create a Mermaid diagram. It's drawn as a figure with your title as the caption, zooms with Ctrl/⌘ + scroll, and has an Edit as Mermaid button that shows the source. Add %% note: … lines for numbered notes under the figure, and :::accent on a flowchart node to highlight it. Supports flowcharts, sequence, class, state, ER, gantt, pie, mindmap, timeline.

curl -X POST https://gui.now/api/flow \
  -H 'Content-Type: application/json' \
  -d '{
    "mermaid": "graph TD\n  %% note: Skipping is fine for drafts.\n  A[Start] --> B{Decision}:::accent\n  B -->|Yes| C[Do it]\n  B -->|No| D[Skip]",
    "title": "My Flow"
  }'
PUT

/canvas/:id

Update an existing canvas. Requires edit_token. All viewers see changes live via SSE. Free: 3 edits. Pro: unlimited. The response lists what changed, any ignored fields, and a content_hash that /embed/:id also sends as X-Content-Hash. A body with nothing to update is a 400.

Headers

HeaderValue
AuthorizationBearer <edit_token>

Body fields

FieldTypeDescription
htmlstringNew HTML content
markdownstringNew body as Markdown, rendered like create (use one of html, markdown or mermaid)
mermaidstringNew body as a Mermaid diagram
themestring"dark" or "light", for markdown and mermaid. Omit it and the page follows each viewer's setting
titlestringUpdated title
framesarrayUpdated tabs
passwordstring | nullSet or remove password (Pro). Omit to keep it; re-sending the current one keeps readers unlocked, a new one signs them out
curl -X PUT https://gui.now/api/canvas/abc123xyz \
  -H 'Content-Type: application/json' \
  -H 'Authorization: Bearer tok_...' \
  -d '{"html": "<h1>Updated!</h1>"}'
POST

/canvas/:id/extend

Extend canvas expiry by 24 hours from now. Send the edit token with a body like {"expires": "7d"} to pick how long, up to your plan's max. Extending never shortens a page.

curl -X POST https://gui.now/api/canvas/abc123xyz/extend
DELETE

/canvas/:id

Delete a canvas and its saved input for good. Its URL returns 404 afterwards. Send the edit_token, or call it signed in as the page's owner (from the app, or with one of your gui_live_ keys in x-api-key). A wrong token gets the same 404 as a missing page. Expired pages can still be deleted.

curl -X DELETE https://gui.now/api/canvas/abc123xyz \
  -H 'Authorization: Bearer tok_...'
{ "id": "abc123xyz", "deleted": true }
GET

/canvas/:id/events

Server-Sent Events stream. Receive real-time updates when canvas content changes.

const source = new EventSource(
  'https://gui.now/api/canvas/abc123xyz/events'
);

source.onmessage = (e) => {
  const data = JSON.parse(e.data);
  if (data.type === 'update') {
    // data.html, data.title, data.frames
  }
};

Events: connected (on subscribe), update (content changed).

Component Library

Auto-injected into every canvas. No imports needed — just use the HTML tags.

<gui-chart>— Charts (bar, line, pie)
<gui-chart type="bar" data='[{"label":"Q1","value":42},{"label":"Q2","value":58}]'></gui-chart>
<gui-table>— Sortable tables
<gui-table data='[{"name":"Alice","role":"Eng"},{"name":"Bob","role":"PM"}]'></gui-table>
<gui-card>— Stat cards
<gui-card title="Users" value="12,847" change="+12.3%"></gui-card>
<gui-code>— Code with syntax highlighting
<gui-code language="python">def hello(): print("world")</gui-code>
<gui-kanban>— Kanban boards
<gui-kanban columns='[{"title":"Todo","items":["Task 1"]},{"title":"Done","items":["Task 2"]}]'></gui-kanban>
<gui-timeline>— Timelines
<gui-timeline data='[{"date":"Mar 1","title":"Launch"}]'></gui-timeline>
<gui-form>— Forms (synced)
<gui-form fields='[{"name":"email","type":"email","label":"Email"}]'></gui-form>
<gui-grid>— Grid layouts (1-4 cols)
<gui-grid columns="3"><gui-card title="A" value="1"></gui-card><gui-card title="B" value="2"></gui-card><gui-card title="C" value="3"></gui-card></gui-grid>
<gui-progress>— Progress bars
<gui-progress label="Launch readiness" value="14" max="22" note="On track for Nov 17"></gui-progress>
<gui-callout>— Callouts (info, success, warn, danger)
<gui-callout tone="warn" title="3 tasks blocked">Legal review is due Thursday.</gui-callout>
<gui-poll>— Polls (one vote per browser, synced)
<gui-poll name="dinner" label="Dinner plan, Friday?" options='["Tacos","Thai","Pizza"]'></gui-poll>
<gui-checklist>— Checklists (shared, or claimable: one person per item)
<gui-checklist name="bbq" claimable items='["Burgers","Buns","Charcoal"]'></gui-checklist>

Form inputs sync across all viewers automatically.

Built-in Features

Every canvas automatically gets:

Input sync— Every <input>, <textarea>, <select> and contenteditable syncs across viewers in real time. Give fields an id, name or data-gui-key so values return to the right field; data-gui-nosync opts one out
State persistence— Form state is saved for the next visit, and an old tab merges in newer values instead of overwriting them
Component library— 16 pre-built components: tables, charts, kanban boards, timelines, polls, checklists and more
OG images— Dynamic social preview with canvas title and metadata
Password protection— Server-side gating with password (Pro only)

Limits

FeatureFreePro
AuthNone, or an account key (gui_live_) to save pages to your libraryYour Pro key in the x-api-key header
Rate limit5 creates / hour per IP, 20 signed in100 creates / hour
Max size2 MB4 MB
Expiry24 hours, up to 72 (signed in: 72 hours, up to 7 days)Never by default, or any duration up to 365 days
Edits3 per canvasUnlimited
Password—Yes
Components10 of 16 typesAll 16 types
Page footer“Made with GUI” under the pageNone

Free tier requires no account or API key. Without one, creates are limited per IP address; signed in (a session or a gui_live_ account key), they count against your account wherever you create from.

Hosted MCP server

GUI runs an MCP server, so an agent can publish without installing anything. Its tools are create_canvas, create_markdown_canvas, create_multi_frame, create_diagram, update_canvas, extend_canvas and list_pages.

https://gui.now/mcp

No sign-in: add this URL as a custom connector in Claude or ChatGPT, or as a remote MCP server (Streamable HTTP) in any other client, and it publishes straight away. Each new page comes with a claim link to keep it in a GUI library. Creates are limited per ChatGPT user or MCP session, 10 an hour.

https://gui.now/mcp/account

With your account (optional): add this URL instead and sign in to GUI when asked. Before you allow it, GUI shows the account, the app that is connecting and the address it sends you back to. Pages go to your library, count against your account's limits, and list_pages can read your library.

Headers instead of sign-in: clients that take headers can send Authorization: Bearer <api key> to either URL with a key from your account. Clients that support MCP authorization find the sign-in at /.well-known/oauth-protected-resource/mcp/account.

SDKs

For building canvases from inside an application. To create one from a terminal, use the CLI.

JavaScript / TypeScript

npmjs.com →
npm install gui-now-sdk
import { createGui } from 'gui-now-sdk'
const gui = createGui()

const canvas = await gui.create({ html: '<h1>Hello</h1>' })
console.log(canvas.url)

await gui.update(canvas.id, canvas.edit_token, { html: '<h1>v2</h1>' })
pip install gui-now
from guinow import GuiNowClient

client = GuiNowClient()
canvas = client.create(
    html="<h1>Hello</h1>",
    title="My Dashboard",
)
print(canvas.url)

client.update(canvas.id, canvas.edit_token, html="<h1>v2</h1>")