Skip to main content

On-Chain API

Part of CLPI Phase 4: On-Chain Verification. The On-Chain API anchors reputation data to Base L2 for immutable, third-party-verifiable trust records.
The On-Chain API provides programmatic access to Mnemom’s on-chain verification system — anchoring Merkle roots, publishing reputation scores, and verifying agent trust data on Base L2. All on-chain operations are submitted via Mnemom’s relayer; you do not need to hold ETH or interact with smart contracts directly. Base URL: https://api.mnemom.ai/v1/on-chain

Authentication

EndpointAuth RequiredNotes
POST /v1/on-chain/anchor-rootAPI keyAnchors a Merkle root on-chain
POST /v1/on-chain/publish-scoresAPI keyPublishes scores on-chain
GET /v1/on-chain/verify-proof/{agent_id}API keyVerifies an agent’s on-chain score
GET /v1/on-chain/status/{agent_id}API keyChecks on-chain status for an agent
GET /v1/on-chain/historyAPI keyRetrieves anchoring and publishing history
API key authentication: Pass in the Authorization header:
Authorization: Bearer {api_key}
API keys can be created in your dashboard under Settings or via POST /v1/api-keys.

Rate Limits

EndpointRate LimitWindow
POST /on-chain/anchor-root10 requestsper minute
POST /on-chain/publish-scores10 requestsper minute
GET /on-chain/verify-proof/{agent_id}30 requestsper minute
GET /on-chain/status/{agent_id}30 requestsper minute
GET /on-chain/history30 requestsper minute
Rate-limited responses return HTTP 429 with a Retry-After header.

Endpoints

POST /v1/on-chain/anchor-root

Anchor a Merkle root from the integrity checkpoint tree to the MnemoMerkleAnchor contract on Base L2. Creates an immutable, tamper-evident reference point for off-chain checkpoint data. Request body:
{
  "merkle_root": "0xabc123def456789012345678901234567890123456789012345678901234abcd",
  "leaf_count": 347,
  "tree_depth": 9
}
FieldTypeRequiredDescription
merkle_rootstringYesMerkle root hash to anchor (hex-encoded, 32 bytes)
leaf_countnumberYesNumber of leaves (checkpoints) in the tree
tree_depthnumberYesDepth of the Merkle tree
Response: 200 OK
{
  "anchor_id": "anc-7f8a9b2c",
  "merkle_root": "0xabc123def456789012345678901234567890123456789012345678901234abcd",
  "tx_hash": "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef",
  "block_number": 18234567,
  "gas_used": 48732,
  "chain": "base",
  "anchored_at": "2026-02-26T10:30:00.000Z"
}
Response fields:
FieldTypeDescription
anchor_idstringUnique identifier for this anchor operation
merkle_rootstringThe anchored Merkle root (echoed back)
tx_hashstringBase L2 transaction hash
block_numbernumberBlock number containing the anchor transaction
gas_usednumberGas consumed by the transaction
chainstringChain identifier (always "base")
anchored_atstringISO 8601 timestamp of when the root was anchored
Error responses:
StatusMeaning
400Invalid Merkle root format, missing required fields, or invalid tree parameters
401API key required or invalid
409Merkle root has already been anchored
429Rate limit exceeded

POST /v1/on-chain/publish-scores

Publish one or more agent reputation scores to the MnemoReputationRegistry contract on Base L2. Scores are published in a single batch transaction for gas efficiency. Request body:
{
  "publications": [
    {
      "agent_id": "smolt-a4c12709",
      "score": 782,
      "grade": "A"
    },
    {
      "agent_id": "smolt-b8e34f21",
      "score": 650,
      "grade": "BBB"
    }
  ]
}
FieldTypeRequiredDescription
publicationsarrayYesArray of score publication objects (max 200)
publications[].agent_idstringYesAgent identifier
publications[].scorenumberYesComposite reputation score (0-1000)
publications[].gradestringYesLetter grade: AAA, AA, A, BBB, BB, B, or CCC
Response: 200 OK
{
  "publication_id": "pub-3e4f5a6b",
  "tx_hash": "0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890",
  "block_number": 18234589,
  "gas_used": 142350,
  "agent_count": 2,
  "published_at": "2026-02-26T10:35:00.000Z"
}
Response fields:
FieldTypeDescription
publication_idstringUnique identifier for this publication batch
tx_hashstringBase L2 transaction hash
block_numbernumberBlock number containing the publish transaction
gas_usednumberGas consumed by the transaction
agent_countnumberNumber of agents published in this batch
published_atstringISO 8601 timestamp of when scores were published
Error responses:
StatusMeaning
400Missing publications, empty array, exceeds 200 agents, invalid score range, or invalid grade
401API key required or invalid
404One or more agent IDs not found
422One or more agents do not have a computed reputation score (below 50-checkpoint minimum)
429Rate limit exceeded

