Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

API reference

The registrar exposes a small HTTP surface. This page covers the wire conventions common to every endpoint; the Registrar API page documents each endpoint, and Bundles & grants covers the share/verify exchange in detail. The handlers are thin wrappers over the registrar operations in crates/tenure-registrar/src/http.rs.

Transport

  • HTTP with JSON bodies. Request and response bodies are JSON.
  • Canonical bytes are still BCS. JSON is the transport, never the signed form. Any signed object inside a request carries its canonical BCS bytes base64url-encoded; signatures are verified over those bytes, not over the JSON.

Signed objects on the wire

A signed protocol object travels as the Signed envelope:

{
  "payload_b64": "…",   // base64url(no-pad) of bcs(("tn-xxx-v1", body))
  "signer_pk":   "…",   // lowercase-hex Ed25519 public key
  "sig":         "…"    // base64url(no-pad) Ed25519 signature over the payload bytes
}

The registrar verifies the signature over payload_b64’s decoded bytes and then decodes under the expected domain tag. A tampered byte fails the signature check before the payload is interpreted.

Authenticated envelopes

Mutating calls from signers (the employer Signer, a holder, etc.) are wrapped in an envelope that authenticates the call, not just the embedded object:

{
  "payload_bcs_b64": "…",
  "signer_pk":       "…",
  "sig":             "…",
  "nonce":           "…",   // unique per signer (single-use)
  "ts":              0       // unix seconds; accepted within ±5 minutes
}

Replay defense (per the security requirements):

  • nonces are unique per signer and recorded, so a captured envelope cannot be replayed;
  • ts must be within ±5 minutes of the registrar’s clock;
  • ShareGrant nonces are single-use per audience.

Unauthenticated surfaces — the public head, checkpoint, and revocation endpoints, and share-link fetches — carry no envelope. In production these are rate-limited and proof-of-work gated; that gating is not wired into this build.

Operation receipts

Every mutating response that appends to the log includes an operation receipt so the caller can retain a witnessed head:

{
  "employer_id": "…",
  "log_seq": 0,
  "entry_hash": "…",
  "log_head": { "epoch_no": 0, "seq": 0, "head_hash": "…", "head_sig": "…" }
}

Wallets keep these as inclusion receipts.

Errors

Errors are a JSON object { "error": "…" } with a status code:

StatusCondition
401 UnauthorizedEnvelope verification failed (bad signature, stale ts, replayed nonce)
404 Not FoundUnknown employer, grant, or entity
422 Unprocessable EntityThe request was authenticated but rejected by policy (e.g. a mint outside delegation, a batch that fails the cross-check)
500 Internal Server ErrorStorage or internal failure