Reference

API Reference

OpenAPI JSON

All write operations require Authorization: Bearer <write-token>. Read operations (GET, SSE) are public. Every write automatically pushes an SSE update to all connected browser tabs.

What you need

Every API call uses a dashboard ID. Write operations also need a write token. Tiles are targeted by their ID (or alternateId on any plan).

Dashboard ID

The last segment of your dashboard URL. In /d/abc123xyz456, the dashboard ID is abc123xyz456.

Write token

Required for POST, PATCH, and DELETE. Treat it like a password. It is not recoverable if lost — but you can regenerate it from your dashboard settings.

Tile ID / alternateId

Fetch the tile list first to find tile IDs. Any dashboard can assign a unique alternateId per tile. Use lookup=alternateId for single-tile GET and DELETE.

Authentication

Read endpoints are public. Anyone with the dashboard ID can fetch tiles or open an SSE stream — no token needed. Write endpoints require a Bearer token in the Authorization header. Without it (or with a wrong token), write endpoints return 401.

Authorization: Bearer YOUR_WRITE_TOKEN

Write endpoints (token required)

PATCH/api/d/{id}
POST/api/d/{id}/tiles
PATCH/api/d/{id}/tiles
DELETE/api/d/{id}/tiles/{ref}
POST/api/d/{id}/tiles/reorder

Public endpoints (no token)

GET/api/d/{id}/tiles
GET/api/d/{id}/tiles/{ref}
GET/api/d/{id}/stream

Plans and limits

When you exceed the rate limit, the API returns 429. Every write response carries X-RateLimit-Limit, X-RateLimit-Remaining, and X-RateLimit-Reset (Unix timestamp in seconds when a slot frees up) headers.

LimitFreePro
Dashboards per user1Unlimited
Tiles per dashboard5Unlimited
API write calls per hour601,000
Alternate tile IDs (alternateId)AvailableAvailable

Quick start

Two commands to go from zero to a live update. Swap in your IDs and token.

Platform note

The curl tab works on macOS, Linux, and WSL. Select PowerShell for native Windows commands. The Arduino (ESP32) tab shows a complete sketch for microcontrollers.

1

Read your tiles

No write token needed. Find the id of the tile you want to update.

curl https://easyboard.live/api/d/YOUR_DASHBOARD_ID/tiles
2

Push a value

Replace YOUR_TILE_ID with the ID from step 1.

curl -X PATCH https://easyboard.live/api/d/YOUR_DASHBOARD_ID/tiles \
  -H "Authorization: Bearer YOUR_WRITE_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"updates":[{"target":{"id":"YOUR_TILE_ID"},"patch":{"value":"1500"}}]}'

Want a step-by-step walkthrough? See the Quick Start guide →

Tile types

All tile values are strings — even numbers. Each tile type interprets that string differently. Use small, medium, or large for the size field.

Typevalue field
metric

Number as a string

"1250"

Large number with optional unit prefix/suffix (e.g. $, kg, ms).

counter

Integer as a string

"12"

A count, usually changed via delta (+1 / -1) to avoid race conditions.

progress

0–100 as a string

"75"

Horizontal bar. Visual is clamped to 100% client-side; API stores the raw value.

text

Plain text

"Kitchen closes at 4pm"

Free-form message, note, or status update.

clock

IANA timezone

"America/New_York"

Live clock. Empty string = viewer's local timezone.

countdown

ISO 8601 datetime

"2027-01-01T00:00:00Z"

Counts down to a target moment. Shows "Done!" when reached.

elapsed

ISO 8601 datetime

"2026-01-01T00:00:00Z"

Counts up from a start moment.

toggle

One of the options

"Open"

Cycles through 2–3 preset options. PATCH {"next":true} to advance.

Common recipes

Copy-paste examples for the most frequent operations.

Create a metric tile

Add a new metric tile at the end of the dashboard.

curl -X POST https://easyboard.live/api/d/YOUR_DASHBOARD_ID/tiles \
  -H "Authorization: Bearer YOUR_WRITE_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"type":"metric","title":"Revenue","value":"1250","unit":"$","size":"medium"}'

Increment a counter with delta

Send `delta` for counter-style updates. `delta` currently wins over `value` if both are present.

