HTTP API
The public, read-only HTTP endpoints for the catalog, model files, listings and read-only project links, with parameters, responses and examples.
Before you start
Unversioned
These endpoints are what the Rack Maker app itself uses. They are not versioned and may change without notice. Don't build anything that can't cope with a field being added, renamed or removed.
- The endpoints on this page are read-only, need no account, and are safe to call from a script or
curl. - Every other endpoint (saving projects, drafting and publishing entries, uploading files, reporting, signing in, syncing between browsers, moderation) is for the app itself. They need a signed-in browser session and aren't documented here.
- Using an AI agent? Connect it to the MCP server instead of calling this API. The MCP server signs your agent in as you and gives it tools made for the job. See Agents.
All paths are relative to https://rack-maker.cbnsndwch.dev.
Responses and errors
Answers are JSON (content-type: application/json), unless noted. An error has an HTTP status and a body like this:
{ "error": "no such entry" }Some errors add a detail field. Unknown paths answer 404 with { "error": "not found" }.
Caching and limits
JSON answers are sent with cache-control: no-store: the server doesn't cache them, and nor should anything between you and it. If you poll, cache on your side and keep it gentle, say once every few minutes. The only cacheable answers are files (model files and link-preview images), noted below.
There is no search endpoint. The catalog page searches in your browser: to search, fetch the snapshot or the entry list and filter it yourself.
Catalog
Catalog ids are <namespace>/<slug>: the namespace is lowercase letters, digits and dashes; the slug may also contain dots. In paths, the namespace and slug are two segments. See Namespaces.
Catalog data is CC BY-SA 4.0: if you republish it, credit its authors and share alike. See Licences and credits.
GET /api/catalog/entries
One summary per entry, sorted by id.
curl https://rack-maker.cbnsndwch.dev/api/catalog/entries[
{
"id": "cbnsndwch/shelf-10in",
"name": "10″ shelf",
"kind": "part",
"category": "shelf",
"latestPublished": 1,
"hidden": false
}
]| Field | Meaning |
|---|---|
id, name, kind, category | the entry; kind is part or assembly |
latestPublished | the newest published revision number, or null if nothing is published yet |
hidden | true when a moderator (or enough reports) has hidden it; see Reports |
The list includes every entry, including ones with no published revision and hidden ones. Filter on latestPublished and hidden for what the catalog page shows.
GET /api/catalog/published
When each entry's newest published revision was published, and by whom: their handle (by), display name (name) and user id (user, the id entries' credits use). Hidden entries are left out. Newest first.
curl https://rack-maker.cbnsndwch.dev/api/catalog/published[
{
"id": "alice/mini-pc-tray",
"rev": 2,
"at": "2026-09-20T14:03:11.000Z",
"by": "alice",
"name": "Alice Chen",
"user": "github:1234567"
}
]Entries that ship with the app show system as by. at, by, name and user can be null.
GET /api/catalog/snapshot
Every published revision of every entry, with its full definition. This is what the catalog loads, and the easiest way to get everything at once.
curl https://rack-maker.cbnsndwch.dev/api/catalog/snapshot{
"entries": [{ "id": "cbnsndwch/shelf-10in", "rev": 1, "kind": "part", "name": "10″ shelf", "…": "…" }],
"statuses": { "cbnsndwch/shelf-10in@1": "published" },
"hidden": ["bob/spam-part"]
}| Field | Meaning |
|---|---|
entries | full entry definitions, one per revision (older revisions included), sorted by id and then revision |
statuses | each revision's status, keyed <id>@<rev>; without an account, always published |
hidden | ids of hidden entries. Their revisions are still in entries (projects that use them must still resolve), but don't offer them to people |
The fields of an entry are described in Authoring parts. To show "the" revision of each entry, take the highest published rev per id and skip hidden ids.
GET /api/catalog/entries/:namespace/:slug
The entry's revisions, newest first, without their definitions.
curl https://rack-maker.cbnsndwch.dev/api/catalog/entries/cbnsndwch/shelf-10in{
"id": "cbnsndwch/shelf-10in",
"canDraft": false,
"revisions": [
{
"id": "cbnsndwch/shelf-10in",
"rev": 1,
"status": "published",
"sha256": "9f2c…",
"authorId": "…",
"forkedFrom": null,
"createdAt": "2026-09-01T00:00:00.000Z",
"updatedAt": "2026-09-01T00:00:00.000Z",
"submittedAt": null,
"publishedAt": "2026-09-01T00:00:00.000Z",
"can": { "change": false, "review": false }
}
]
}| Field | Meaning |
|---|---|
revisions[].status | review, published or rejected (drafts are only shown to their author) |
revisions[].sha256 | a hash of the revision's definition |
revisions[].forkedFrom | <id>@<rev> it was copied from, if any |
revisions[].authorId | an opaque account id, not a handle |
canDraft, can | what the caller may do; always false without an account |
Answers 404 when there is no such entry.
GET /api/catalog/entries/:namespace/:slug/:rev
One revision, with its full definition in entry. The other fields are those of a revision in the list above, without can.
curl https://rack-maker.cbnsndwch.dev/api/catalog/entries/cbnsndwch/shelf-10in/1{
"id": "cbnsndwch/shelf-10in",
"rev": 1,
"status": "published",
"publishedAt": "2026-09-01T00:00:00.000Z",
"…": "…",
"entry": { "id": "cbnsndwch/shelf-10in", "rev": 1, "kind": "part", "name": "10″ shelf", "…": "…" }
}Without an account, only published revisions can be read. Anything else, or a rev that isn't a whole number from 1 up, answers 404.
Model files
Model files are the GLB and STL files catalog entries are drawn from. Each keeps its own licence: see Licences and credits. An entry that uses one has "geometry": { "kind": "mesh", "asset": { "asset": "<id>" } } in its definition, where the id is the file's SHA-256.
The files that ship with the app aren't in this API. Their ids start with bundled/, and they are served as static files from /models/, for example /models/rack-19in-12u.stl. Their credits are on the Credits page.
GET /api/assets
Without parameters: every model file that hasn't been taken down, newest first, up to 500. With ids: those files, taken down or not.
| Parameter | Meaning |
|---|---|
ids | optional: up to 200 file ids, separated by commas |
curl "https://rack-maker.cbnsndwch.dev/api/assets?ids=3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1b"[
{
"id": "3a7bd3e2…",
"kind": "mesh-glb",
"license": "CC-BY-4.0",
"bytes": 1843200,
"source": {
"origin": "third-party",
"provider": "Sketchfab",
"title": "Some switch",
"author": "someone",
"authorUrl": "https://…",
"url": "https://…",
"changes": "Scaled to fit the part's envelope.",
"acknowledgements": "…",
"retrievedAt": "2026-09-20T14:03:11.000Z"
},
"meta": { "format": "glb", "…": "…" },
"uploader": "alice",
"createdAt": "2026-09-20T14:03:11.000Z",
"hidden": false
}
]| Field | Meaning |
|---|---|
kind | mesh-glb or mesh-stl |
license | an SPDX-style id: CC0-1.0, CC-BY-4.0, CC-BY-SA-4.0, CC-BY-3.0, CC-BY-SA-3.0, MIT or Apache-2.0 |
source.origin | own (the uploader made it) or third-party |
source | where it comes from and whom to credit; optional fields may be null |
meta | what the server read from the file when it was uploaded |
uploader | the uploader's handle |
hidden | true when it was taken down after a report |
GET /api/assets/:id
One file's details, as a single object shaped like an item of the list above. 404 when there is no such file.
curl https://rack-maker.cbnsndwch.dev/api/assets/3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1bGET /api/assets/:id/file
The file itself, as model/gltf-binary (GLB) or model/stl (STL).
curl -o model.glb https://rack-maker.cbnsndwch.dev/api/assets/3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1b/file- Cached publicly for a day (
cache-control: public, max-age=86400). A file never changes under the same id, but it can be taken down. 410when it was taken down after a report;404when there is no such file.- Up to 15 MB.
Before you share the file, check its licence and credits with GET /api/assets/:id.
Listings
GET /api/listings
Where to get catalog entries: online shops and physical stores, each with its latest price and stock report. Hidden listings are left out.
| Parameter | Meaning |
|---|---|
ids | catalog entry ids, separated by commas, up to 200. Without it, the answer is {} |
curl "https://rack-maker.cbnsndwch.dev/api/listings?ids=cbnsndwch/shelf-10in,cbnsndwch/cage-nut-m6"{
"cbnsndwch/shelf-10in": [
{
"id": "V1StGXR8_Z5jdHi6B-myT",
"catalogId": "cbnsndwch/shelf-10in",
"vendor": "Some shop",
"url": "https://…",
"channel": "online",
"location": null,
"sku": null,
"region": null,
"kind": "new",
"packQty": 1,
"price": { "amount": 24.9, "currency": "EUR", "at": "2026-09-20T14:03:11.000Z" },
"stock": { "status": "in-stock", "at": "2026-09-20T14:03:11.000Z" }
}
]
}| Field | Meaning |
|---|---|
| (keys) | the catalog ids that have listings; ids without any are left out |
channel | online (with its product page in url) or store (a physical store at location; url may be null) |
kind | new, used, print-service or self-print |
packQty | items per purchase |
price | the latest price with its three-letter currency and date, or null |
stock | the latest stock report (in-stock, low or out-of-stock) with its date, or null |
Prices and stock are reported by contributors and dated. The app treats a price older than 90 days as stale. See BOM & quote.
Read-only project links
A project's owner can share a read-only link, /v/<token>, where the token is 21 characters of letters, digits, _ and -. See Sharing. These endpoints read what such a link shows. They never reveal the project's own id, which is what grants editing.
GET /api/view/:token
The project behind a read-only link, as it was last saved.
curl https://rack-maker.cbnsndwch.dev/api/view/Uakgb_J5m9g-0JDMbcJqL{
"project": {
"id": "",
"name": "Office rack",
"createdAt": "2026-09-10T09:00:00.000Z",
"updatedAt": "2026-09-20T14:03:11.000Z",
"claimed": true,
"mine": false
},
"state": {
"id": 0,
"version": 1790000000000,
"updatedAt": "2026-09-20T14:03:11.000Z",
"doc": { "…": "…" }
}
}| Field | Meaning |
|---|---|
project.id, state.id | always empty or 0 here |
project.name | may be null |
state | null when nothing has been saved yet |
state.version | changes on every save; compare it to see whether the project changed |
state.doc | the project: its racks and parts, each pointing at a catalog entry and revision |
404 with { "error": "no such link" } when the token matches no project.
GET /api/view/:token/og.jpg
The link-preview picture of a read-only link: a 1200 × 630 JPEG of the project in 3D. The owner's browser makes it while they have the project open, so a project may not have one yet. HEAD works too.
| Parameter | Meaning |
|---|---|
v | optional: the picture's version, as it appears in the page's og:image tag |
curl -o preview.jpg https://rack-maker.cbnsndwch.dev/api/view/Uakgb_J5m9g-0JDMbcJqL/og.jpg- With the current
v, the answer is cached for a year (immutable): a new picture gets a new version. Without it, or with an old one, it is cached for 5 minutes. - It carries an
ETag. 404when there is no such link or no picture yet. Link previews then use the site's default picture.
The easiest way to get the current URL, with its version, is the og:image tag in the HTML of /v/<token>.
Docs for agents
How AI agents can read these docs - llms.txt, llms-full.txt, any page as Markdown, Accept text/markdown, Copy Markdown, the Open menu and the sitemap.
FAQ
Short answers about accounts, privacy, sharing, prices, printing, contributing, licences, agents, browsers, exports and deleting things.