Hub API Overview
API reference for the Treeship Hub at api.treeship.dev. Authentication, endpoints, and error format.
Base URL
https://api.treeship.devAll endpoints are prefixed with /v1/.
IDs in the examples are illustrative. Every art_…, ssn_…, and
hub_… value on these API pages is a placeholder chosen to show the shape of
the identifier — pasting one into curl returns 404, which is the correct
answer for an id that was never pushed. Substitute an id from your own
treeship status or treeship hub push output.
Two endpoints take no id and answer for anyone, so they are the ones to reach for when you want to confirm Hub is up:
curl -s https://api.treeship.dev/v1/merkle/checkpoint/latest
curl -s https://api.treeship.dev/v1/dock/challengeWhat Hub does
Hub is optional infrastructure. Artifact validity never depends on it -- the signatures are the trust. Hub provides three things:
- Artifact storage for signed envelopes pushed from local Treeships
- Shareable verification URLs at
treeship.dev/verify/{artifact_id} - Transparency log anchoring via Sigstore Rekor, for every pushed artifact except one signed only by an agent key (reported as skipped with a reason, not silently unanchored)
Hub does not sign, modify, or interpret artifacts. It stores and serves the DSSE envelopes created locally. The WASM verifier on the verification page checks a named artifact's signature client-side against your own trust roots, so Hub cannot forge a passing result for it -- that's narrower than a bare Session Receipt fetch, which carries no signature at all (see GET /v1/receipt/{session_id}).
Authentication
Hub uses DPoP (Demonstration of Proof-of-Possession) for write endpoints. There are no API keys, session tokens, or bearer tokens.
Authenticated requests require two headers:
| Header | Value |
|---|---|
Authorization | DPoP {dock_id} |
DPoP | A fresh JWT signed by the dock private key |
The DPoP JWT contains:
{
"iat": 1711500000,
"jti": "unique-random-hex",
"htm": "POST",
"htu": "https://api.treeship.dev/v1/artifacts"
}Hub verifies:
iatis within 60 seconds of the current timejtihas not been seen before (replay protection)htmmatches the HTTP method of the requesthtumatches the request URL- The JWT signature matches the dock public key stored during login
Read endpoints require no authentication.
Endpoints
| Method | Path | Auth | Description |
|---|---|---|---|
GET | /v1/dock/challenge | None | Start device flow login |
GET | /v1/dock/authorized | None | Poll device flow status |
POST | /v1/dock/authorize | None | Complete device flow login |
POST | /v1/artifacts | DPoP | Push a signed artifact |
GET | /v1/artifacts/:id | None | Retrieve an artifact |
GET | /v1/workspace/:dock_id | DPoP | List artifacts in a workspace |
POST | /v1/session | DPoP | Mint a short-lived share token for browser workspace reads |
GET | /v1/verify/:id | None | Retired. Returns 410 Gone; verify locally instead |
POST | /v1/merkle/checkpoint | DPoP | Publish a Merkle checkpoint |
POST | /v1/merkle/proof | DPoP | Publish a Merkle inclusion proof |
POST | /v1/merkle/consistency | DPoP | Publish a Merkle consistency proof |
GET | /v1/merkle/checkpoint/latest | None | Get the latest Merkle checkpoint |
GET | /v1/merkle/checkpoint/:id | None | Get a specific Merkle checkpoint |
GET | /v1/merkle/consistency | None | Get a Merkle consistency proof |
GET | /v1/merkle/:artifactId | None | Get a Merkle inclusion proof |
PUT | /v1/receipt/:session_id | DPoP | Publish a session receipt |
GET | /v1/receipt/:session_id | None | Fetch a session receipt (permanent URL) |
GET | /v1/ship/agents | DPoP | List this ship's registered agents |
GET | /v1/ship/sessions | DPoP | List this ship's sessions |
GET | /v1/agents | None | Resolve an agent URI to its verifiable bundle |
GET | /v1/agents/log | None | Agent transparency log (metadata + Merkle anchors) |
GET | /v1/agents/history | None | Agent receipt history |
GET | /v1/agents/match | None | Match agents in the registry |
GET | /v1/stats | None | Public adoption metrics (counts only, cached 5 min) |
GET | /v1/version | None | Which build is running: version, commit, build time, Go runtime (/version is an alias; /health and /healthz are the liveness probe, /readyz readiness) |
GET | /.well-known/treeship/revoked.json | None | Revoked key list |
Which build is running
GET /v1/version{"service":"treeship-hub","version":"0.31.10","commit":"1a2b3c4","built_at":"2026-09-26T00:00:00Z","go":"go1.26.4"}Values come from the build; unset ones read dev or unknown rather than a guess. Never cached. /version is an alias, /health and /healthz answer liveness, /readyz readiness.
Error format
All errors return JSON:
{
"error": "artifact not found"
}HTTP status codes:
200-- Success201-- Created (artifact stored)202-- Accepted (pending, used during device flow polling)400-- Bad request401-- Authentication failed (DPoP invalid)404-- Not found409-- Conflict (device code already used)410-- Gone (expired device code, or the retired/v1/verify/:idendpoint)500-- Server error
OpenAPI spec
The full OpenAPI 3.1 spec is available at hub-openapi.yaml for code generation and tooling.