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

# On-Chain API

> API reference for the three public, read-only on-chain verification endpoints.

The On-Chain API exposes three **public, read-only** endpoints for checking an agent's Base L2 anchor status. See [On-Chain Verification](/concepts/on-chain-verification) for the conceptual background and [the guide](/guides/on-chain-verification) for a walkthrough with examples.

<Note>
  Anchoring Merkle roots and publishing score batches are **not customer-callable**. Mnemom runs them internally on a 6-hour cron under a service credential; those write paths are excluded from this reference.
</Note>

## Authentication

| Endpoint | Auth Required | Notes | Reference |
| - | - | - | - |
| `GET /v1/on-chain/verify-proof/{agent_id}` | No | Recomputes and verifies an agent's Merkle proof | [↗](/api-reference/endpoint/get-on-chain-verify-proof-agent-id) |
| `GET /v1/on-chain/status/{agent_id}` | No | Latest publication, anchor, and tree summary for an agent | [↗](/api-reference/endpoint/get-on-chain-status-agent-id) |
| `GET /v1/on-chain/history` | No | Paginated list of Merkle-root anchoring events | [↗](/api-reference/endpoint/get-on-chain-history) |

All three are public and require no `Authorization` header.

***

## Endpoints

### `GET /v1/on-chain/verify-proof/{agent_id}`

Recomputes the agent's Merkle root from its stored leaf hashes, checks the stored leaf count against the actual number of leaves, optionally verifies a single leaf's inclusion proof, and looks up the confirming anchor by the **recomputed** root.

**Parameters:**

| Parameter | In | Type | Required | Description |
| - | - | - | - | - |
| `agent_id` | path | string | Yes | Agent identifier |
| `leaf_index` | query | integer | No | Zero-based leaf index to generate and verify an inclusion proof for |

**Response:** `200 OK`

```json theme={null}
{
  "verified": true,
  "agent_id": "mnm-550e8400-e29b-41d4-a716-446655440000",
  "merkle_root": "0x3a8c...",
  "leaf_count": 347,
  "inclusion_proof": {
    "leaf_hash": "0x91fe...",
    "leaf_index": 3,
    "tree_size": 347,
    "siblings": [{ "hash": "0x02aa...", "position": "left" }]
  },
  "verification": {
    "root_recomputed_from_leaves": true,
    "leaf_count": 347,
    "leaf_count_checked": true,
    "inclusion_proof_verified": true,
    "anchored_root_source": "mnemom_database"
  },
  "anchor": {
    "tx_hash": "0x1234...",
    "block_number": 18234567,
    "chain": "base",
    "anchored_at": "2026-02-26T10:30:00.000Z"
  }
}
```

**Response fields:**

| Field | Type | Description |
| - | - | - |
| `verified` | boolean | `true` only when the root recomputes from stored leaves, the leaf count matches, any requested inclusion proof verifies, AND a confirmed anchor exists for the recomputed root |
| `agent_id` | string | Agent identifier |
| `reason` | string | Present only when `verified` is `false` -- see below |
| `merkle_root` | string | The agent's stored root (absent if no checkpoint exists yet) |
| `recomputed_root` | string | Present only on `root_mismatch`, for inspecting the discrepancy |
| `leaf_count` | integer | Present on `leaf_count_mismatch` / `leaf_index_out_of_range` |
| `leaf_hashes_length` | integer | Present only on `leaf_count_mismatch` |
| `inclusion_proof` | object \| null | The verified proof for `leaf_index`; `null` when no `leaf_index` was supplied |
| `verification` | object | What was actually checked (see below) |
| `anchor` | object | The confirming anchor; present only when `verified` is `true` |

`reason` (present only when `verified` is `false`): `no_merkle_tree`, `no_checkpoint`, `no_leaf_hashes`, `root_mismatch`, `leaf_count_mismatch`, `leaf_index_out_of_range`, `inclusion_proof_failed`, or `not_anchored`.

**`verification` object:**