curl -X PATCH https://easyboard.live/api/d/YOUR_DASHBOARD_ID/tiles \
  -H "Authorization: Bearer YOUR_WRITE_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"updates":[{"target":{"id":"YOUR_TILE_ID"},"patch":{"delta":1}}]}'

Set a text tile

Text tiles use the same batch PATCH endpoint with a string value.

curl -X PATCH https://easyboard.live/api/d/YOUR_DASHBOARD_ID/tiles \
  -H "Authorization: Bearer YOUR_WRITE_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"updates":[{"target":{"id":"YOUR_TILE_ID"},"patch":{"value":"Kitchen closes at 4pm"}}]}'

Set a progress tile

Progress values are stored exactly as sent; the UI clamps the visual bar client-side.

curl -X PATCH https://easyboard.live/api/d/YOUR_DASHBOARD_ID/tiles \
  -H "Authorization: Bearer YOUR_WRITE_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"updates":[{"target":{"id":"YOUR_TILE_ID"},"patch":{"value":"75"}}]}'

Read all tiles

Fetch a one-shot snapshot of the dashboard without opening a streaming connection.

curl https://easyboard.live/api/d/YOUR_DASHBOARD_ID/tiles

Subscribe with SSE

Use a streaming connection when you want live dashboard snapshots without polling.

curl -N https://easyboard.live/api/d/YOUR_DASHBOARD_ID/stream

Behavioral notes

Batch PATCH requests are atomic. If any instruction fails, none of the tile updates are saved.

If you send both delta and value in the same tile patch, delta wins and value is ignored.

If you send next: true and value in the same tile patch, next wins and value is ignored.

delta is mainly for counters, but the API currently applies it to any tile whose value can be treated like a number.

Progress values are stored exactly as sent. The visual bar is clamped client-side, not by the API.

alternateId is available on all plans. It must be unique within a dashboard and lets you target tiles by name instead of UUID.

SSE sends full dashboard snapshots and may emit a deleted event before closing if the dashboard is removed elsewhere.

Endpoint reference

patch/api/d/{dashboardId}Needs write token

Update dashboard settings

Updates dashboard-level settings. Currently supports renaming the dashboard. The name appears in the header and browser tab for all viewers, and is broadcast to connected SSE clients in real time.

URL Parts

NameInRequiredDescription
dashboardIdpathYesThe 12-character dashboard ID from your dashboard URL.

What To Send

FieldTypeRequiredNotes
namestringNoDisplay name for the dashboard. Emojis are welcome. Send an empty string to clear. Max 100 chars.

Examples

curl -X PATCH https://easyboard.live/api/d/YOUR_DASHBOARD_ID \
  -H "Authorization: Bearer YOUR_WRITE_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name":"Coffee Shop Sales"}'

What You Get Back

200Updated dashboard settings.
application/json
{
  "name": "Coffee Shop Sales"
}
400Invalid body or name too long.
application/json
{
  "error": "name must be 100 characters or fewer"
}
401Missing or incorrect write token.
application/json
{
  "error": "Unauthorized"
}
404Dashboard not found.
application/json
{
  "error": "Dashboard not found"
}
get/api/d/{dashboardId}/tilesNo write token needed

List tiles

Returns the current tiles for a dashboard, sorted by order. You can call this without a write token.

URL Parts

NameInRequiredDescription
dashboardIdpathYesThe 12-character dashboard ID from your dashboard URL.

Examples

curl https://easyboard.live/api/d/YOUR_DASHBOARD_ID/tiles

What You Get Back

200Sorted tile array.
application/json
[
  {
    "id": "tile-abc123",
    "alternateId": "RevenueTile",
    "type": "metric",
    "title": "Revenue",
    "value": "1250",
    "unit": "$",
    "size": "medium",
    "order": 0
  },
  {
    "id": "tile-def456",
    "type": "counter",
    "title": "Orders",
    "value": "12",
    "unit": "",
    "size": "small",
    "order": 1
  }
]
404Dashboard not found.
application/json
{
  "error": "Dashboard not found"
}
post/api/d/{dashboardId}/tilesNeeds write token

Create a tile

Creates a new tile at the end of the dashboard. Send your dashboard write token in the Authorization header.

URL Parts

NameInRequiredDescription
dashboardIdpathYesThe 12-character dashboard ID from your dashboard URL.

