Queries
Query endpoints read data from a repository without modifying it. Public repositories can be queried without authentication.
To keep repository existence opaque, every deny path on these endpoints — anonymous requests against private repos, authenticated callers without sufficient scope, and lookups against missing repos — collapses to the same 404 response with Vary: Authorization. Authenticate with a token that has access to the repo to see real responses.
All paths are prefixed with /api/repos/:orgName/:repoName.
The query endpoints documented on this page are:
GET /headGET /about/:wrefGET /query
Other repository read routes (such as GET /export) are documented on their own pages and are not covered here.
Anonymous Pagination Caps
Section titled “Anonymous Pagination Caps”Anonymous callers (no Bearer token) on the routes below are subject to narrowed paging to discourage bulk crawling of public repos:
limitis capped at 25 items per page. Requests withlimit > 25return400with aVALIDATION_ERROR. Whenlimitis omitted, anonymous callers get a 25-item page (authenticated callers continue to get the helper’s 50-item default).- The page size is bound to the cursor. An anonymous follow-up that supplies
nextCursormust either omitlimit(and inherit the cursor’s page size) or pass the samelimitused for the previous page. Mixing a differentlimitwithnextCursorreturns400with aVALIDATION_ERROR. - Anonymous pagination stops after 2 pages. Following
nextCursorpast the second page returns404. Authenticate to continue paging.
Authenticated callers see no narrowing — they continue to use limit up to 500 and may follow nextCursor indefinitely.
Filtered Read Freshness
Section titled “Filtered Read Freshness”The endpoints on this page — GET /head, GET /about/:wref, and GET /query — all accept a match parameter for glob-filtered reads. A scoped Bearer token can also limit which wrefs a caller can see.
Filtered reads may lag briefly after a write while WarmHub updates its read indexes. Subsequent reads after the indexes catch up will see the new state. Unfiltered reads made with an unscoped token reflect the latest written data immediately.
Shape Membership and Closure Reads
Section titled “Shape Membership and Closure Reads”Two shape-membership read parameters exist on the CLI and SDK and are not part of the HTTP surface:
declaredShape(--declared-shape) filters to records that directly declare a shape, whereshapefilters to records of that shape name.includeValidatedShapes(--include-validated-shapes) adds avalidatedShapesarray to each returned item, carrying the full certified shape closure for that version.
GET /head, GET /about/:wref, and GET /query each forward a fixed set of query parameters, and neither parameter is in it. Unknown query parameters are ignored rather than rejected, so ?includeValidatedShapes=true returns an ordinary 200 with no validatedShapes field — not a 400. The MCP tools do not accept these parameters either.
The shapeless filter is not on the HTTP surface either. The CLI, the SDKs and the MCP warmhub_thing_query and warmhub_thing_head tools accept it.
Read a shape closure through the CLI or the SDK:
wh thing query --repo warmhub-data/us.congress.trades --shape CongressTrade --include-validated-shapesconst result = await client.thing.query('warmhub-data', 'us.congress.trades', { shape: 'CongressTrade', includeValidatedShapes: true,})See Shapes for what a shape closure contains.
GET /head
Section titled “GET /head”Return the current HEAD snapshot — the latest version of every active thing in the repository.
Filtered /head reads — either with an explicit match or on a scoped Bearer token — are subject to the freshness note above.
Query Parameters
Section titled “Query Parameters”| Parameter | Type | Required | Description |
|---|---|---|---|
shape | string | No | Filter by shape name |
kind | string | No | Filter by kind: thing, shape, assertion or collection. Filtering by assertion or collection narrows the rows returned; the kind each row reports is still thing or shape |
match | string | No | Glob pattern to filter wrefs (* = one segment, ** = zero or more) |
limit | integer | No | Maximum items per page (max 500). When omitted, WarmHub returns up to 50 items. Anonymous callers are capped — see Anonymous Pagination Caps. |
cursor | string | No | Opaque pagination cursor from a previous nextCursor response. Anonymous callers are capped at two pages — see Anonymous Pagination Caps. |
Response 200
Section titled “Response 200”Each item in items includes the fields listed below, plus a metadata object that carries a stable durable identifier and creation timestamps. All timestamp fields are epoch-millisecond numbers.
The kind filter accepts thing, shape, assertion and collection, but a response row reports only thing or shape. Filtering by assertion or collection narrows which rows come back; it does not change the kind they report, so no row carries kind: "assertion" or kind: "collection". collection is a deprecated value: it selects the items WarmHub recognises as collections, not every thing you might consider one — query filtering has the detail. Read those semantics from the row instead: assertions carry aboutWref (when present) and affirmedWrefs (where present), and collections carry a collections array naming the collection Shapes they satisfy.
| Field | Type | Description |
|---|---|---|
wref | string | The thing’s wref within this repo |
name | string | The name segment of the wref |
kind | string | One of thing, shape |
active | boolean | false when the item has been retracted |
version | integer | Current version number |
createdAt | number (epoch ms) | Timestamp when this version was written (same value as metadata.revisedOn) |
data | object | Shape-defined payload |
componentRef | string | Present when the item is owned by an installed component; omitted otherwise |
declaredShapes | array of strings | Version-pinned shape wrefs (e.g. Shape@vN) this item directly declares membership in, returned as [] when it declares none. Presence is not guaranteed — whether shape membership is projected at all depends on the repo and the read path, so the field may be absent from every row of a response. Always branch on its absence; never require it. To read the certified closure deterministically, pass includeValidatedShapes and use validatedShapes. |
aboutWref | string | Assertions only. The durable id of the shape or shaped thing this assertion is about, pinned to the version the assertion was created against. May be absent — omitted when the target is suppressed, not found, or its repo is no longer accessible, and also omitted on assertion reads where affirmedWrefs is present but the stored target reference could not be resolved. Always check for presence before reading. |
affirmedWrefs | array of strings | Assertions only. Each entry is a pinned @vN durable id of the assertion’s about target that this assertion affirms. Always present on assertion rows — returned as [] when the assertion affirms nothing. Omitted only for non-assertion items. |
collections | array of objects | Collections only. One entry per collection Shape this item is recognised under, each naming the pinned shape wref (e.g. Set@v3). Absent on a thing that is not a collection, and never empty when present — so its presence is how you identify a collection. Each entry also carries memberCount, but only when the read returned a complete body: a read that withheld or summarised the body omits it rather than reporting 0, so treat a missing memberCount as “not known from this read”, never as an empty collection. Member layout is not in this array — to place members, read the Shape version it names. |
metadata.durableId | string | Stable, repo-scoped identifier that survives renames |
metadata.createdOn | number (epoch ms) | Timestamp when the thing was first created |
metadata.revisedOn | number (epoch ms) | Timestamp when this specific version was written |
{ "items": [ { "wref": "20030868/0", "name": "20030868/0", "kind": "thing", "active": true, "version": 3, "createdAt": 1723194344000, "declaredShapes": ["StockTrade@v2"], "data": { "owner": "spouse", "ticker": "ABBNY", "amount": "$1,001 - $15,000", "tx_type": "sale", "trade_date": "2025-08-08", "legislator_name": "Adam Smith" }, "metadata": { "durableId": "dbl_01jt2k8mxe000000000000000a", "createdOn": 1723126921000, "revisedOn": 1723194344000 } } ], "nextCursor": "whc1_eyJ2Ijox..."}When there are more results, nextCursor contains an opaque token to pass as the cursor parameter on the next request. When all results have been returned, nextCursor is omitted.
Example
Section titled “Example”# All things in the CongressTrade shapecurl "https://api.warmhub.ai/api/repos/warmhub-data/us.congress.trades/head?shape=CongressTrade"
# All shapes in the repositorycurl "https://api.warmhub.ai/api/repos/warmhub-data/us.congress.trades/head?kind=shape"
# Paginate through resultscurl "https://api.warmhub.ai/api/repos/warmhub-data/us.congress.trades/head?shape=CongressTrade&limit=20&cursor=whc1_eyJ2Ijox..."GET /about/:wref
Section titled “GET /about/:wref”Get a shape or shaped thing and all assertions about it.
Filtered /about reads — either with an explicit match or on a scoped Bearer token — are subject to the freshness note above. Unfiltered /about requests reflect the latest written state immediately.
When the URL-encoded wref is canonical (wh:org/repo/...) and points at a private repo the caller cannot read, the route returns 404 — the response is intentionally indistinguishable from a missing target. The same gate applies to /query reads with an about=wh:... filter. See Wrefs — Visibility gate on resolution.
Path Parameters
Section titled “Path Parameters”| Parameter | Type | Description |
|---|---|---|
wref | string | URL-encoded wref of the target shape or shaped thing |
Query Parameters
Section titled “Query Parameters”| Parameter | Type | Required | Description |
|---|---|---|---|
shape | string | No | Filter assertions by shape name |
match | string | No | Glob pattern to filter assertion wrefs (* = one segment, ** = zero or more) |
includeRetracted | boolean | No | Resolve a retracted target and include retracted assertions (default false). When combined with depth > 1, retracted assertions are also included in nested children arrays. |
resolveCollections | boolean | No | Include assertions about collections containing the target entity (default false) |
depth | integer | No | Nesting depth for recursive assertion lookup |
limit | integer | No | Maximum assertions to return (max 500). Anonymous callers are capped — see Anonymous Pagination Caps. |
cursor | string | No | Opaque pagination cursor from a previous nextCursor response. Anonymous callers are capped at two pages — see Anonymous Pagination Caps. |
Response 200
Section titled “Response 200”The response contains a target object representing the looked-up shape or shaped thing, and an assertions array. All timestamp fields are epoch-millisecond numbers.
Every item in assertions reports kind: "thing" — the array holds only assertion rows, and assertions never report shape. Their assertion semantics are carried by aboutWref (when present) and affirmedWrefs; no row carries kind: "assertion".
The target object contains the following fields:
| Field | Type | Description |
|---|---|---|
target.wref | string | The target’s wref within this repo |
target.pinnedWref | string | The version-pinned wref for this target |
target.name | string | The name segment of the wref |
target.kind | string | One of thing, shape |
target.version | integer | Current version number |
target.data | object | Shape-defined payload; for a shape target, the shape definition |
target.active | boolean | false when the target has been retracted |
target.declaredShapes | array of strings | Version-pinned shape wrefs (e.g. Shape@vN) this target directly declares membership in. Always present on target rows; returned as [] when the target declares no shapes. |
target.validatedShapes | array of strings | Version-pinned shape wrefs (e.g. Shape@vN) for every shape in the certified closure of this target’s version. Always present on target rows; returned as [] when the target is itself a shape or its version certifies no shapes. |
target.aboutWref | string | Assertions only. The pinned durable id of the shape or shaped thing this assertion is about. May be absent — omitted when the target is suppressed, not found, or its repo is no longer accessible, and also omitted when affirmedWrefs is present but the stored target reference could not be resolved. Always check for presence before reading. |
target.affirmedWrefs | array of strings | Present on assertion targets. Each entry is a pinned @vN durable id; always returned on assertion rows — [] when the assertion affirms nothing. Omitted for non-assertion targets. |
target.committerWref | string | Optional committer the writer declared via --committer — present only when the originating write recorded one. Returned as a bare durable id, without a version suffix. |
target.createdBy | string | Optional. Bare durable id of the authenticated identity that authored the first version of this target (immutable creator attribution); omitted when the creator cannot be resolved |
target.revisedBy | string | Optional. Bare durable id of the authenticated identity that authored the current version (distinct from the optional committerWref label); omitted when the current-version author cannot be resolved |
target.metadata | object | Stable durable identifier and creation timestamps (see metadata fields in the GET /head field table) |
Each item in assertions includes the same fields as items returned by GET /head — including aboutWref (when present) and affirmedWrefs on assertion rows — see the field reference in GET /head for the full list. Each item also includes a children array — nested assertions about that assertion, populated when a higher depth is requested and [] otherwise. When includeRetracted=true is combined with depth > 1, retracted assertions appear in children arrays at every nesting level, not just at the top level.
The example below uses CongressTrade + CongressTradeSecurity because the relationship assertion is about an Arc from the trade to its resolved security. Pass resolveCollections=true to include that relationship in the /about response.
{ "target": { "wref": "20034954/bd598743649e738e-2", "pinnedWref": "20034954/bd598743649e738e-2@v1", "name": "20034954/bd598743649e738e-2", "kind": "thing", "version": 1, "active": true, "declaredShapes": ["CongressTrade@v2"], "validatedShapes": ["CongressTrade@v2"], "data": { "ticker": "CSCO", "filing_doc_id": "20034954", "transaction_type": "sale_partial" }, "metadata": { "durableId": "040SXA5RYM7Q4QXAGM8N6MXYVH5G37TDS2P16YQAG6D6M3VKT6YE8ZCW52H0", "createdOn": 1783716424678, "revisedOn": 1783716424678 } }, "assertions": [ { "wref": "20034954/bd598743649e738e-2--0000858877", "name": "20034954/bd598743649e738e-2--0000858877", "kind": "thing", "active": true, "version": 1, "createdAt": 1783803885129, "declaredShapes": ["CongressTradeSecurity@v1"], "data": { "cik10": "0000858877", "ticker_raw": "CSCO", "resolver_confidence": 1 }, "aboutWref": "040SXA5RYM7Q4QXAGM8N6MXYVH5G37TDS2P16K4WBN7QZE3XR8T5C9FMDT2Q@v1", "affirmedWrefs": [], "children": [], "metadata": { "durableId": "040SXA5RYM7Q4QXAGM8N6MXYVH5G37TJZWVKEZ7MHK5HJCWWDJ98DBEKFQYG", "createdOn": 1783803885129, "revisedOn": 1783803885129 } } ], "nextCursor": "whc1_eyJ2Ijox..."}Errors
Section titled “Errors”| Code | Status | Description |
|---|---|---|
NOT_FOUND | 404 | Target thing not found, or the caller cannot access the repo |
VALIDATION_ERROR | 400 | Missing or invalid wref |
Example
Section titled “Example”# All assertions about a thing, including relationship assertions on its collectionscurl "https://api.warmhub.ai/api/repos/warmhub-data/us.congress.trades/about/20034954%2Fbd598743649e738e-2?resolveCollections=true"
# Only CongressTradeSecurity-shape assertions, including retractedcurl "https://api.warmhub.ai/api/repos/warmhub-data/us.congress.trades/about/20034954%2Fbd598743649e738e-2?shape=CongressTradeSecurity&includeRetracted=true&resolveCollections=true"GET /query
Section titled “GET /query”Query things by filters. Returns items matching the specified criteria.
Filtered /query reads — either with an explicit match or on a scoped Bearer token — are subject to the freshness note above.
Query Parameters
Section titled “Query Parameters”| Parameter | Type | Required | Description |
|---|---|---|---|
shape | string | No | Filter by shape name |
about | string | No | Filter assertions by target wref |
kind | string | No | Filter by kind: thing, shape, assertion or collection. Filtering by assertion or collection narrows the rows returned; the kind each row reports is still thing or shape |
match | string | No | Glob pattern to filter wrefs (* = one segment, ** = zero or more) |
resolveCollections | boolean | No | When about is set, also include assertions about collections containing the target (default false) |
includeRetracted | boolean | No | Include retracted items (default false) |
limit | integer | No | Maximum items to return (max 500). Anonymous callers are capped — see Anonymous Pagination Caps. |
cursor | string | No | Opaque pagination cursor from a previous nextCursor response. Anonymous callers are capped at two pages — see Anonymous Pagination Caps. |
Response 200
Section titled “Response 200”Each item in items includes the same fields as items returned by GET /head — including aboutWref (when present) and affirmedWrefs on assertion rows — see the field reference in GET /head for the full list. declaredShapes is subject to the same no-guarantee rule described there. All timestamp fields are epoch-millisecond numbers.
Every returned item reports kind as thing or shape. assertion and collection are accepted as filter values to narrow which rows come back, but the rows they select still report thing.
{ "items": [ { "wref": "20034954/bd598743649e738e-2", "name": "20034954/bd598743649e738e-2", "kind": "thing", "active": true, "version": 1, "createdAt": 1783716424678, "declaredShapes": ["CongressTrade@v2"], "data": { "ticker": "CSCO", "amount_range": "$1,001 - $15,000", "transaction_type": "sale_partial" }, "metadata": { "durableId": "040SXA5RYM7Q4QXAGM8N6MXYVH5G37TDS2P16YQAG6D6M3VKT6YE8ZCW52H0", "createdOn": 1783716424678, "revisedOn": 1783716424678 } } ], "nextCursor": "whc1_eyJ2Ijox..."}Example
Section titled “Example”# All things in the CongressTrade shapecurl "https://api.warmhub.ai/api/repos/warmhub-data/us.congress.trades/query?shape=CongressTrade&kind=thing"
# Assertions about a specific thingcurl "https://api.warmhub.ai/api/repos/warmhub-data/us.congress.trades/query?about=20034954%2Fbd598743649e738e-2&kind=assertion"