GET /v1/on-chain/verify-proof/

Verify an agent’s on-chain reputation score and retrieve the cryptographic proof linking the on-chain record to the underlying integrity data. Parameters:
ParameterInTypeRequiredDescription
agent_idpathstringYesAgent identifier
Response: 200 OK
{
  "agent_id": "smolt-a4c12709",
  "on_chain_score": 782,
  "grade": "A",
  "metadata_hash": "0x9876543210fedcba9876543210fedcba9876543210fedcba9876543210fedcba",
  "published_at": "2026-02-26T10:35:00.000Z",
  "block_number": 18234589,
  "tx_hash": "0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890",
  "verified": true
}
Response fields:
FieldTypeDescription
agent_idstringAgent identifier
on_chain_scorenumberScore as recorded on-chain (0-1000)
gradestringLetter grade as recorded on-chain
metadata_hashstringkeccak256 hash of the off-chain metadata at time of publication
published_atstringISO 8601 timestamp of when the score was published on-chain
block_numbernumberBlock number containing the publication transaction
tx_hashstringTransaction hash of the publication
verifiedbooleanWhether the on-chain score matches the current off-chain score and the proof is valid
Error responses:
StatusMeaning
401API key required or invalid
404Agent not found or no on-chain score exists for this agent
429Rate limit exceeded

GET /v1/on-chain/status/

Check whether an agent has an on-chain score and retrieve the current on-chain state, including the latest score and anchor information. Parameters:
ParameterInTypeRequiredDescription
agent_idpathstringYesAgent identifier
Response: 200 OK
{
  "agent_id": "smolt-a4c12709",
  "has_on_chain_score": true,
  "latest_score": {
    "score": 782,
    "grade": "A",
    "block_number": 18234589,
    "published_at": "2026-02-26T10:35:00.000Z"
  },
  "latest_anchor": {
    "merkle_root": "0xabc123def456789012345678901234567890123456789012345678901234abcd",
    "block_number": 18234567,
    "anchored_at": "2026-02-26T10:30:00.000Z"
  },
  "last_updated": "2026-02-26T10:35:00.000Z"
}
Response fields:
FieldTypeDescription
agent_idstringAgent identifier
has_on_chain_scorebooleanWhether this agent has at least one published on-chain score
latest_scoreobject | nullLatest on-chain score record, or null if no score exists
latest_score.scorenumberMost recent on-chain score
latest_score.gradestringMost recent on-chain grade
latest_score.block_numbernumberBlock number of the latest publication
latest_score.published_atstringTimestamp of the latest publication
latest_anchorobject | nullLatest Merkle root anchor relevant to this agent, or null
latest_anchor.merkle_rootstringThe anchored Merkle root
latest_anchor.block_numbernumberBlock number of the anchor transaction
latest_anchor.anchored_atstringTimestamp of the anchor
last_updatedstringMost recent on-chain activity timestamp for this agent
Error responses:
StatusMeaning
401API key required or invalid
404Agent not found
429Rate limit exceeded

GET /v1/on-chain/history

Retrieve the paginated history of on-chain anchoring and score publishing events for your account. Query parameters:
ParameterTypeRequiredDescription
pagenumberNoPage number (default: 1)
per_pagenumberNoResults per page (default: 20, max: 100)
Response: 200 OK
{
  "anchors": [
    {
      "anchor_id": "anc-7f8a9b2c",
      "merkle_root": "0xabc123def456789012345678901234567890123456789012345678901234abcd",
      "leaf_count": 347,
      "tree_depth": 9,
      "tx_hash": "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef",
      "block_number": 18234567,
      "anchored_at": "2026-02-26T10:30:00.000Z"
    }
  ],
  "publications": [
    {
      "publication_id": "pub-3e4f5a6b",
      "agent_count": 2,
      "tx_hash": "0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890",
      "block_number": 18234589,
      "published_at": "2026-02-26T10:35:00.000Z"
    }
  ],
  "page": 1,
  "per_page": 20,
  "total_anchors": 42,
  "total_publications": 18
}
Response fields:
FieldTypeDescription
anchorsarrayList of Merkle root anchor events
anchors[].anchor_idstringUnique anchor identifier
anchors[].merkle_rootstringThe anchored Merkle root hash
anchors[].leaf_countnumberNumber of leaves in the tree
anchors[].tree_depthnumberDepth of the Merkle tree
anchors[].tx_hashstringTransaction hash
anchors[].block_numbernumberBlock number
anchors[].anchored_atstringISO 8601 timestamp
publicationsarrayList of score publication events
publications[].publication_idstringUnique publication identifier
publications[].agent_countnumberNumber of agents in the batch
publications[].tx_hashstringTransaction hash
publications[].block_numbernumberBlock number
publications[].published_atstringISO 8601 timestamp
pagenumberCurrent page number
per_pagenumberResults per page
total_anchorsnumberTotal anchor events across all pages
total_publicationsnumberTotal publication events across all pages
Error responses:
StatusMeaning
401API key required or invalid
429Rate limit exceeded

