relationships
Graph lane: labelled relationship EDGES between companies/entities (ownership, operates, supplies,
…) — the PRODUCT (edges with tiers + provenance), named for the capability, not the meter. Typed query
params (GET /relationships): the answer is about ONE entity (GreenlandAI 2026-10-01). entity_type
("company" | "infrastructure" | "deposit" | "project") + entity_id pin the START NODE; or entity — the one entity
whose name equals it (case-insensitive), else the one whose name contains it. If several entities match, the call
fails (isError, upstream_status 409, nothing charged) with upstream_body.detail = {error: "ambiguous_entity",
candidates: [{entity_type, entity_id, name, country}], how_to_choose} — call again with entity_type + entity_id from
one of them; each candidate carries has_site (true = it holds a site, so the measurement routes can answer about it; false =
name-only or a country centre, which those routes refuse). The answer's resolved names the entity it is about, with its place
block; every entity in the answer has one in places (rows point there by subject_ref / object_ref): has_site, height_class (its
last measurement's, else unknown), last_measured, and the measurement routes filled in for it. WHEN NOT TO CALL: "did the site
change" is entity_change; a volume is never in this answer (only entity_change's repeat_surface measures a volume change). hops (traversal DEPTH 1-10, default 1 — the BILLING UNIT:
metered per hop, which is why billing_quote takes hops=),
relation_type (one relation label, e.g. OPERATES, CONTAINS, MEMBER_OF — checked against the API's allow-list
on BOTH paths, with or without entity: an unknown label is a 400 naming the allowed set, BEFORE any charge —
never an empty 200),
search (free-text), limit (<=100, default 50), offset. Metered — debited from the CALLING agent's own
wallet, not the owner's (read it with the joules_balance tool). For the exact per-caller price before
you call, use the billing_quote tool (free, tier-aware; returns joules_all_in) or check
affordability with the joules_deficit tool; the true debit is the base joule_cost plus a 0.5% rail
surcharge rounded up (a 100 J call debits 101 J) = joules_all_in. Preserves source_tier/tier_label
on each edge — do not strip them. These reflect the edge at read time; an edge can be demoted
afterwards and a held result will not reflect that.
⚠ CHARGING: the meter RESERVES before the query runs and SETTLES after delivery for what was actually
delivered (an empty result settles to 0; a partial traversal settles for the hops delivered; a 4xx
releases the reservation). An abandoned or timed-out call still settles once the backend delivers.
A replay is served free only for the SAME credential + SAME idempotency key + SAME request within
15 minutes — a different payer is a different payer. Every call through this relay carries a fresh
key, so a retry here is always a new charge. Price with billing_quote first; verify any charge
with the billing_attempts tool (own wallet: reserved vs settled, per attempt).
AS OF A DATE (GR-126-5): as_of = YYYY-MM-DD or a UTC datetime (needs one entity) answers TWICE, labelled — true_at: the
edges true then in VALID time (every hop: a source dates its start on/before as_of, or — start unknown — a source stated it
by then, and it had not ended), with the excluded edges counted by reason (began after / ended by / first stated after /
undated); and served_at: the edges GreenlandAI SERVED then in RECORD time, each with the observation it rests on (a dated
archive snapshot, the record-time epoch, or a recorded version); before 2026-07-30 what we served is not recorded by id and
the answer says so. One request, one price; nothing in either answer costs nothing; a bad or future as_of is a 400, not charged.
WHAT YOU PAID: the JSON response carries a top-level charged_joules — the all-in PRICE of this call —
and a metering block written AFTER the settle has run: {attempt_id, settlement, settled_joules, check}.
metering.settlement is whether you PAID: settled · settled_zero (empty result, nothing moved) ·
settle_failed (delivered but UNPAID — the wallet is then locked until it clears; the next metered call
402s naming the attempt, the amount and what clears it) · released (4xx/5xx, nothing moved) · unknown.
settled_joules is what actually left the wallet (0 unless settled). A cached replay carries no block.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| hops | No | ||
| as_of | No | ||
| limit | No | ||
| entity | No | ||
| offset | No | ||
| search | No | ||
| entity_id | No | ||
| entity_type | No | ||
| relation_type | No |
Output Schema
| Name | Required | Description | Default |
|---|---|---|---|
No arguments | |||