What To Send

FieldTypeRequiredNotes
typestringNoUse one of the built-in tile types: metric, text, counter, progress, clock, countdown, elapsed, or toggle. Other values may save successfully but may not display correctly in EasyBoard.
titlestringNoTile label shown above the value. Max 200 chars.
valuestringNoTile value, always stored as a string. Max 10000 chars.
unitstringNoOptional prefix or suffix for metric tiles. Max 32 chars.
sizestringNoUse small, medium, or large. Other values may save successfully but may display oddly, so integrations should stick to those three.
optionsarrayNoToggle tiles only. The ordered list of values to cycle through (2–3 entries). The first entry becomes the initial value.
optionColorsarrayNoToggle tiles only. Per-option highlight colors. Length should match `options`. Falls back to gray + green (2-option) or gray + amber + green (3-option) if missing or length-mismatched.
alternateIdstringNoOptional human-readable identifier you control. Must be unique within the dashboard and can later be used with `lookup=alternateId` or as a batch update target.
fontFamilystringNoPro-only. Font for the tile. `sans` (Geist Sans, default), `mono` (Geist Mono), or `serif` (Georgia). Omit or send empty string for default.
textColorstringNoPro-only. Text color for the tile value. `white` (default), `accent` (matches dashboard accent color), or `muted` (gray). Omit or send empty string for default.

Examples

curl -X POST https://easyboard.live/api/d/YOUR_DASHBOARD_ID/tiles \
  -H "Authorization: Bearer YOUR_WRITE_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"type":"metric","title":"Revenue","value":"1250","unit":"$","size":"medium"}'

What You Get Back

201Created tile.
application/json
{
  "id": "tile-abc123",
  "alternateId": "RevenueTile",
  "type": "metric",
  "title": "Revenue",
  "value": "1250",
  "unit": "$",
  "size": "medium",
  "order": 0
}
400Invalid JSON body or field length violation.
application/json
{
  "error": "title must be 200 characters or fewer"
}
401Missing or incorrect write token.
application/json
{
  "error": "Unauthorized"
}
404Dashboard not found.
application/json
{
  "error": "Dashboard not found"
}
patch/api/d/{dashboardId}/tilesNeeds write token

Update one or more tiles

Applies one or more tile updates atomically. Each instruction targets exactly one tile by `id` or `alternateId`. Current server behavior is important here: if you send both `delta` and `value`, `delta` wins and `value` is ignored.

URL Parts

NameInRequiredDescription
dashboardIdpathYesThe 12-character dashboard ID from your dashboard URL.

What To Send

FieldTypeRequiredNotes
updatesarrayYesOne or more tile updates applied atomically. If any instruction fails, no tile changes are saved.

Examples

curl -X PATCH https://easyboard.live/api/d/YOUR_DASHBOARD_ID/tiles \
  -H "Authorization: Bearer YOUR_WRITE_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"updates":[{"target":{"id":"YOUR_TILE_ID"},"patch":{"value":"1500"}}]}'

What You Get Back

200Updated tiles in request order.
application/json
{
  "updated": [
    {
      "id": "tile-abc123",
      "alternateId": "RevenueTile",
      "type": "metric",
      "title": "Revenue",
      "value": "1500",
      "unit": "$",
      "size": "medium",
      "order": 0
    }
  ]
}
400Invalid JSON body, malformed target, or field length violation.
application/json
{
  "error": "Body must be an object with an updates array"
}
401Missing or incorrect write token.
application/json
{
  "error": "Unauthorized"
}
403A Pro-only feature (per-tile styling) was attempted on a FREE dashboard.
application/json
{
  "error": "Per-tile styling is a Pro feature. Upgrade to Pro to customize font and text color."
}
404Dashboard or tile not found.
application/json
{
  "error": "Tile not found"
}
409The requested alternateId already exists on this dashboard.
application/json
{
  "error": "alternateId is already used on this dashboard"
}
get/api/d/{dashboardId}/tiles/{tileRef}No write token needed

Get a single tile

Fetch one tile by its generated tile ID or, when `lookup=alternateId`, by its alternateId.

URL Parts

