Read a node's subtree on a specific branch, to a bounded depth
const url = 'https://api.hydrate.sh/v1/branches/2489E9AD-2EE2-8E00-8EC9-32D5F69181C0/subtree/2489E9AD-2EE2-8E00-8EC9-32D5F69181C0?depth=1';const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
try { const response = await fetch(url, options); const data = await response.json(); console.log(data);} catch (error) { console.error(error);}curl --request GET \ --url 'https://api.hydrate.sh/v1/branches/2489E9AD-2EE2-8E00-8EC9-32D5F69181C0/subtree/2489E9AD-2EE2-8E00-8EC9-32D5F69181C0?depth=1' \ --header 'Authorization: Bearer <token>'Returns a node and its descendants down to depth levels on this branch, with the edges among them. The scoped counterpart to GET /v1/branches/{branch_id}/graph: bounded by depth rather than by the size of the branch, so reading a slice of a large project never puts the whole graph on the wire.
Authorizations
Section titled “Authorizations”Parameters
Section titled “Parameters”Path Parameters
Section titled “Path Parameters”The branch to read.
The branch to read.
The node to root the subtree at.
The node to root the subtree at.
Query Parameters
Section titled “Query Parameters”How many levels of descendants to include. 1 = direct children only.
How many levels of descendants to include. 1 = direct children only.
Responses
Section titled “Responses”Successful Response
A node plus its descendants to a bounded depth.
nodes EXCLUDES root. truncated is true when the walk stopped
with descendants still below it — a caller that cannot distinguish a
complete cell from a slice will treat a slice as complete, so the signal
is explicit rather than inferred from depth.
cross_boundary_edges carries edges with exactly one endpoint inside
the returned set: real dependencies of this slice, which a scoped read
would otherwise hide.
object
object
Read-path edge: source/target are server-derived NODE ids
(absent from the client-authored h2o.types.Edge); *_handle are the
PORT ids.
Read-path edge: source/target are server-derived NODE ids
(absent from the client-authored h2o.types.Edge); *_handle are the
PORT ids.
object
Read-path node data. NOT h2o.NodeData: the response omits
kind/parent_id (those live on the wrapper) and emits the boundary/
external scalars matrix-conditionally — so the matrix fields are
optional (absent = not-applicable-to-kind).
object
object
Dotted path for every node returned that has one, keyed by node id. Server-rendered because a scoped read returns a SLICE: the ancestors a path is built from are not in the payload, so a client cannot derive it. Every returned node appears in exactly one of paths or unaddressable — index this map for anything not listed there.
object
object
Read-path node data. NOT h2o.NodeData: the response omits
kind/parent_id (those live on the wrapper) and emits the boundary/
external scalars matrix-conditionally — so the matrix fields are
optional (absent = not-applicable-to-kind).
object
object
Nodes that could not be given a dotted path, keyed by node id, with the reason: empty_name (the node, or an ancestor, has no name — legal while designing), reserved_separator (a name contains .), or ambiguous (two returned nodes would render the same path, so neither is safe to act on). These are data conditions a user fixes by renaming, not errors.
object
Example
{ "nodes": [ { "data": { "config": [ { "contract_name": null, "description": "", "external": false, "name": "", "type": "" } ], "documentation_url": null, "external_kind": null, "inputs": [ { "contract_name": null, "description": "", "external": false, "name": "", "type": "" } ], "language": null, "outputs": [ { "contract_name": null, "description": "", "external": false, "name": "", "type": "" } ], "path_prefix": null, "protocol": null, "source_decisions": null, "user_kind": null, "verifications": [ { "author": "user", "type": null } ] }, "kind": "behavior" } ], "root": { "data": { "config": [ { "contract_name": null, "description": "", "external": false, "name": "", "type": "" } ], "documentation_url": null, "external_kind": null, "inputs": [ { "contract_name": null, "description": "", "external": false, "name": "", "type": "" } ], "language": null, "outputs": [ { "contract_name": null, "description": "", "external": false, "name": "", "type": "" } ], "path_prefix": null, "protocol": null, "source_decisions": null, "user_kind": null, "verifications": [ { "author": "user", "type": null } ] }, "kind": "behavior" }}No credentials, malformed credentials, or revoked credentials. The envelope is leak-parity (same shape across all 401 paths) so an attacker cannot distinguish revoked vs. unknown via the body.
object
Example
{ "detail": "unauthenticated"}Credentials are valid but lack the scope required for this route, or the principal lacks membership in the target project.
object
object
Examplegenerated
{ "detail": { "code": "example", "message": "example" }}Resource not found OR not accessible to this principal. Leak parity: the response is identical in both cases so an attacker cannot enumerate resources via 404-vs-403 timing.
object
object
Example
{ "detail": { "code": "not_found" }}Validation Error
object
object
object
Examplegenerated
{ "detail": [ { "ctx": {}, "input": "example", "loc": [ "example" ], "msg": "example", "type": "example" } ]}Per-bucket rate limit exceeded. The response carries Retry-After and the standard X-RateLimit-* headers (Limit / Remaining / Reset).
object
Example
{ "detail": "rate_limited"}