Error Codes

StatusCodeDescription
400invalid_requestMissing or invalid parameters (e.g., malformed Merkle root, score out of range, invalid grade)
401unauthorizedAPI key required but not provided or invalid
404not_foundAgent not found or no on-chain data exists for the specified agent
409already_anchoredThe specified Merkle root has already been anchored on-chain
422ineligible_agentAgent does not have a computed reputation score (below 50-checkpoint minimum)
429rate_limitedToo many requests; check Retry-After header
500internal_errorServer error; retry with exponential backoff
502chain_unavailableBase L2 network is temporarily unavailable; retry after a short delay
All error responses follow the standard envelope:
{
  "error": "invalid_request",
  "message": "Merkle root must be a 32-byte hex string prefixed with 0x"
}

SDK Usage

TypeScript

import {
  anchorMerkleRoot,
  publishScores,
  verifyOnChainScore,
  getOnChainStatus,
  getOnChainHistory,
} from '@mnemom/on-chain';

// Anchor a Merkle root
const anchor = await anchorMerkleRoot({
  merkleRoot: '0xabc123def456789012345678901234567890123456789012345678901234abcd',
  leafCount: 347,
  treeDepth: 9,
});
console.log(`Root anchored in tx: ${anchor.tx_hash}`);

// Publish scores for multiple agents
const publication = await publishScores({
  publications: [
    { agentId: 'smolt-a4c12709', score: 782, grade: 'A' },
    { agentId: 'smolt-b8e34f21', score: 650, grade: 'BBB' },
  ],
});
console.log(`Published ${publication.agent_count} agents in tx: ${publication.tx_hash}`);

// Verify an agent's on-chain score
const proof = await verifyOnChainScore('smolt-a4c12709');
console.log(`Verified: ${proof.verified}, Score: ${proof.on_chain_score}`);

// Check on-chain status
const status = await getOnChainStatus('smolt-a4c12709');
console.log(`Has on-chain score: ${status.has_on_chain_score}`);

// View history
const history = await getOnChainHistory({ page: 1, perPage: 20 });
console.log(`Total anchors: ${history.total_anchors}`);
console.log(`Total publications: ${history.total_publications}`);

Python

import httpx

API_BASE = "https://api.mnemom.ai"
HEADERS = {"Authorization": f"Bearer {api_key}"}

# Anchor a Merkle root
anchor = httpx.post(
    f"{API_BASE}/v1/on-chain/anchor-root",
    headers=HEADERS,
    json={
        "merkle_root": "0xabc123def456789012345678901234567890123456789012345678901234abcd",
        "leaf_count": 347,
        "tree_depth": 9,
    },
).json()
print(f"Root anchored in tx: {anchor['tx_hash']}")

# Publish scores
publication = httpx.post(
    f"{API_BASE}/v1/on-chain/publish-scores",
    headers=HEADERS,
    json={
        "publications": [
            {"agent_id": "smolt-a4c12709", "score": 782, "grade": "A"},
            {"agent_id": "smolt-b8e34f21", "score": 650, "grade": "BBB"},
        ]
    },
).json()
print(f"Published {publication['agent_count']} agents in tx: {publication['tx_hash']}")

# Verify an agent's on-chain score
proof = httpx.get(
    f"{API_BASE}/v1/on-chain/verify-proof/smolt-a4c12709",
    headers=HEADERS,
).json()
print(f"Verified: {proof['verified']}, Score: {proof['on_chain_score']}")

# Check on-chain status
status = httpx.get(
    f"{API_BASE}/v1/on-chain/status/smolt-a4c12709",
    headers=HEADERS,
).json()
print(f"Has on-chain score: {status['has_on_chain_score']}")

# View history
history = httpx.get(
    f"{API_BASE}/v1/on-chain/history",
    headers=HEADERS,
    params={"page": 1, "per_page": 20},
).json()
print(f"Total anchors: {history['total_anchors']}")
print(f"Total publications: {history['total_publications']}")

See Also