> ## Documentation Index
> Fetch the complete documentation index at: https://docs.usecarry.xyz/llms.txt
> Use this file to discover all available pages before exploring further.

# API reference

> The Carry web app's HTTP routes — gated chat, the companion, capture, policy, and anchoring.

The Next.js app exposes a small set of routes under `/api`. The gate runs server-side in these handlers, in `@carry/core`, before any model is called.

## POST /api/chat

Gate, generate, and return an answer with its receipt (Chat A / Chat B).

```jsonc theme={null}
// request
{ "agentId": "agent-b", "query": "Am I allergic to anything?" }
```

```jsonc theme={null}
// response
{
  "answer": "You're allergic to penicillin.",
  "receipt": {
    "answerId": "ans-…",
    "agentId": "agent-b",
    "usedMemories": [
      { "namespace": "health", "snippet": "Allergic to penicillin",
        "walrusRef": "oHJR…", "authorized": true, "verified": true }
    ],
    "blockedNamespaces": [],
    "createdAt": "2026-…"
  }
}
```

<Note>
  The gate runs before the model: `recall(agentId, query, memories, policy)` returns only allowed memories plus the blocked namespaces. Blocked memory never enters the prompt. "verified" is a live Walrus `GET`, done in parallel over the used blobs.
</Note>

## POST /api/companion

Aria — same shape as `/api/chat` but with a health-companion persona (Claude) and a warm blocked message when a namespace is revoked.

```jsonc theme={null}
{ "query": "Am I allergic to anything?" }  // → { answer, receipt }
```

## POST /api/memories · GET /api/memories

Capture a fact to Walrus, or list all stored memories.

```jsonc theme={null}
// POST
{ "namespace": "health", "content": "Allergic to penicillin", "sourceAgent": "agent-a" }
// → { "memory": { "memoryId": "m…", "walrusRef": "…", "namespace": "health", … } }
// GET → { "memories": Memory[] }
```

## GET /api/policy · POST /api/policy

Read or flip the access policy.

```jsonc theme={null}
// POST
{ "agentId": "agent-b", "namespace": "health", "allowed": false }
// → { "policy": { "agent-b": { "health": false, … }, … } }
```

## POST /api/anchor

Store the receipt to Walrus and verify the blob resolves.

```jsonc theme={null}
{ "receipt": { /* AnswerReceipt */ } }  // → { "blobId": "…", "verified": true }
```

## POST /api/anchor-sui

The full on-chain proof: store the receipt to Walrus, compute its `blake2b256` digest, and submit `anchor_receipt` — minting a verifiable **Receipt** object.

```jsonc theme={null}
// request  (claimNamespaces is optional — used to demonstrate the on-chain gate)
{ "receipt": { /* AnswerReceipt */ }, "claimNamespaces": ["billing"] }
```

```jsonc theme={null}
// response
{
  "txDigest": "98ppKaNG…",
  "receiptId": "0x4351…",
  "allAuthorized": true,
  "suiscanUrl": "https://suiscan.xyz/testnet/tx/98ppKaNG…",
  "verifyPath": "/verify/0x4351…",
  "walrusBlob": "yPe_41r…",
  "digestHex": "698dfa4b…"
}
```

<Tip>
  Anchoring is signed **server-side** via the Sui CLI keystore (no wallet). The `digestHex` is `blake2b256` over the canonical receipt bytes; the [verifier](/onchain/verifier) re-derives it from the stored Walrus blob.
</Tip>

## POST /api/reset

Reset the demo to seed state (seed memories + default policy). Handy before a recording.

```jsonc theme={null}
{ "ok": true }
```

## Typed client

A thin client wraps these in `apps/web/lib/api.ts`:

```ts theme={null}
sendChat(agentId, query)                    // POST /api/chat
sendCompanion(query)                        // POST /api/companion
capture({ namespace, content, sourceAgent })// POST /api/memories
getMemories()                               // GET /api/memories
getPolicy() / setAccess(agentId, ns, allowed) // /api/policy
anchorReceipt(receipt)                      // POST /api/anchor  -> { blobId, verified }
anchorOnSui(receipt)                        // POST /api/anchor-sui -> { receiptId, verifyPath, … }
resetDemo()                                 // POST /api/reset
```
