Canvas API

Expose HTML Canvas2D to the web via REST and WebSocket. Each key owns an independent canvas. Commands are broadcast in real-time — no command history is stored.

Start Now

Session IDs

Every operation requires a session string to identify the source. The canvas page generates a random UUID session ID automatically. When calling the API externally, provide any string you choose.

// REST — session in request body:
{ "session": "my-session", "x": 10, "y": 10, "width": 100, "height": 50 }

// WebSocket — session at message root:
{ "session": "my-session", "method": "fillRect", "params": { ... } }

Command Limit

Each canvas is limited to 100 commands. When the 101st command is received, the canvas is automatically cleared and the counter resets. This applies to all drawing commands (not transient events like _mouse or _key).

Input Events

When the canvas page is open in a browser, mouse and keyboard events are automatically captured and sent over WebSocket as transient _mouse and _key methods. These are broadcast to all other connected clients and logged to the events endpoint.

Mouse

{ "method": "_mouse", "params": { "type": "move", "x": 100, "y": 200 } }
{ "method": "_mouse", "params": { "type": "down", "button": "left", "x": 100, "y": 200 } }
{ "method": "_mouse", "params": { "type": "up", "button": "left", "x": 100, "y": 200 } }

Keyboard

{ "method": "_key", "params": { "type": "keydown", "key": "a", "code": "KeyA" } }
{ "method": "_key", "params": { "type": "keyup", "key": "a", "code": "KeyA" } }

Events REST API

Logged mouse and keyboard events can be polled via REST:

GET /api/:key/events?since=0
// { "ok": true, "count": 5, "events": [{ "id": 1, "session": "...", "method": "_mouse", "params": {...}, "timestamp": 1234567890 }, ...] }

The since parameter is the last event ID your client has seen. Events are indexed sequentially per key.

List all unique session IDs that have sent events to this key:

GET /api/:key/sessions
// { "ok": true, "sessions": ["my-session", "abc...", ...] }

REST API

Send drawing commands as JSON POST requests. Every request must include a session field.

POST /api/:key/:method
// body: { "session": "my-session", "param": "value", ... }
// response: { "ok": true }

Clear the canvas:

POST /api/:key/clear
// body: { "session": "my-session" }
// { "ok": true }

WebSocket API

Connect with the key as a query parameter:

ws://host:8080/ws?key=YOUR_KEY

On connection, the server sends { "type": "init" }. Send commands as JSON messages with a session field:

// send:
{ "session": "my-session", "method": "fillRect", "params": { "x": 10, "y": 10, "width": 200, "height": 100 } }

// receive:
{ "ok": true }

All connected clients with the same key receive the command in real-time (excluding the sender).

Examples

REST (curl)

# set the key
KEY=your_key_here

# draw a red rectangle
curl -X POST http://localhost:8080/api/$KEY/fillStyle \
  -H 'Content-Type: application/json' \
  -d '{"session":"demo","value":"#ff0000"}'

curl -X POST http://localhost:8080/api/$KEY/fillRect \
  -H 'Content-Type: application/json' \
  -d '{"session":"demo","x":10,"y":10,"width":200,"height":100}'

# draw text
curl -X POST http://localhost:8080/api/$KEY/font \
  -H 'Content-Type: application/json' \
  -d '{"session":"demo","value":"24px monospace"}'

curl -X POST http://localhost:8080/api/$KEY/fillText \
  -H 'Content-Type: application/json' \
  -d '{"session":"demo","text":"hello","x":50,"y":100}'

# draw a circle
curl -X POST http://localhost:8080/api/$KEY/beginPath \
  -H 'Content-Type: application/json' \
  -d '{"session":"demo"}'

curl -X POST http://localhost:8080/api/$KEY/arc \
  -H 'Content-Type: application/json' \
  -d '{"session":"demo","x":200,"y":200,"radius":50,"startAngle":0,"endAngle":6.283}'

curl -X POST http://localhost:8080/api/$KEY/fill \
  -H 'Content-Type: application/json' \
  -d '{"session":"demo"}'

WebSocket (node.js)

const WebSocket = require('ws');
const ws = new WebSocket('ws://localhost:8080/ws?key=YOUR_KEY');

ws.on('open', () => {
  ws.send(JSON.stringify({
    session: 'my-session',
    method: 'fillStyle',
    params: { value: '#00ff00' }
  }));

  ws.send(JSON.stringify({
    session: 'my-session',
    method: 'fillRect',
    params: { x: 50, y: 50, width: 100, height: 100 }
  }));
});

ws.on('message', (d) => console.log('recv:', d.toString()));

Supported Methods

Drawing

beginPath closePath moveTo lineTo rect arc arcTo bezierCurveTo quadraticCurveTo fill stroke clip clear

Shapes

fillRect strokeRect clearRect

Text

fillText strokeText font textAlign textBaseline direction

Style

fillStyle strokeStyle lineWidth lineCap lineJoin miterLimit setLineDash lineDashOffset globalAlpha globalCompositeOperation imageSmoothingEnabled filter

Shadows

shadowBlur shadowColor shadowOffsetX shadowOffsetY

Transform

save restore translate rotate scale setTransform resetTransform

Image Data

drawImage putImageData createImageData