Skip to content

Updated

View MarkdownOpen in ChatGPTOpen in Claude

API Reference

Public, unauthenticated HTTP API at https://glasshome.app for reading the widget catalog. /api/v1/widgets/* is CORS-open (one exception under Conventions).

What’s public

Only the endpoints below are public and versioned. /api/* without /v1/ is internal: it powers the Hub UI and @glasshome/widget-cli, requires a session, and may change without notice. Do not integrate against it.

To publish widgets, use the Widget CLI; it handles auth and the publish flow.

API versioning and sunset

/api/v1/ is the current stable version. A breaking change gets a new prefix (e.g. /api/v2/); the old one is announced for sunset with reasonable notice.

Conventions

  • All requests/responses are JSON.
  • Errors: { "error": "<human-readable message>" } with an appropriate HTTP status.
  • Timestamps: ISO 8601, UTC.
  • Pagination: page-based (?page=, ?limit=).
  • CORS: Access-Control-Allow-Origin: * on /api/v1/widgets/* only. /api/widgets/{scope}/registry.json sends no CORS header: cross-origin browser fetches fail; server-to-server and same-origin fetches work.

GET /api/v1/widgets/search

Search the public widget registry.

Query parameters

Parameter Type Description
q string Free-text. Matches displayName and description.
compatSdk string SDK semver (e.g. 0.5.2). Must be a valid semver string or the endpoint returns 400. Adds latestCompatibleVersion per result.
scope string Restrict to a scope, e.g. glasshome.
official boolean true limits to Official widgets; false limits to non-official.
page number Page number, default 1.
limit number Page size, default 20, max 100.

Unlisted widgets are excluded from results.

Response

{
  "widgets": [/* WidgetSummary */],
  "total": 123,
  "page": 1,
  "limit": 20
}

WidgetSummary fields

Field Type Description
scope string Publishing scope (e.g. "glasshome")
name string Widget identifier
displayName string Human-readable display name
description string or null Short description
icon string or null Iconify icon identifier
isOfficial boolean or null Whether this is an Official (GlassHome-maintained) widget
downloadCount number or null Cumulative installs
latestVersion VersionEntry or null Latest non-yanked version. null if no published version exists.
latestCompatibleVersion VersionEntry or null Only present when compatSdk is supplied. Newest version satisfying the requested SDK range, or null.

VersionEntry fields

Field Type Description
scope string Scope (same as parent)
name string Widget name (same as parent)
version string Semver version string
bundleUrl string CDN URL for the JS bundle
bundleSize number Bundle size in bytes (raw, not gzip)
sha256Hash string SHA-256 hex digest of the bundle
publishedAt string ISO 8601 timestamp
yanked boolean Whether this version has been yanked
yankedReason string or null Human-readable reason if yanked
deprecationMessage string or null Warning shown on widgets using this version
releaseNotes string or null User-facing changelog text
displayName string From version manifest, falls back to widget row
description string or null From version manifest, falls back to widget row
icon string or null From version manifest, falls back to widget row
minSize {w, h} Minimum grid size
maxSize {w, h} Maximum grid size
sdkVersion string SDK version range the bundle was built against
configVersion number or null Config version for migration support
permissions string[] Declared permissions
license string or null License identifier

Error responses

Status Condition
400 compatSdk is not a valid semver string

GET /api/v1/widgets/{scope}/{name}

Single widget detail, including the full version list.

Response

{
  "widget": {
    "scope": "glasshome",
    "name": "my-widget",
    "displayName": "My Widget",
    "description": "...",
    "icon": "mdi:lightbulb",
    "isOfficial": false,
    "downloadCount": 42,
    "createdAt": "2025-01-01T00:00:00.000Z"
  },
  "versions": [/* VersionEntry (see above) */],
  "latestVersion": "1.2.0"
}

versions is ordered by publishedAt descending. latestVersion is the newest non-yanked published version string, or null if none exists.

Error responses

Status Condition
404 Widget not found or is unlisted

POST /api/v1/widgets/{scope}/{name}

Increments the download counter; dashboards call it on install. No request body, no auth. Best-effort: a plain +1 SQL update, no rate-limiting or deduplication, so not suitable for precise install analytics.

Response

{ "success": true }

Error responses

Status Condition
404 Widget not found

GET /api/widgets/{scope}/registry.json

Static-shaped registry for one scope, used by the dashboard for fast bulk fetch on first load. Edge-cacheable (the route sets no Cache-Control). No CORS header (see Conventions): fetch server-to-server only.

Operational endpoints

Unauthenticated, unversioned tooling and status endpoints outside /v1/: GET /api/health, GET /api/version (latest Hub release), GET /api/widgets/cli-version (minimum supported widget-cli version), GET /api/stats, GET /api/settings. No stability guarantee or CORS header; not an integration surface.

Rate limits

Currently unmetered. Be reasonable; aggressive scraping may get rate-limited later with 429 + Retry-After.

Reporting issues

Bug Reports. Include the full request (URL + payload) and the response (status + body).