# API reference

Authentication, request signing, errors and resource endpoints.


Use `https://trust-staging.rebellion.systems` for development through [early access](/early-access), or `https://trust.rebellion.systems` for production. Request origin allowlisting as part of onboarding. There is no sandbox environment. Public SDK distribution is coming soon.

Send JSON with `Content-Type: application/json`. Examples use descriptive placeholders for IDs and signatures; generate real values with the SDK before sending them.

## Choose the authorization model

| Surface | Authorization |
| --- | --- |
| Bind start, callback, finalize and polling | The [bind ceremony](/api/bind), with both one-time proofs at finalize |
| Graph reads | Fresh device-signed `authorization` for the exact operation and query |
| Graph mutations | Device-signed edge certificate or action |
| Own persona key listing | Verified AuthenSee persona credential |
| Key revocation | Device signature, or the target's own persona credential |
| Certificate status | A complete issuer-signed certificate plus a fresh nonce |
| Health, current epoch, attestation keys, append-only report, attestation verification | No device authorization |

A `graphNodeId` identifies a stable persona node. A `graphKeyId` identifies one device key. In edge certificates, `signerGraphKeyId` and `subjectGraphKeyId` are **node IDs**. In reachability queries, `sourceGraphKeyId` and `targetGraphKeyId` are also **node IDs**. In `authorization` and signed actions, `graphKeyId` is the **signing device**.

## Signed reads

An authorization contains `graphKeyId`, `nonce`, `signedAt` and `signature`. Sign the UTF-8 canonical JSON of this structure using ECDSA P-256 with SHA-256, then encode the DER signature as base64:

```json
{
  "v": "trust-graph-read-v1",
  "operation": "list-edges",
  "graphKeyId": "signing-device-id",
  "nonce": "fresh-random-nonce",
  "signedAt": "2026-11-04T12:00:00.000Z",
  "query": { "graphKeyId": "own-node-id" }
}
```

The query is exactly the request body without `authorization`. Sign before defaults, and send exactly what you signed. The signer must own the source node. Use a new nonce and timestamp for each request, including retries. The freshness window is five minutes. Prefer the SDK signing helpers over implementing canonical encoding yourself.


**Does not establish**
Read replay tracking is process-local and resets on restart. An authorization may be accepted once per instance within its freshness window. Mutation replay tracking is separate and durable.

## Signed mutations

Actions travel as `{action, signature}`. Sign canonical JSON of `{v: "trust-graph-action-v1", ...action}`. Each action names its operation, signing device, nonce, timestamp and operation-specific fields. The exact fields are listed on each resource page. Edge declarations use their own certificate signing format; use `signBrowserEdgeCertificate` or the corresponding signer helper.

A bound key must be usable for the operation: unrevoked, unexpired, of the right purpose and, on a node with a device chain, approved. [Device authority](/api/devices) describes the limited operations available to quarantined devices.

## Errors and retries

| HTTP | Typical meaning | Client behavior |
| --- | --- | --- |
| 400 | Invalid shape, timestamp, policy or signed field | Correct the request before signing again |
| 401 | Missing or invalid authorization | Check signing bytes and credentials |
| 403 | Authenticated key lacks authority, purpose or usable lifecycle | Refresh device state; use recovery when appropriate |
| 404 | Resource or current membership unavailable | Treat evidence as unavailable |
| 409 | Nonce reuse, stale revision or conflicting state | Read current state and reconcile |
| 429 | Rate limit | Honor `retry-after` where returned |
| 503 | Required capability or service unavailable | Retry later with a fresh authorization |

Graph errors use `{error, code?}`; some conflicts include `currentEdgeId`. Shape errors use `{error: "Invalid request", issues}`. Dispatch on a documented `code` when present; do not assume every error has one.

After an uncertain mutation response, read the relevant state before signing another mutation. Revision-based APIs document how to distinguish success from a conflicting write. A failed attestation verification can return HTTP 200 with `verified: false`; HTTP success alone is not a trust result.

## Rate limits

Limited graph routes return 429 with `retry-after` and `x-ratelimit-limit`, `x-ratelimit-remaining`, and `x-ratelimit-reset`. The default general budget is 300 requests per minute per connection origin, with 120 successful writes per minute per graph key; deployments may configure those budgets. Devices, recovery and external keys also have resource-specific limits. Use the returned headers rather than assuming a deployment's budget.

## Resources

| Resource | Reference |
| --- | --- |
| Identity and authority | [Bind](/api/bind), [graph keys](/api/graph-keys), [devices](/api/devices), [nodes](/api/nodes) |
| Connections | [Edges](/api/edges), [tags](/api/tags), [handles](/api/handles) |
| Query and evidence | [Reachability](/api/query), [attestations](/api/attestations), [epochs](/api/epochs) |
| Signing integrations | [Content certificates](/api/content-certificates), [Git signers](/api/git-signers), [external keys](/api/external-keys) |
| Service probes | [Health](/api/health) |