NameInRequiredDescription
dashboardIdpathYesThe 12-character dashboard ID from your dashboard URL.
tileRefpathYesA tile ID, or an alternateId when used with `lookup=alternateId`.
lookupqueryNoHow to interpret the `tileRef` path segment. Defaults to `id`. Use `alternateId` to fetch or delete by alternateId.

What You Get Back

200Tile found.
application/json
{
  "id": "tile-abc123",
  "alternateId": "RevenueTile",
  "type": "metric",
  "title": "Revenue",
  "value": "1250",
  "unit": "$",
  "size": "medium",
  "order": 0
}
400Invalid lookup mode.
application/json
{
  "error": "lookup must be either \"id\" or \"alternateId\""
}
404Dashboard or tile not found.
application/json
{
  "error": "Tile not found"
}
delete/api/d/{dashboardId}/tiles/{tileRef}Needs write token

Delete a tile

Permanently removes a tile and re-indexes the remaining `order` fields. By default `tileRef` is treated as a tile ID; use `lookup=alternateId` to delete by alternateId.

URL Parts

NameInRequiredDescription
dashboardIdpathYesThe 12-character dashboard ID from your dashboard URL.
tileRefpathYesA tile ID, or an alternateId when used with `lookup=alternateId`.
lookupqueryNoHow to interpret the `tileRef` path segment. Defaults to `id`. Use `alternateId` to fetch or delete by alternateId.

Examples

curl -X DELETE https://easyboard.live/api/d/YOUR_DASHBOARD_ID/tiles/YOUR_TILE_ID \
  -H "Authorization: Bearer YOUR_WRITE_TOKEN"

What You Get Back

204Tile deleted successfully.
400Invalid lookup mode.
application/json
{
  "error": "lookup must be either \"id\" or \"alternateId\""
}
401Missing or incorrect write token.
application/json
{
  "error": "Unauthorized"
}
404Dashboard or tile not found.
application/json
{
  "error": "Tile not found"
}
post/api/d/{dashboardId}/tiles/reorderNeeds write token

Reorder tiles

Updates all tile order values at once. Used by drag-and-drop and bulk reordering.

URL Parts

NameInRequiredDescription
dashboardIdpathYesThe 12-character dashboard ID from your dashboard URL.

What To Send

FieldTypeRequiredNotes
idsarrayYesOrdered list of tile IDs. The first element becomes order 0.

Examples

curl -X POST https://easyboard.live/api/d/YOUR_DASHBOARD_ID/tiles/reorder \
  -H "Authorization: Bearer YOUR_WRITE_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"ids":["tile-def456","tile-abc123"]}'

What You Get Back

204Tiles reordered successfully.
400Invalid JSON body or ids must be an array.
application/json
{
  "error": "ids must be an array"
}
401Missing or incorrect write token.
application/json
{
  "error": "Unauthorized"
}
404Dashboard not found.
application/json
{
  "error": "Dashboard not found"
}
get/api/d/{dashboardId}/streamNo write token needed

Stream live dashboard snapshots

Opens a Server-Sent Events stream for one dashboard. The first event is the current dashboard snapshot, later events are updated snapshots. If the dashboard is removed elsewhere, the stream may emit a `deleted` event before closing.

URL Parts

NameInRequiredDescription
dashboardIdpathYesThe 12-character dashboard ID from your dashboard URL.

Examples

curl -N https://easyboard.live/api/d/YOUR_DASHBOARD_ID/stream

What You Get Back

200Server-Sent Events stream.
text/event-stream
data: {"name":"Coffee Shop Sales","tiles":[{"id":"tile-abc123","type":"metric","title":"Revenue","value":"1250","unit":"$","size":"medium","order":0}]}

: keepalive

event: deleted
data: {}

404Dashboard not found.
application/json
{
  "error": "Dashboard not found"
}

Field limits

title

200 characters

value

10,000 characters

unit

32 characters

Dashboard name

100 characters

Batch PATCH

100 update instructions

alternateId

100 chars · letters, numbers, . _ -

Error codes

400

Malformed JSON, missing fields, or field length exceeded

401

Missing or invalid write token

403

Pro-only feature on a Free dashboard, or tile/dashboard limit reached

404

Dashboard or tile not found

409

alternateId already in use on this dashboard

429

Rate limit exceeded — check X-RateLimit-Reset for when to retry