API reference
The registry site exposes a small public read API plus a download endpoint
the hermesone CLI calls on install. All read endpoints send permissive CORS
(Access-Control-Allow-Origin: *), so they're usable from the browser.
Base URL: your deployment (e.g. https://registry.hermesone.org).
Entries
GET /api/entries
Paginated, filtered list with facets.
Query params: type, category, tag, q (full-text), sort
(name | downloads | type | relevance), page, limit (max 100).
{
"total": 237,
"page": 1,
"limit": 24,
"pageCount": 10,
"entries": [ /* entry rows incl. live `downloads` */ ],
"facets": { "types": [...], "categories": [...], "tags": [...] }
}
GET /api/entries/:type/:id
One entry's metadata plus resolved detail.
:typeis singular:skill|mcp|agent|workflow.:idis the entry id (URL-encode it if it contains/).
{
"entry": { "type": "mcp", "id": "github", "name": "GitHub", "version": "1.1.0",
"path": "mcp/github", "category": null, "downloads": 42, "...": "..." },
"manifest": { /* the entry's manifest.json */ },
"markdown": "…", // SKILL.md / AGENT.md when present
"frontmatter": {}, // skills
"workflow": null, // workflows
"readme": null
}
Returns 404 { "error": "not_found" } for unknown entries.
POST /api/entries/:type/:id/download
Records an install: increments the entry's counter, appends an event, and
returns the new total. Called by hermesone add.
Request body (optional):
{ "version": "1.1.0", "source": "cli" }
Response:
{ "ok": true, "type": "mcp", "id": "github", "downloads": 43 }
404 { "error": "not_found" } if the entry doesn't exist. OPTIONS is handled
for CORS preflight.
The
entries.downloadscolumn is the fast read; every install also appends to an append-onlydownload_eventslog (with a hashed IP) for analytics.
Models
GET /api/models
The full model catalog (providers + their models).
GET /api/models/:provider
One provider's catalog.
Data flow
The catalog on GitHub is the source of truth. A seed step ingests index.json,
models.json, and the per-entry folders into Postgres; pages and these
endpoints query Postgres per request, so download counts are always live and new
entries appear without a rebuild. Re-seeding never resets download counters. See
web/WEB.md for the data model and deployment.