Reference
API reference
Every route the hub answers, grouped by what it is for, generated from the OpenAPI document.
MarkdownOne base URL, no key for any read. Everything below is generated at build time from /openapi.json, the OpenAPI 3.1 document that describes the whole endpoint, so a route cannot appear here without being described there. The interactive rendering of the same document is at /docs.
https://gethologram.ai
| Placeholder | Meaning | Example |
|---|---|---|
{owner}/{name} |
a model id, as on Hugging Face | hexgrad/Kokoro-82M |
{revision} |
main, or the commit the hub indexed |
f3ff3571791e39611d31c381e3a41a3af07b4987 |
{path} |
a file inside the model; may contain slashes | voices/af_heart.pt |
{source} |
huggingface, modelscope or ipfs |
ipfs |
{id} |
an object address | blake3:3cc11e52… |
Models
Find a model and read its files, in Hugging Face's shape. This is the dialect every Python client already speaks.
GET/api/models
Search the index.
Hugging Face's list shape, so HfApi.list_models works unchanged, plus a hologram block on every row
carrying the facts Hugging Face has no field for: the index address of the model, how many files it has,
how many bytes of weights, and which sources hold them. A search costs a few hundred bytes; reading the
whole catalog object costs several hundred KB, so search here rather than there.
This route lists everything the hub holds, not only what is trending today. Rows for models on the
current browse list carry the full facts — task, parameters, library, downloads, licence. Models the browse
list has forgotten, but whose bytes this hub has published and still serves, appear as thin rows: the name,
the index address, and hologram.listed: false. The facts a browse row carries were never published with
the object, so a thin row says so rather than reporting zeros as if they were measurements. Filter on
hologram.listed if you want one kind or the other.
Query parameters are checked rather than coerced: a limit outside 1–500 or one that is not a whole number,
and a sort outside the enum, each refuse with 400 BadParameter and a sentence saying what is allowed.
| Parameter | In | Type | Description |
|---|---|---|---|
search optional | query | string | Case-insensitive substring of the model id. |
author optional | query | string | Exact owner match. |
pipeline_tag optional | query | string | Exact task match. |
library optional | query | string | Exact library match. |
filter optional | query | array of string | Tag that must be present. Repeat the parameter, or comma-separate. Tags include the task, the library, the format, the architecture, license:<id> and languages. |
sort optional | query | downloads, likes, trendingScore, trending_score, createdAt, created_at | Sort key. |
direction optional | query | string | 1 sorts ascending. Anything else sorts descending. |
limit optional | query | integer | Rows to return, 1 to 500. |
| Status | Meaning |
|---|---|
200 | Matching rows, most relevant first by the chosen sort. application/json |
400 | A parameter is outside what this operation accepts. application/json |
405 | The hub endpoint is read-only: any method other than GET or HEAD on this path is refused. application/json |
GET/api/models/{owner}/{name}
One model at the indexed revision.
Hugging Face's model-info shape. sha is the revision the hub pinned; siblings lists every file. For sizes and hashes ask for the tree instead.
| Parameter | In | Type | Description |
|---|---|---|---|
owner | path | string | The owning organisation or user, exactly as on Hugging Face. |
name | path | string | The model name. |
| Status | Meaning |
|---|---|
200 | The model. application/json |
403 | The model is gated on Hugging Face. The hub serves public models only and will not proxy a gate. application/json |
404 | Not in the index. The request is recorded and considered for the next index run. application/json |
GET/api/models/{owner}/{name}/revision/{revision}
One model, asserting the revision.
The same answer as getModel, refused unless the revision you name is the one the hub indexed. Use it to fail loudly rather than silently receive a different revision.
| Parameter | In | Type | Description |
|---|---|---|---|
owner | path | string | The owning organisation or user, exactly as on Hugging Face. |
name | path | string | The model name. |
revision | path | string | main, or a commit prefix of at least seven characters. The hub indexes one revision per model and refuses any other, so main is always the pinned revision. |
| Status | Meaning |
|---|---|
200 | The model. application/json |
404 | Either the model is not indexed, or it is indexed at another revision. application/json |
GET/api/models/{owner}/{name}/refs
The branches the hub knows.
Always exactly one branch, main, pointing at the indexed revision. Clients call this before a download to turn main into a commit.
| Parameter | In | Type | Description |
|---|---|---|---|
owner | path | string | The owning organisation or user, exactly as on Hugging Face. |
name | path | string | The model name. |
| Status | Meaning |
|---|---|
200 | One branch, no tags. application/json |
404 | Not in the index. application/json |
GET/api/models/{owner}/{name}/tree/{revision}
Every file, with its size and its SHA-256.
oid is the SHA-256 of the file's bytes, which is the value you check a download against. This is the only place the expected hashes come from: never take a hash from the source that serves the bytes.
| Parameter | In | Type | Description |
|---|---|---|---|
owner | path | string | The owning organisation or user, exactly as on Hugging Face. |
name | path | string | The model name. |
revision | path | string | main, or a commit prefix of at least seven characters. The hub indexes one revision per model and refuses any other, so main is always the pinned revision. |
| Status | Meaning |
|---|---|
200 | One entry per file. application/json |
404 | Not in the index, or indexed at another revision. application/json |
GET/api/models/{owner}/{name}/tree/{revision}/{prefix}
The files under one directory.
The same entries, filtered to one directory prefix.
| Parameter | In | Type | Description |
|---|---|---|---|
owner | path | string | The owning organisation or user, exactly as on Hugging Face. |
name | path | string | The model name. |
revision | path | string | main, or a commit prefix of at least seven characters. The hub indexes one revision per model and refuses any other, so main is always the pinned revision. |
prefix | path | string | Directory prefix, with or without a trailing slash. |
| Status | Meaning |
|---|---|
200 | One entry per file under the prefix; empty if nothing matches. application/json |
404 | Not in the index, or indexed at another revision. application/json |
GET/api/models/{owner}/{name}/xet-read-token/{revision}
Hand a Xet client back to Hugging Face.
huggingface_hub follows the hub's redirect, meets Hugging Face's Xet headers there, then asks this endpoint for a Xet read token. That token is Hugging Face's to give, so the hub sends the client there and issues nothing itself.
| Parameter | In | Type | Description |
|---|---|---|---|
owner | path | string | The owning organisation or user, exactly as on Hugging Face. |
name | path | string | The model name. |
revision | path | string | main, or a commit prefix of at least seven characters. The hub indexes one revision per model and refuses any other, so main is always the pinned revision. |
| Status | Meaning |
|---|---|
307 | Redirect to the same path on huggingface.co. |
405 | The hub endpoint is read-only: any method other than GET or HEAD on this path is refused. application/json |
Files
Turn a model file into a URL that is up right now, together with the SHA-256 it must have.
GET/{owner}/{name}/resolve/{revision}/{path}
A URL for one file, at a source that is up.
The route every download goes through. The hub answers 302 to the first source in its preference order
that passed the last probe, and puts the expected SHA-256 in ETag and X-Linked-Etag and the serving
source in X-Hub-Source. No weight byte passes through the hub.
Ask for the path SHA256SUMS and the hub synthesises the checksum file for the whole model instead, so a
download can be checked with sha256sum -c and no tool of ours.
| Parameter | In | Type | Description |
|---|---|---|---|
owner | path | string | The owning organisation or user, exactly as on Hugging Face. |
name | path | string | The model name. |
revision | path | string | main, or a commit prefix of at least seven characters. The hub indexes one revision per model and refuses any other, so main is always the pinned revision. |
path | path | string | The file path inside the repository. It may contain slashes; do not encode them. The literal path SHA256SUMS is synthesised by the hub and is not a file of the repository. |
| Status | Meaning |
|---|---|
200 | Only for the synthesised SHA256SUMS path: the checksum file itself. text/plain |
302 | Follow Location for the bytes, then check them against ETag. |
404 | The model is not indexed, the revision is not the indexed one, or the file is not in it. application/json |
GET/via/{source}/{owner}/{name}/resolve/{revision}/{path}
A URL for one file, from the source you name.
The caller states the policy and the hub executes it: /via/ipfs/... serves from IPFS even when Hugging
Face is up. The prefix works in front of any Models or Files route, not only this one.
A pin is a constraint, not a hint. If the named source does not hold the file this refuses with
404 SourceHasNotGotIt, naming the sources that do; an unrecognised source name refuses with
404 UnknownSource. It does not quietly serve you something else. That matters most for the obvious use of
a pin — fetching the same file through two sources and comparing them — which is worthless if one fetch can
silently come from the other's host.
X-Hub-Source still names who served, and on this route it will always equal the source you asked for.
Drop the prefix to let the hub choose by health and order.
| Parameter | In | Type | Description |
|---|---|---|---|
source | path | huggingface, modelscope, ipfs | Pin one byte source instead of letting the hub choose. |
owner | path | string | The owning organisation or user, exactly as on Hugging Face. |
name | path | string | The model name. |
revision | path | string | main, or a commit prefix of at least seven characters. The hub indexes one revision per model and refuses any other, so main is always the pinned revision. |
path | path | string | The file path inside the repository. It may contain slashes; do not encode them. The literal path SHA256SUMS is synthesised by the hub and is not a file of the repository. |
| Status | Meaning |
|---|---|
200 | Only for the synthesised SHA256SUMS path, which the prefix reaches like any other. text/plain |
302 | Redirect to a source. Check X-Hub-Source: it names who actually served, which is not always the source you asked for. |
404 | Unknown model, revision or file; SourceHasNotGotIt when the named source does not hold this file, naming the ones that do; or UnknownSource when the source name is not one this hub knows. A malformed source segment, such as one with capitals, is refused by the edge as a bare 404 with an empty body rather than in this shape. application/json |
405 | The hub endpoint is read-only: any method other than GET or HEAD on this path is refused. application/json |
GET/via/{source}/api/models
Search with a source pinned for what follows.
The same rows as listModels. The prefix is accepted on every read route so a client can be configured once, with HF_ENDPOINT=https://gethologram.ai/via/ipfs, and never choose again.
| Parameter | In | Type | Description |
|---|---|---|---|
source | path | huggingface, modelscope, ipfs | Pin one byte source instead of letting the hub choose. |
| Status | Meaning |
|---|---|
200 | Matching rows. application/json |
405 | The hub endpoint is read-only: any method other than GET or HEAD on this path is refused. application/json |
Registry
The OCI distribution dialect: Ollama pulls, CNCF ModelPack artifacts, and the hub's own daily index. Reads are anonymous; a write is refused at the edge unless it carries the registry token that docker login sends, and writes are not described here because only the hub publishes.
GET/v2/
The OCI distribution entry point.
200 {} means version 2 of the distribution API is supported and reads are anonymous. docker login is needed only to push.
| Status | Meaning |
|---|---|
200 | The registry speaks the v2 API. application/json |
401 | A write was attempted without a registry token. Reads never need one. text/plain |
GET/v2/_catalog
The repositories the hub's own registry holds.
The hub's registry namespace only, model-hub/index among them. Model repositories are answered from the index and do not appear here; ask for a model's tags directly.
| Status | Meaning |
|---|---|
200 | Repository names. application/json |
401 | A write was attempted without a registry token. Reads never need one. text/plain |
GET/v2/{owner}/{name}/tags/list
The tags a model can be pulled by.
latest always, plus one tag per single-file GGUF quantisation, which is what ollama pull …:Q4_K_M asks for. Owner and name must be lowercase: OCI references are case-sensitive and lowercase-only.
| Parameter | In | Type | Description |
|---|---|---|---|
owner | path | string | The owning organisation or user, exactly as on Hugging Face. |
name | path | string | The model name. |
| Status | Meaning |
|---|---|
200 | The tag list. application/json |
404 | Not in the index. application/json |
GET/v2/{owner}/{name}/manifests/{reference}
A model as an OCI artifact.
One route, two answers, chosen by Accept. Send the OCI manifest type and the hub answers a CNCF ModelPack
artifact whose layers are the model's files, each layer digest being that file's SHA-256, which oras,
modctl, skopeo and crane all verify for you. Send the Docker manifest type, which is what Ollama sends,
and the hub answers a GGUF model manifest; models with no GGUF file refuse it.
| Parameter | In | Type | Description |
|---|---|---|---|
owner | path | string | The owning organisation or user, exactly as on Hugging Face. |
name | path | string | The model name. |
reference | path | string | A tag, or a manifest digest asked for again. |
Accept optional | header | string | application/vnd.oci.image.manifest.v1+json for ModelPack, application/vnd.docker.distribution.manifest.v2+json for Ollama. |
| Status | Meaning |
|---|---|
200 | The manifest. Every layer digest is the SHA-256 of one file of the model. application/vnd.oci.image.manifest.v1+json, application/vnd.docker.distribution.manifest.v2+json |
404 | Not in the index, or asked for a GGUF manifest of a model that has none. application/json |
GET/v2/{owner}/{name}/blobs/{digest}
One layer of a model artifact.
Small layers (config, chat template, parameters) are answered directly, each checked against its digest before the hub keeps it. Weight layers are a redirect to a live source; the client verifies the digest, as every OCI client already does. HEAD answers 200 with the size directly, because newer Ollama refuses a cross-host redirect on HEAD.
| Parameter | In | Type | Description |
|---|---|---|---|
owner | path | string | The owning organisation or user, exactly as on Hugging Face. |
name | path | string | The model name. |
digest | path | string | sha256:<64 hex>, the SHA-256 of the file's bytes. |
| Status | Meaning |
|---|---|
200 | A small layer, in full. application/octet-stream |
307 | A weight layer: follow Location, then verify the digest. |
404 | No such blob in this model at the indexed revision. application/json |
MCP
The Model Context Protocol server, for agents that bind to tools rather than to routes.
POST/mcp
The Model Context Protocol server.
Streamable HTTP, stateless, anonymous, POST only. Protocol versions 2026-07-28, 2025-11-25,
2025-06-18 and 2025-03-26 are accepted. Three tools: search_models finds one, get_model lists its
files with sizes and hashes, resolve_file gives a URL, the SHA-256 it must have, and the command that
hands the file to an engine.
Weight bytes never travel in a tool result: the tool returns the instruction, the agent's shell or engine does the download.
get_model returns at most 200 files. When a model has more it keeps every config, tokenizer and other
small text file first, fills the remainder with the largest weights, and sets files_truncated and
files_truncated_note; files_total always counts the whole model. It truncates by usefulness rather than
alphabetically, because the tail of a model directory is where the tokenizer lives and a caller cannot
proceed without it. For the complete list use listModelFiles.
Body: application/json — A JSON-RPC 2.0 request.
| Status | Meaning |
|---|---|
200 | A JSON-RPC 2.0 response. A tool that fails answers 200 with result.isError set, as the protocol requires. application/json |
405 | GET and DELETE are refused: the server keeps no session, so there is no stream to open or close. application/json |
Objects
The content-addressed floor under every dialect. An object is named by the BLAKE3 of its bytes, so its answer can be cached forever.
GET/api/v1/capabilities
What this server can do.
Every operation the server exposes, which modules are loaded, and the hard limits. maximum_message_bytes is 32 MiB: anything larger is published as chunks.
| Status | Meaning |
|---|---|
200 | The capability manifest. application/json |
404 | The edge routes only GET and HEAD to this path; anything else falls through to the catch-all. text/plain |
GET/api/v1/modules
The modules that are loaded.
One entry per module, with the operations it owns and whether it is ready.
| Status | Meaning |
|---|---|
200 | Success. application/json |
404 | The edge routes only GET and HEAD to this path; anything else falls through to the catch-all. text/plain |
GET/api/v1/objects
List stored objects.
Needs a publisher token. Reading a known address needs none. There is no anonymous listing, on purpose: the catalog is the public index and it is one object away.
Auth: publisherToken
| Status | Meaning |
|---|---|
200 | Success. application/json |
401 | No publisher token. text/plain |
POST/api/v1/objects
Publish an object.
The body is the bytes; the response id is their BLAKE3 address. Up to 8 MiB per request at the edge, 32 MiB at the server. Larger payloads are published as chunks and joined by a source record.
Auth: publisherToken
| Parameter | In | Type | Description |
|---|---|---|---|
content-type optional | header | string,null | Stored media type |
x-hologram-kind optional | header | string,null | Object kind; defaults to file |
x-hologram-filename optional | header | string,null | Original filename |
Body: application/octet-stream — The object's bytes.
| Status | Meaning |
|---|---|
201 | Success. application/json |
401 | No publisher token. text/plain |
GET/api/v1/objects/{id}
One object, by the hash of its bytes.
The content-addressed floor. The answer for an address never changes, so it is served immutable with a one-year lifetime and may be cached forever. The server does not verify on read: hash what arrives and keep it only if the BLAKE3 equals the address you asked for.
| Parameter | In | Type | Description |
|---|---|---|---|
id | path | string | blake3:<64 hex>, the hash of the object's bytes. |
| Status | Meaning |
|---|---|
200 | The object's bytes, served under the media type they were published with. The hub publishes application/vnd.hologram.model-hub.catalog.v1+json for a catalog, …model.v1+json for one model revision and …source.v1+json for one place its bytes can be fetched; anything else published here keeps its own type, and an object stored without one is served as opaque bytes. Match on the address, not on the media type. application/vnd.hologram.model-hub.catalog.v1+json, application/vnd.hologram.model-hub.model.v1+json, application/vnd.hologram.model-hub.source.v1+json, application/octet-stream |
400 | The path is not an address. An address is blake3: followed by 64 hexadecimal characters; anything else under this prefix is refused at the edge rather than passed to the server. application/json |
404 | No object at that address. application/json |
Account
The only surface that needs a person. Everything else on this endpoint is anonymous, and signing in adds nothing to it: an account exists so that a saved list, an attributed model request and a recorded interest in publishing have somewhere to live. Signing in grants no read that anonymous callers do not already have, and publishing access is an operator's decision, not a form's.
GET/api/account/health
Is sign-in available.
The one account route that needs no token. configured: false means this hub has no sign-in keys, which changes nothing for anonymous callers.
| Status | Meaning |
|---|---|
200 | Whether the account service is up and configured. application/json |
404 | Any other path under /api/account that is not a route answers 404 once the caller is signed in. application/json |
GET/api/account/me
The signed-in account.
What the hub holds for this person: nothing but a saved list, the models they asked for, and a wallet address they chose to report.
Auth: privyToken
| Status | Meaning |
|---|---|
200 | The account. application/json |
401 | Not signed in, or the token is not this hub's to accept. application/json |
429 | Too many requests from this account. application/json |
503 | Sign-in is not configured on this hub. Every anonymous surface still works. application/json |
PATCH/api/account/me
Record or clear a wallet address.
The address is Privy's to mint and the page's to report. It is recorded and never trusted for anything.
Auth: privyToken
Body: application/json
| Status | Meaning |
|---|---|
200 | The address as it now stands. application/json |
400 | Not an address. application/json |
401 | Not signed in, or the token is not this hub's to accept. application/json |
429 | Too many requests from this account. application/json |
503 | Sign-in is not configured on this hub. Every anonymous surface still works. application/json |
POST/api/account/saved
Save a model to this account.
A list the person keeps, nothing more. It is not a download, a pin or a claim on anything.
Auth: privyToken
Body: application/json
| Status | Meaning |
|---|---|
200 | The saved list. application/json |
400 | Not a model id. application/json |
401 | Not signed in, or the token is not this hub's to accept. application/json |
409 | The saved list is full. application/json |
429 | Too many requests from this account. application/json |
503 | Sign-in is not configured on this hub. Every anonymous surface still works. application/json |
DELETE/api/account/saved/{model}
Remove a model from the saved list.
Removing something that is not there is not an error.
Auth: privyToken
| Parameter | In | Type | Description |
|---|---|---|---|
model | path | string | The model id, URL-encoded (the slash included). |
| Status | Meaning |
|---|---|
200 | The saved list as it now stands. application/json |
401 | Not signed in, or the token is not this hub's to accept. application/json |
429 | Too many requests from this account. application/json |
503 | Sign-in is not configured on this hub. Every anonymous surface still works. application/json |
POST/api/account/request
Ask for a model to be indexed.
The anonymous version of this already happens: the endpoint records every model it is asked for and does not have. Signing in only adds attribution, so the operator can tell one person asking ten times from ten people asking once.
Auth: privyToken
Body: application/json
| Status | Meaning |
|---|---|
200 | Recorded. application/json |
400 | Not a model id. application/json |
401 | Not signed in, or the token is not this hub's to accept. application/json |
409 | This account has asked for enough for now. application/json |
429 | Too many requests from this account. application/json |
503 | Sign-in is not configured on this hub. Every anonymous surface still works. application/json |
POST/api/account/publisher-request
Record an interest in publishing.
It issues nothing and grants nothing. Who may write to this registry is an operator's decision, and a decision is not something a web form gets to make.
Auth: privyToken
Body: application/json
| Status | Meaning |
|---|---|
202 | Recorded, and nothing was issued. application/json |
401 | Not signed in, or the token is not this hub's to accept. application/json |
429 | Too many requests from this account. application/json |
503 | Sign-in is not configured on this hub. Every anonymous surface still works. application/json |
Health
Is the endpoint up, and which byte sources are up behind it.
GET/healthz
Is the endpoint up.
The Hologram Server behind the object routes. status: ready means the object plane answers; it says nothing about byte sources, which have their own probe.
| Status | Meaning |
|---|---|
200 | The server is up. application/json |
404 | The edge routes only GET and HEAD to this path; anything else falls through to the catch-all. text/plain |
GET/api/hub/health
Which byte sources are up, as seen from the hub.
The result of the hub's own periodic probe of every source it can redirect to, and the order it prefers them in. A file request is sent to the first source in order that is ok.
This is measured from the hub, not from you. A source reported ok here can still be unreachable from the network you are on — ipfs.filebase.io in particular is blocked or TLS-terminated on some networks while the hub reaches it fine. Read this as the hub's routing preference, not as a promise about your own failover. If failover matters to you, test a /via/{source} fetch from where your code will actually run.
| Status | Meaning |
|---|---|
200 | Per-source liveness and the preference order. application/json |
405 | The hub endpoint is read-only: any method other than GET or HEAD on this path is refused. application/json |
Discovery
What this endpoint is, in a form a machine can bind to without reading prose.
GET/
The hub, answered three ways.
One URL, three readers, chosen by Accept.
A browser sends text/html and gets the website. A caller that asks for application/json by name gets the
descriptor, which points at today's catalog address and at everything else here. Anything else — */*, which
is what curl, node's fetch and python's requests all send, and therefore what an arriving agent actually
asks — gets agent.md: the whole hub on one screen, in the imperative, ending in a check it can run itself.
So curl gethologram.ai is the shortest useful thing an agent can be told about this service.
| Parameter | In | Type | Description |
|---|---|---|---|
Accept optional | header | string | text/html for the site, application/json for the descriptor, anything else for the brief. |
| Status | Meaning |
|---|---|
200 | The website, the descriptor or the brief, depending on what was asked for. application/json, text/markdown, text/html |
405 | The hub endpoint is read-only: any method other than GET or HEAD on this path is refused. application/json |
GET/.well-known/model-hub.json
The hub descriptor at its well-known path.
The same bytes as GET / with Accept: application/json. Start here if you were given nothing but the host name.
| Status | Meaning |
|---|---|
200 | The descriptor. application/json |
404 | This document describes a deployment that serves this path; a hub that has not been updated to it answers 404 here. Fall back to /llms.txt, which every deployment serves. text/plain |
GET/openapi.json
This document.
The whole endpoint, every dialect, in one OpenAPI 3.1 document. /docs renders it. Both paths serve the same bytes; the well-known one exists because that is where an agent looks first.
| Status | Meaning |
|---|---|
200 | This document. application/json |
404 | This document describes a deployment that serves this path; a hub that has not been updated to it answers 404 here. Fall back to /llms.txt, which every deployment serves. text/plain |
GET/.well-known/openapi.json
This document.
The whole endpoint, every dialect, in one OpenAPI 3.1 document. /docs renders it. Both paths serve the same bytes; the well-known one exists because that is where an agent looks first.
| Status | Meaning |
|---|---|
200 | This document. application/json |
404 | This document describes a deployment that serves this path; a hub that has not been updated to it answers 404 here. Fall back to /llms.txt, which every deployment serves. text/plain |
GET/.well-known/agent-card.json
An agent card for this endpoint.
The hub described as a set of skills, for frameworks that discover services through an agent card rather than an OpenAPI document.
| Status | Meaning |
|---|---|
200 | The agent card. application/json |
404 | This document describes a deployment that serves this path; a hub that has not been updated to it answers 404 here. Fall back to /llms.txt, which every deployment serves. text/plain |
GET/agent.md
The whole hub, for the agent that just arrived.
One screen of plain markdown: what this is, the one line that switches an existing tool over, the three requests that use it directly, and the rule that makes the bytes safe. It is what GET / answers to anything that is not a browser, and it ends with a check the reader can run to confirm the rest. The last line is a canary: a fetcher that summarises drops it, and an agent that cannot see it knows to fetch this path again verbatim.
| Status | Meaning |
|---|---|
200 | Markdown, a few hundred lines at most. text/markdown, text/plain |
404 | This document describes a deployment that serves this path; a hub that has not been updated to it answers 404 here. Fall back to /llms.txt, which every deployment serves. text/plain |
GET/models
The models section, answered two ways.
The site shows this address beside the models heading — the same tag on every section, so one shape
covers all five. A browser gets the section's page; anything else gets a brief covering
finding a model, proving it and fetching it: the few requests that do the job, in the order you would make them, with the rule that makes
the bytes safe.
Ask for application/json and the same address answers a section descriptor: one fixed shape, the
same on all five sections, naming how to enumerate this section, how to reach one item, how to fetch
its bytes and how to check them. Where the section has a snapshot, catalog.address is a content
address holding the whole of it, so the entire section is one verifiable fetch. Where it has none the
field is null and list carries a live route instead; no section borrows a catalogue it does not have.
It adds no API — every route the descriptor names is already in this document. What was missing was an
address that gathers them, which the site was already advertising. The trailing slash works either way,
and a page below the section, such as a single model or one docs page, is untouched.
| Status | Meaning |
|---|---|
200 | The section descriptor to a caller that asked for JSON, the section brief to any other non-browser, and the section's page to a browser. application/json, text/markdown, text/html |
404 | This document describes a deployment that serves this path; a hub that has not been updated to it answers 404 here. Fall back to /llms.txt, which every deployment serves. text/plain |
GET/registry
The registry section, answered two ways.
The site shows this address beside the registry heading — the same tag on every section, so one shape
covers all five. A browser gets the section's page; anything else gets a brief covering
pulling the same models as OCI artifacts: the few requests that do the job, in the order you would make them, with the rule that makes
the bytes safe.
Ask for application/json and the same address answers a section descriptor: one fixed shape, the
same on all five sections, naming how to enumerate this section, how to reach one item, how to fetch
its bytes and how to check them. Where the section has a snapshot, catalog.address is a content
address holding the whole of it, so the entire section is one verifiable fetch. Where it has none the
field is null and list carries a live route instead; no section borrows a catalogue it does not have.
It adds no API — every route the descriptor names is already in this document. What was missing was an
address that gathers them, which the site was already advertising. The trailing slash works either way,
and a page below the section, such as a single model or one docs page, is untouched.
/v2/ itself is deliberately left alone: it is a protocol endpoint and OCI clients depend on exactly what it returns.
| Status | Meaning |
|---|---|
200 | The section descriptor to a caller that asked for JSON, the section brief to any other non-browser, and the section's page to a browser. application/json, text/markdown, text/html |
404 | This document describes a deployment that serves this path; a hub that has not been updated to it answers 404 here. Fall back to /llms.txt, which every deployment serves. text/plain |
GET/spaces
The spaces section, answered two ways.
The site shows this address beside the spaces heading — the same tag on every section, so one shape
covers all five. A browser gets the section's page; anything else gets a brief covering
browser-only apps, each sealed under one root digest, and how to read one from the registry: the few requests that do the job, in the order you would make them, with the rule that makes
the bytes safe.
Ask for application/json and the same address answers a section descriptor: one fixed shape, the
same on all five sections, naming how to enumerate this section, how to reach one item, how to fetch
its bytes and how to check them. Where the section has a snapshot, catalog.address is a content
address holding the whole of it, so the entire section is one verifiable fetch. Where it has none the
field is null and list carries a live route instead; no section borrows a catalogue it does not have.
It adds no API — every route the descriptor names is already in this document. What was missing was an
address that gathers them, which the site was already advertising. The trailing slash works either way,
and a page below the section, such as a single model or one docs page, is untouched.
| Status | Meaning |
|---|---|
200 | The section descriptor to a caller that asked for JSON, the section brief to any other non-browser, and the section's page to a browser. application/json, text/markdown, text/html |
404 | This document describes a deployment that serves this path; a hub that has not been updated to it answers 404 here. Fall back to /llms.txt, which every deployment serves. text/plain |
GET/buckets
The buckets section, answered two ways.
The site shows this address beside the buckets heading — the same tag on every section, so one shape
covers all five. A browser gets the section's page; anything else gets a brief covering
walking a bucket as an OCI index tree and checking every block against its address: the few requests that do the job, in the order you would make them, with the rule that makes
the bytes safe.
Ask for application/json and the same address answers a section descriptor: one fixed shape, the
same on all five sections, naming how to enumerate this section, how to reach one item, how to fetch
its bytes and how to check them. Where the section has a snapshot, catalog.address is a content
address holding the whole of it, so the entire section is one verifiable fetch. Where it has none the
field is null and list carries a live route instead; no section borrows a catalogue it does not have.
It adds no API — every route the descriptor names is already in this document. What was missing was an
address that gathers them, which the site was already advertising. The trailing slash works either way,
and a page below the section, such as a single model or one docs page, is untouched.
| Status | Meaning |
|---|---|
200 | The section descriptor to a caller that asked for JSON, the section brief to any other non-browser, and the section's page to a browser. application/json, text/markdown, text/html |
404 | This document describes a deployment that serves this path; a hub that has not been updated to it answers 404 here. Fall back to /llms.txt, which every deployment serves. text/plain |
GET/models/
The models, browsed.
The browse page: every model the hub lists, with its files, sizes and addresses. For people; anything that is not a browser gets the section brief instead of 236 KB of markup. A page below this one, such as a single model, is untouched by that and always answers HTML.
| Status | Meaning |
|---|---|
200 | The page to a browser; to anything else the section brief, the same bytes as /models. text/html, text/markdown |
404 | This document describes a deployment that serves this path; a hub that has not been updated to it answers 404 here. Fall back to /llms.txt, which every deployment serves. text/plain |
GET/docs
This document, rendered.
A reference page for people, built from /openapi.json at load time. It is the same contract as the document; nothing is written twice.
| Status | Meaning |
|---|---|
200 | An HTML page. text/html |
404 | This document describes a deployment that serves this path; a hub that has not been updated to it answers 404 here. Fall back to /llms.txt, which every deployment serves. text/plain |
GET/docs/
The documentation.
Overview, quickstart, the concepts, one page per dialect, and a reference generated from this document.
Every page has a Markdown twin at /docs/{page}.md, and /llms.txt lists them all.
This is also the address the site shows beside the Docs heading, the same tag every section carries. A
browser gets this index; anything else gets the section brief, which lists every page and the address of
its twin, generated from the pages themselves. The slash is load-bearing: /docs without one is the
server's own API reference, on a different upstream.
| Status | Meaning |
|---|---|
200 | The descriptor to a caller that asked for JSON, the section brief to any other non-browser, the index to a browser. application/json, text/html, text/markdown |
404 | This document describes a deployment that serves this path; a hub that has not been updated to it answers 404 here. Fall back to /llms.txt, which every deployment serves. text/plain |
GET/docs/{page}/
One documentation page.
The page named by its slug: quickstart, verification, addresses, sources, huggingface, ollama, oci, mcp, objects, api, errors, limits.
| Parameter | In | Type | Description |
|---|---|---|---|
page | path | string | The page slug, as listed in /llms.txt. |
| Status | Meaning |
|---|---|
200 | An HTML page. text/html |
404 | No page has that slug. text/html |
GET/docs/{page}.md
One documentation page, as Markdown.
The same page as /docs/{page}/, from the same source, with every link resolved to an absolute Markdown twin. index.md is the overview.
| Parameter | In | Type | Description |
|---|---|---|---|
page | path | string | The page slug, as listed in /llms.txt. |
| Status | Meaning |
|---|---|
200 | Markdown. text/markdown |
404 | No page has that slug. text/plain |
GET/registry/
The hub's own registry, browsed.
A page over /v2/: every repository and tag the hub's registry holds, each layer verified in the browser against its digest. For people; a client uses /v2/ directly, and anything that is not a browser gets the section brief instead of the markup.
| Status | Meaning |
|---|---|
200 | The page to a browser; to anything else the section brief, the same bytes as /registry. text/html, text/markdown |
404 | This document describes a deployment that serves this path; a hub that has not been updated to it answers 404 here. Fall back to /llms.txt, which every deployment serves. text/plain |
GET/spaces/
Apps that run entirely in the browser, each in its own sealed frame.
Five demo Apps (speech, image, chat, vision, depth). Every file of an App is sealed under one root digest, its model bytes are accepted only when they re-derive to the digest the model index names, and nothing runs on a server. An App published to the registry lives at /v2/spaces/<id> as an OCI artifact of type application/vnd.hologram.space.v1+json.
| Status | Meaning |
|---|---|
200 | An HTML page. text/html |
404 | This document describes a deployment that serves this path; a hub that has not been updated to it answers 404 here. Fall back to /llms.txt, which every deployment serves. text/plain |
GET/spaces/spaces.json
The Apps catalog: id, sealed root, files, models and their sizes.
{ format: "hologram.spaces.catalog/v1", spaces: [{ id, name, task, tagline, root, bytes, files, models, modelHost, modelBytes, source, requires, entry }] }. root is SHA-256 over the App's file map; entry is the page to open.
| Status | Meaning |
|---|---|
200 | JSON. application/json |
404 | This document describes a deployment that serves this path; a hub that has not been updated to it answers 404 here. Fall back to /llms.txt, which every deployment serves. text/plain |
GET/llms.txt
The endpoint explained for an agent, shortest path first.
Prose, not a schema: what to do, in order, with the tools an agent already has. Read this when you would otherwise guess.
| Status | Meaning |
|---|---|
200 | Plain text. text/plain |
404 | This document describes a deployment that serves this path; a hub that has not been updated to it answers 404 here. Fall back to /llms.txt, which every deployment serves. text/plain |
GET/archive.json
Every day the hub has indexed.
One row per day: the index address, its IPFS CID, how many models and files it held, and the previous day. The chain lets anyone replay the hub's history and check each step.
| Status | Meaning |
|---|---|
200 | The archive ledger. application/json |
404 | This document describes a deployment that serves this path; a hub that has not been updated to it answers 404 here. Fall back to /llms.txt, which every deployment serves. text/plain |
GET/pins.json
Which models are pinned on IPFS.
The models whose weights the hub can still serve when Hugging Face and ModelScope are both unreachable, with the IPFS root of each and the gateway to read it through.
| Status | Meaning |
|---|---|
200 | The pin set. application/json |
404 | This document describes a deployment that serves this path; a hub that has not been updated to it answers 404 here. Fall back to /llms.txt, which every deployment serves. text/plain |
GET/robots.txt
Crawling policy.
Allows the website, the discovery paths and this document; asks crawlers to leave redirect and blob routes alone, because they cost a byte source real traffic.
| Status | Meaning |
|---|---|
200 | Plain text. text/plain |
404 | This document describes a deployment that serves this path; a hub that has not been updated to it answers 404 here. Fall back to /llms.txt, which every deployment serves. text/plain |