| Field | Type | Description |
| - | - | - |
| `root_recomputed_from_leaves` | boolean | Whether the stored root was successfully rebuilt from stored leaves |
| `leaf_count` | integer | Stored leaf count |
| `leaf_count_checked` | boolean | Whether the stored leaf count was available to compare against the leaf array |
| `inclusion_proof_verified` | boolean \| null | `true`/`false` if `leaf_index` was supplied and checked; `null` if not supplied |
| `anchored_root_source` | `"mnemom_database"` \| null | Where the anchored root was read from -- **Mnemom's own record, not a live Base RPC read**. Null when no confirmed anchor was found. |

**`anchor` object:** `tx_hash`, `block_number`, `chain` (`"base"` or `"base-sepolia"`), `anchored_at`.

**Error responses:** `400` malformed `agent_id`, `401` (reserved), `404` agent not found, `429` rate limited, `500` internal error.

***

### `GET /v1/on-chain/status/{agent_id}`

A lighter-weight summary assembled from three tables; each nested object is `null` when no matching row exists.

**Response:** `200 OK`

```json theme={null}
{
  "agent_id": "mnm-550e8400-e29b-41d4-a716-446655440000",
  "latest_score_publication": {
    "id": "pub-abc123",
    "score": 782,
    "grade": "A",
    "tx_hash": "0xabcd...",
    "block_number": 18234589,
    "chain": "base",
    "status": "confirmed",
    "published_at": "2026-02-26T10:35:00.000Z"
  },
  "latest_anchor": {
    "tx_hash": "0x1234...",
    "block_number": 18234567,
    "chain": "base",
    "anchored_at": "2026-02-26T10:30:00.000Z"
  },
  "merkle_tree": {
    "merkle_root": "0x3a8c...",
    "leaf_count": 347,
    "tree_depth": 9,
    "updated_at": "2026-02-26T10:25:00.000Z"
  }
}
```

`latest_anchor` is filtered to `status: confirmed` anchors only. `latest_score_publication.status` can be `pending`, `confirmed`, or `failed`.

**Error responses:** `400`, `401` (reserved), `404` agent not found, `429`, `500`.

***

### `GET /v1/on-chain/history`

A paginated list of Merkle-root anchoring events (not score-publication events -- there is no publication-history endpoint).

**Query parameters:**

| Parameter | Type | Default | Description |
| - | - | - | - |
| `chain` | string | -- | Filter to `base` or `base-sepolia` |
| `agent_id` | string | -- | Filter to anchors that included this agent |
| `from` / `to` | date-time | -- | Time range filter |
| `limit` | integer | 50 | 1--100 (values above 100 are clamped) |
| `offset` | integer | 0 | Pagination offset |

**Response:** `200 OK`

```json theme={null}
{
  "anchors": [
    {
      "tx_hash": "0x1234...",
      "block_number": 18234567,
      "chain": "base",
      "anchored_at": "2026-02-26T10:30:00.000Z"
    }
  ],
  "limit": 50,
  "offset": 0
}
```

**Error responses:** `400`, `401` (reserved), `404`, `429`, `500`.

***

## Error codes

| Status | Meaning |
| - | - |
| `400` | Invalid query parameter (e.g. malformed `agent_id`, bad `chain` value) |
| `404` | Agent (or resource) not found |
| `429` | Rate limit exceeded |
| `500` | Internal server error |

## SDK usage

There is no dedicated on-chain SDK; call the endpoints directly.

```typescript theme={null}
const result = await fetch(
  'https://api.mnemom.ai/v1/on-chain/verify-proof/agent-xyz',
).then((r) => r.json());

if (result.verified) {
  console.log('Anchored at', result.anchor.chain, result.anchor.block_number);
}
```

```python theme={null}
import httpx

result = httpx.get("https://api.mnemom.ai/v1/on-chain/verify-proof/agent-xyz").json()
if result["verified"]:
    print("Anchored at", result["anchor"]["chain"], result["anchor"]["block_number"])
```

## See also

* [On-Chain Verification Concepts](/concepts/on-chain-verification) -- why anchoring exists, what it does and doesn't guarantee
* [On-Chain Verification Guide](/guides/on-chain-verification) -- full walkthrough with examples
* [Mnemom Trust Rating](/concepts/reputation-scores) -- how the anchored scores are computed


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.