Browse searches AND browses the cross-org catalog: every project, app and site…
Browse searches AND browses the cross-org catalog: every project, app and site the fleet has built, whichever org built it.
GET /v1/catalog
| Address | https://api.hanzo.ai/v1/catalog |
| Method | GET |
| Operation | get_catalog |
| Auth | Authorization: Bearer $HANZO_API_KEY |
Browse searches AND browses the cross-org catalog: every project, app and site the fleet has built, whichever org built it.
It reads TWO corpora and returns them as one page — the published,
world-readable catalog that every caller sees, plus the caller's OWN org's
private entries when the request carries a validated principal. Each row says
which it came from in scope, so a client can warn before sharing a link. An
anonymous caller simply gets the published one; no filter can ever widen a
caller into another tenant's corpus, because the query that would return it is
never run for them.
A request with no q is a browse rather than a search, and both answer the same shape: the page, the total before paging, and the facet counts over the whole matching set.
Request
10 fields.
| Field | In | Type | Required | Description |
|---|---|---|---|---|
q | query | string | — | Q is the free-text query the lexical index scores relevance on. |
org | query | string | — | Org narrows to one builder org: hanzo | lux | zoo. |
kind | query | string | — | Kind narrows to repo | site. |
origin | query | string | — | Origin narrows to what a row IS to you: template | community | third-party | product. |
archetype | query | string | — | Archetype narrows to one project archetype. |
language | query | string | — | Language narrows to one implementation language. |
template | query | string | — | Template narrows a lane to ONE lineage: the id of the parent everything returned was forked from. |
forkable | query | string | — | Forkable is tri-state: "true" selects the forkable rows, "false" selects the rest, and anything else — including absent — applies no filter at all. |
limit | query | string | — | Limit caps the page at 200, default 50. |
offset | query | string | — | Offset is where the page starts, default 0, with the same tolerance. |
Response
| Status | Body | Meaning |
|---|---|---|
200 | catalogPage | ok |
200 body — 24 fields.
| Field | In | Type | Always | Description |
|---|---|---|---|---|
data | body | Entry[] | — | Data is the page of matching entries, most recently updated first. |
data[].archetype | body | string | — | Archetype is WHAT KIND OF THING this is, from a closed and ordered list — model | contract | chain | sdk | template | infra | site | app — derived from the… |
data[].description | body | string | — | Description is the repository's own one-line GitHub description, carried verbatim. |
data[].forkable | body | boolean | — | Forkable is NOT omitempty: false is an answer here, not a missing field. |
data[].id | body | string | — | ID is "<org>/<name>" and is the corpus's primary key: a re-published entry updates in place under it rather than accumulating duplicates, so it is the one… |
data[].kind | body | string | — | repo | site |
data[].language | body | string | — | Language is the repository's primary implementation language as GitHub computes it ("Go", "TypeScript"), and the case is GitHub's. |
data[].license | body | string | — | License is the terms that upstream work carries, in whichever form the half that credited it had: an SPDX id ("MIT", "Apache-2.0") on a GitHub fork, free text… |
data[].name | body | string | — | Name is the short identifier inside the org — the repository's name, or the site's slug — and is the half of ID after the slash. |
data[].note | body | string | — | Note is why a row is NOT in the published catalog, set by the admission gate (gate.go) on the sites it holds back. |
data[].org | body | string | — | hanzo | lux | zoo |
data[].origin | body | string | — | Origin is WHAT THIS IS TO YOU: template | community | third-party | product (origin.go owns the four nouns and derives them). |
data[].repo | body | string | — | source |
data[].scope | body | string | — | Scope is provenance, not storage: "public" for a row from the published corpus, "org" for one only this caller can see. |
data[].stars | body | integer | — | Stars is GitHub's stargazer count for the source repository, read at the last sync and never accumulated here. |
data[].template | body | string | — | lineage, if forked from one |
data[].title | body | string | — | Title is what to SHOW. A site's human name wins where it has one; a repo row falls back to the repository name, so on a repo this usually just repeats Name. |
data[].updated | body | string | — | Updated is when the thing last MOVED, as RFC 3339 in UTC: a repository's last push, or a site's last deploy. |
data[].upstream | body | string | — | Upstream/License credit the third-party work an entry was published from: the difference between "this org built it" and "somebody else built it and we are… |
data[].url | body | string | — | live, if it is deployed |
facets | body | object | — | Facets counts the whole matching set along every browse axis, so a rail a client renders is a rail that has results behind it. |
facets.* | body | object | — | |
facets.*.* | body | integer | — | |
total | body | integer | — | Total is how many entries matched BEFORE paging — what a pager sizes itself on. |
Failure carries the platform error shape — see Errors.
Examples
hanzo catalog getimport { Configuration, CatalogApi } from 'hanzoai';
const api = new CatalogApi(new Configuration({ accessToken: process.env.HANZO_API_KEY }));
const { data } = await api.getCatalog();from hanzoai.cloud import ApiClient, Configuration
from hanzoai.cloud.api import CatalogApi
client = ApiClient(Configuration(access_token=os.environ["HANZO_API_KEY"]))
result = CatalogApi(client).get_catalog()cfg := cloud.NewConfiguration()
cfg.AddDefaultHeader("Authorization", "Bearer "+os.Getenv("HANZO_API_KEY"))
client := cloud.NewAPIClient(cfg)
resp, _, err := client.CatalogAPI.GetCatalog(context.Background()).Execute()
if err != nil {
return err
}use hanzo_cloud::apis::{configuration::Configuration, catalog_api};
let mut cfg = Configuration::new();
cfg.bearer_access_token = std::env::var("HANZO_API_KEY").ok();
let result = catalog_api::get_catalog(&cfg, Default::default()).await?;import ai.hanzo.cloud.ApiClient;
import ai.hanzo.cloud.api.CatalogApi;
ApiClient client = new ApiClient();
client.setRequestInterceptor(b -> b.header("Authorization", "Bearer " + System.getenv("HANZO_API_KEY")));
var result = new CatalogApi(client).getCatalog();curl https://api.hanzo.ai/v1/catalog \
-H "Authorization: Bearer $HANZO_API_KEY"Tool catalog, op get_catalog — POST the JSON-RPC envelope to https://api.hanzo.ai/v1/mcp.
curl -X POST https://api.hanzo.ai/v1/mcp \
-H "Authorization: Bearer $HANZO_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "catalog",
"arguments": {
"op": "get_catalog",
"input": {}
}
}
}'How is this guide?