API reference
Shapes below are the fields this service returns. FastAPI generates the machine-readable description at /docs/openapi and /openapi.json.
GET /v1/revocations
Pull list of stored principal revocations. The response sets Cache-Control: public, max-age=300.
Response
{
"revocations": []
}POST /v1/revocations/push
Notifier-signed webhook. The body is the object from sign_revocation_push: at, kata_revocation_push "1", revocation, and signature. signature is a flattened JWS whose protected header typ is kata-revocation-push+jws.
Request
{
"at": "2026-10-04T18:00:00Z",
"kata_revocation_push": "1",
"revocation": {
"agreement_id": "agr_demo",
"at": "2026-10-04T18:00:00Z",
"kata_revocation": "1",
"mandate_hash": "sha256:…",
"reason": "principal revoked",
"signature": {"payload": "…", "protected": "…", "signature": "…"}
},
"signature": {"payload": "…", "protected": "…", "signature": "…"}
}Response
{
"stored": true,
"revocation_id": "sha256:…",
"sequence": 1
}POST /v1/log/entries
Append an agreement, revocation, registration, or incident and sign a new tree head. Authorization: Bearer
Request
{
"kind": "agreement",
"body": {}
}Response
{
"entry": {
"kind": "agreement",
"sequence": 1,
"body": {},
"entry_hash": "sha256:…"
},
"tree_head": {
"algorithm": "EdDSA",
"at": "2026-10-04T14:02:11Z",
"kata_tree_head": "1",
"root": "sha256:…",
"tree_size": 1,
"signature": {"payload": "…", "protected": "…", "signature": "…"}
}
}GET /v1/log/entries/{sequence}
One hash-chained entry. sequence starts at 1.
Response
{
"entry": {
"kind": "revocation",
"sequence": 1,
"body": {},
"entry_hash": "sha256:…"
}
}GET /v1/log/entries/{sequence}/proof
Merkle inclusion proof for that entry. index is sequence minus 1. side is left or right.
Response
{
"sequence": 1,
"index": 0,
"leaf": "sha256:…",
"proof": [{"hash": "sha256:…", "side": "right"}],
"root": "sha256:…",
"tree_size": 1
}GET /v1/log/head
Signed tree head. The same fields are on tree_head from a log append.
Response
{
"algorithm": "EdDSA",
"at": "2026-10-04T14:02:11Z",
"kata_tree_head": "1",
"root": "sha256:…",
"tree_size": 1,
"signature": {"payload": "…", "protected": "…", "signature": "…"}
}GET /.well-known/kata-keys.json
Log public key, plus any records in KATA_PUBLISHED_KEYS. An empty key list is a 200 when no seed is set.
Response
{
"keys": [
{"public_key": {"crv": "Ed25519", "kid": "sha256:…", "kty": "OKP", "x": "…"}}
]
}GET /v1/fx?currency=CAD&reference=USD&day=YYYY-MM-DD
Reference-currency units for one unit of currency on that UTC day. reference_currency is an alias of reference. The default reference is USD. day defaults to the current UTC date. The rate is a decimal string from the configured source (default https://api.frankfurter.dev/v1). The same currency returns rate "1".
Response
{
"currency": "CAD",
"reference_currency": "USD",
"day": "2026-10-04",
"rate": "…"
}POST /demo/check
Signs one sample agreement with the public demo keys and evaluates one payment. principal is K. Uluer and the agent is shopper-01. demo is true. verdict is ALLOW, DENY, or STEP_UP. kata_decision is ALLOW, BLOCK, or STEP_UP. DENY maps to BLOCK.
Request
{
"intent": {
"maximum_amount": 1500,
"currency": "CAD",
"purpose": "purchase",
"category": "electronics",
"natural_language": "Find and buy a laptop for me, maximum CAD 1,500.",
"include_expiry": true,
"time_limit": "2026-12-31"
},
"payment": {
"amount": 1300,
"currency": "CAD",
"merchant": "techstore.example",
"item": "Laptop"
}
}Response
{
"verdict": "ALLOW",
"kata_decision": "ALLOW",
"reasons": [],
"messages": [],
"required_action": "NONE",
"confirmation_text": "…",
"mandate_hash": "sha256:…",
"principal": "K. Uluer",
"principal_fingerprint": "sha256:…",
"agent_id": "shopper-01",
"agreement_id": "agr_demo",
"status": "active",
"demo": true
}POST /v1/orgs
Admin bootstrap. Creates a participant organization. org_type is agent_operator, wallet, bank_issuer, processor_psp, or merchant.
Request
{
"name": "Harbor Agents",
"org_type": "agent_operator"
}Response
{
"org_id": "org_…",
"name": "Harbor Agents",
"org_type": "agent_operator",
"status": "active"
}POST /v1/orgs/{org_id}/keys
Issues an API key. The raw token is returned once. Stored value is the SHA-256 hash. List responses omit the token.
Request
{
"name": "primary"
}Response
{
"key_id": "key_…",
"prefix": "…",
"scopes": ["registry:read"],
"token": "gab_…"
}POST /v1/agents
An agent operator registers an agent. public_key is an Ed25519 or P-256 JWK with no private d. principal_id is a pseudonymous id.
Request
{
"agent_id": "shopper-01",
"principal_id": "prn_demo",
"verification_level": "operator_verified",
"public_key": {"kty": "OKP", "crv": "Ed25519", "x": "…"}
}Response
{
"agent_id": "shopper-01",
"status": "active",
"verification_level": "operator_verified",
"fingerprint": "sha256:…",
"score": 700
}POST /v1/verify
Checks a payment action against the agent's active stored agreement. ALLOW records the spend. DENY maps to kata_decision BLOCK.
Request
{
"agent_id": "shopper-01",
"action": {"action_id": "act_1", "action_type": "purchase", "amount": 1300, "currency": "CAD", "proposed_at": "2026-10-04T13:55:00Z"}
}Response
{
"verdict": "ALLOW",
"kata_decision": "ALLOW",
"reasons": [],
"agent_id": "shopper-01",
"agreement_id": "agr_demo"
}POST /v1/inquiries
Purpose-coded inquiry. Returns identity, verification, active authorizations, revocations, incident counts, and the trust score. Contributors also receive recent evidence hashes.
Request
{
"agent_id": "shopper-01",
"purpose_code": "payment_authorization"
}Response
{
"inquiry_id": "inq_…",
"agent": {"agent_id": "shopper-01", "status": "active", "verification_level": "institution_attested"},
"trust_score": {"score": 724, "cold_start": false, "reasons": [{"code": "CHARGEBACK", "points": -56}]}
}POST /v1/reports
Files a transaction outcome, fraud incident, chargeback, or policy violation. evidence_hash is sha256 and 64 hex characters. The same reporter, agent, kind, and hash is a duplicate.
Request
{
"agent_id": "shopper-01",
"kind": "chargeback",
"evidence_hash": "sha256:…",
"summary": "Disputed purchase."
}Response
{
"report_id": "rpt_…",
"kind": "chargeback"
}POST /v1/subscriptions
Subscribes the caller to signed webhooks for revocation, a new incident, and a score drop of 50 points or more. The signature typ is kata-bureau-alert+jws and uses the log signing key.
Request
{
"agent_id": "shopper-01",
"webhook_url": "https://merchant.example/hooks/gab"
}Response
{
"subscription_id": "sub_…",
"agent_id": "shopper-01"
}POST /v1/portal/magic-link
Sends a portal sign-in link. The response is always sent true. In development, GAB_DEV_MAILBOX=1 keeps the latest link at GET /v1/dev/mailbox.
Request
{
"email": "principal@example.com"
}Response
{
"sent": true
}POST /v1/admin/seed-demo
Inserts the public demo organizations, shopper-01, and agr_demo into the live repository. Authorization is the GAB_ADMIN_TOKEN bearer. The route stays closed unless GAB_ALLOW_DEMO_SEED=1. It does not require GAB_DEMO. A second call returns already_present true and does not insert another copy. The response omits the admin token.
Response
{
"operator_key": "gab_demo_operator_public",
"wallet_key": "gab_demo_wallet_public",
"merchant_key": "gab_demo_merchant_public",
"agent_id": "shopper-01",
"agreement_id": "agr_demo",
"already_present": "false"
}