REST API
Machine-readable contract: OpenAPI 3.1. Orientation for LLMs: api.chainmemory.ai/llms.txt.
Authentication
All API calls require authentication via API Key in the header:
HTTP
x-api-key: your-api-key
Base URL: https://api.chainmemory.ai/v1
Memories
Create a new memory. Fee: 0.001 AIC
bash
curl -X POST https://api.chainmemory.ai/v1/memory \
-H "x-api-key: your-api-key" \
-H "Content-Type: application/json" \
-d '{
"summary": "Decided to use PostgreSQL instead of MongoDB",
"category": "decision",
"importance": 8,
"platform": "manual"
}'
javascript
const res = await fetch('https://api.chainmemory.ai/v1/memory', {
method: 'POST',
headers: {
'x-api-key': 'your-api-key',
'Content-Type': 'application/json'
},
body: JSON.stringify({
summary: 'Decided to use PostgreSQL instead of MongoDB',
category: 'decision',
importance: 8,
platform: 'api'
})
});
const memory = await res.json();
// { id: 207, hash: '0x4f2a...', memory_number: 42 }
python
import requests
res = requests.post(
'https://api.chainmemory.ai/v1/memory',
headers={'x-api-key': 'your-api-key'},
json={
'summary': 'Decided to use PostgreSQL instead of MongoDB',
'category': 'decision',
'importance': 8,
'platform': 'api'
}
)
memory = res.json()
# {'id': 207, 'hash': '0x4f2a...', 'memory_number': 42}
Parameters
| Parameter | Type | Description |
|---|---|---|
| summary* | string | Text of the memory. The only required field |
| project | string | Project to link it to. Optional: without it, tags are inferred from your projects keywords |
| tags | string[] | Tags for organization (max 10) |
| platform | string | Origin label: manual, extension, mcp, api. Defaults to api |
| category | string | DECISION, LEARNING, INTERACTION, STATE, ERROR, MILESTONE or CUSTOM. Defaults to CUSTOM |
| importance | number | 1 to 10, clamped to that range. Defaults to 5 |
List memories with optional filters.
| Parameter | Type | Description |
|---|---|---|
| project | string | Filter by project |
| tags | string | Filter by tags (comma-separated) |
| search | string | Search in content |
| limit | number | Maximum results (default: 20) |
| offset | number | Pagination offset |
Semantic search by content, tags, project, or date range.
Projects
List all user projects.
Get the consolidated project state (decisions, milestones, risks, priorities, open questions, environment).
Response (trimmed)
{
"project": "payment-system",
"schema_version": 2,
"version": 4,
"state_hash": "0x3f8c2a…e91d",
"generated_at": "2026-09-13T22:02:35.000Z",
"anchor": { "status": "anchored", "onchain_anchor_id": 12, "tx_hash": "0x…", "block_number": 681919 },
"state": {
"phase": "beta",
"current_focus": "PCI review before opening to the first tenants",
"decisions": [
{ "id": "dec_0002", "title": "PostgreSQL with RLS for multi-tenancy",
"statement": "Row-level security removes tenant filtering from the application layer",
"status": "confirmed", "superseded_by": null,
"evidence_root": "0x9a41…c07e", "created_version": 2, "updated_version": 3 }
],
"milestones": [
{ "id": "mil_0001", "title": "Database schema", "status": "done",
"evidence_root": "0x5b2d…81fa", "created_version": 1, "updated_version": 2 }
],
"risks": [
{ "id": "risk_0001", "title": "RLS performance at 100K tenants", "severity": "med", "status": "open",
"evidence_root": "0xd7e0…2a19", "created_version": 3, "updated_version": 3 }
],
"state_meta": { "version": 4, "consolidated_until_event": 150, "previous_state_hash": "0x7b2e…f4c0" }
}
}
Always the latest version; requires the owner's API key. Severity values are low, med and high.
The project's Brain as text ready to paste into a chat, ordered by relevance and cut to a character budget. Free.
| Parameter | Type | Description |
|---|---|---|
| budget | number | Maximum characters, 1,000 to 50,000 (default 7,000). The most relevant sections are kept whole; the rest is shortened to fit |
| lang | string | en (default) or es: the language of the headings. Items are returned as they were written |
| since | number | Version to compare against for the "what changed" section. Default: the previous version |
| task | string | A priority id such as pri_0015. Returns everything needed to work on that priority instead of the overview: the priority in full with its completion criterion, the risks it mitigates, what else mentions it, and every work rule and constraint |
| level | string | public (default) or full. See below |
Response (trimmed)
{
"project": "payment-system",
"version": 4,
"state_hash": "0x3f8c2a…e91d",
"level": "public",
"budget": 7000,
"lang": "en",
"since": 3,
"length": 2841,
"text": "[ChainMemory · Project State: payment-system v4]
…"
}
With task, the response carries task instead of since. Always the latest version; requires the owner's key or an organization key with access to the project (a project key only reads its own project).
public level, addresses, ports, server paths and security rules are replaced by [withheld] and counted, so the text is safe to paste into any chat. How a project's AIC are safeguarded is never included, at any level. The full level adds the withheld details; it is served only to the owner's personal key (an organization key gets 403), and every request is logged with a fingerprint of the key, the project, the version, the task, the client and the number of sensitive lines. Its response adds sensitive_lines: exactly the lines the public level would have withheld, so the client can show them to the owner before anything is pasted. If the log cannot be written, the full level is not served (503). Send an x-cm-client header to name your client in that log.
The last 100 full-level requests for this project: version, task, client, number of sensitive lines and date. Owner's key only.
Injection
Get relevant memories formatted for prompt injection. Fee: 0.1 AIC
| Parameter | Type | Description |
|---|---|---|
| memory_ids* | number[] | Your memory numbers (#N), 1 to 50. Archived and quarantined memories are excluded automatically |
| project_filter | string | Optional project label recorded with the injection |
| target_platform | string | Optional destination label (chatgpt, claude, gemini...) |
| optimistic | boolean | Return the text immediately and confirm the on-chain payment in the background |
Response
The endpoint returns the selected memories formatted for injection. Each memory arrives tagged with its user-facing number and a verification reference, so an AI can cite the exact memory behind any statement — and you can trace that citation back to its on-chain evidence. A claim stops being "trust me" and becomes "here's the memory, verify it yourself."
Seal a memory, making it permanently immutable on-chain. Fee: 0.001 AIC
| Parameter | Type | Description |
|---|---|---|
| id* | number | Memory ID to seal (URL parameter) |
Write a new project state version. Only charged if state actually changed. Fee: 0.1 AIC
| Parameter | Type | Description |
|---|---|---|
| state* | object | The full project state object |
| expected_version | number | Optimistic concurrency check |
Apply operations to project state (Brain consolidation). Fee scales with number of operations applied. Fee: 0.05 + 0.005/op AIC
| Parameter | Type | Description |
|---|---|---|
| ops* | array | Array of operations to apply (max 100) |
| consolidated_until_event | number | Event cursor for consolidation tracking |
| generated_by | string | Client identifier |
evidence_memory_ids. If any cited memory does not exist, is not yours or is not anchored yet, the whole call returns 422 evidence_unresolved with the list of what failed, and nothing is written or charged. Ops that cite nothing are accepted with evidence_root 0x000…0, and the response carries a provenance_warning.
Audit & Oracle
Audit the integrity of a specific memory: verifies hash consistency and on-chain status. Fee: 0.1 AIC
| Parameter | Type | Description |
|---|---|---|
| id* | number | Memory ID to audit (URL parameter) |
Response
Returns chain verification (on-chain status, sealed status, tx hash) and hash verification (stored vs computed event hash match). Never exposes memory content to external parties.
Full audit of a project: state hash verification, on-chain anchor check, version history, and memory count. Fee: 5 AIC
| Parameter | Type | Description |
|---|---|---|
| project* | string | Project name to audit (URL parameter) |
Response
Returns hash verification (stored vs recomputed), anchor status (on-chain ID, tx, block), version history (last 20 versions), and total memory count. The most comprehensive verification available.
Blind Oracle query: derives insights from memory metadata without accessing content. Returns verification proof. Fee: 0.1 AIC
| Parameter | Type | Description |
|---|---|---|
| question* | string | The question to query |
| project | string | Filter by project |
| memory_ids | array | Specific memory IDs to consult |
Response
Returns categories involved, time range, memory count attestation, and a SHA-256 query hash for verification. The oracle never accesses or returns memory content — only cryptographic proofs and derived metadata.
Verification
Verify the on-chain anchor of a project state. Public endpoint, no authentication required.
| Parameter | Type | Description |
|---|---|---|
| version | number | Specific version (default: latest) |
Response
{
"project": "chainmemory",
"projectId": "0x77f7d980...",
"version": 3,
"state_hash": "a7b3c9f2...",
"anchor": {
"status": "anchored",
"tx_hash": "0xce55a800a2a4e30b...",
"block_number": 123539,
"contract": "0xa7A8BA51950255b3e223a6745597C67009Fe7875"
}
}
state_hash with the one recorded in the on-chain contract. No account or API key needed.
Error Codes
| Code | Meaning | Solution |
|---|---|---|
| 401 | Invalid or missing API Key | Check your x-api-key header |
| 402 | insufficient_aic — not enough AIC for a paid operation | Response includes balance_aic, required_aic and faucet_url. Top up at the faucet |
| 403 | No permissions for this resource | Verify that the project belongs to you |
| 404 | Resource not found | Check the project name or ID |
| 409 | version conflict (POST /v1/project/:name/state with expected_version) | Re-read the state and retry |
| 422 | evidence_unresolved — a cited memory does not exist, is not yours or is not anchored yet | Wait ~30 s for anchoring, or fix the memory numbers. Nothing was written or charged |
| 429 | Too many requests from your IP | Wait and retry. The only limit enforced today is 30 requests per second per IP at the proxy; the per-plan requests-per-minute figures are not enforced yet (see Limits) |
| 429 | key_creation_limit — POST /v1/keys | At most 3 new keys per IP and 100 in total every 24 hours. The response includes retry_after_seconds |
| 500 | Internal error | Retry. If persistent, contact support |
Feature Equivalence: Extension ↔ MCP ↔ API
Not every feature is available through every integration method. This table shows what's available where:
| Feature | Extension | MCP | API REST |
|---|---|---|---|
| Save memory | ✓ 1-click save | ✓ chainmemory_remember | ✓ POST /v1/memory |
| Recall memories | ✓ Memory list | ✓ chainmemory_recall | ✓ GET /v1/memories/list |
| Search memories | ~ Basic filter | ✓ search_memories | ✓ GET /v1/memories/search |
| Inject context | ✓ Auto-inject | ✓ inject_memories | ✓ POST /v1/inject |
| Project Brain brief (overview or one task) | ✓ Inject project state | ✓ get_project_brief | ✓ GET /v1/project/:name/inject |
| Full Project State (JSON) | ✗ Not available | ✓ get_project_state | ✓ GET /v1/project/:name/state |
| Seal (anchor on-chain) | ✗ Not available | ✓ chainmemory_seal | ✓ POST /v1/seal/:id |
| Account stats | ✓ Dashboard | ✓ chainmemory_stats | ✓ GET /v1/stats |
| Profile info | ✓ Settings | ✓ chainmemory_profile | ✓ GET /v1/profile |
| List projects | ✓ Project selector | ✓ list_projects | ✓ GET /v1/projects |
| Create project | ✓ New Project | ✓ create_project | ✓ POST /v1/projects |
| Verify anchor | ~ Via Explorer link | ✓ verify_project_state, get_memory_proof | ✓ GET /v1/project/:name/state/anchor |
| Archive memory | ✓ | ✓ archive_memory | ✓ POST /v1/memories/:id/archive |
| Update tags | ✓ | ✓ update_memory_tags | ✓ PUT /v1/memories/:id/tags |
Trust & Governance
Every memory carries a trust status from the moment it is written: trusted, tentative (flagged at write time by deterministic screening rules), or quarantined (condemned by the owner). Tentative memories are always delivered marked — agents see the flag and decide. Quarantined memories are excluded from context, injection, quotes and oracle queries, while their on-chain fingerprint remains as immutable evidence. All read responses include a trust field.
Govern the trust status of a memory. Owner only.
bash
curl -X POST https://api.chainmemory.ai/v1/memories/487/trust \
-H "x-api-key: your-api-key" \
-H "Content-Type: application/json" \
-d '{"action": "quarantine"}'
Actions: approve → trusted · quarantine → quarantined · tentative → tentative. Response includes the previous status for auditability.
Complete biography of a memory as an ordered timeline. Owner only.
bash
curl https://api.chainmemory.ai/v1/memory/485/forensics \
-H "x-api-key: your-api-key"
Timeline events: born, trust, batched, checkpoint_anchored, recalled (every read, with endpoint and query), injected (every delivery, with target platform), cited_as_evidence (Project Brain items citing this memory). Includes cross-checked counters and on-chain anchoring proof. This answers the forensic question: which memory caused what, when did it enter, who read it, and where did it go.
Restore project state to a prior version, verifiably. Fee: 0.1 AIC
bash
curl -X POST https://api.chainmemory.ai/v1/project/myproject/state/rollback \
-H "x-api-key: your-api-key" \
-H "Content-Type: application/json" \
-d '{"to_version": 35}'
Append-only restore: rolling back to version N never deletes anything — it creates a new version whose content is byte-identical to N. Since hashes are computed over canonical bytes, the new version's hash equals the hash already anchored on-chain for N: the faithfulness of the restoration is a mathematical fact, not a promise. Before restoring, the server re-computes the stored content's hash and refuses (HTTP 409) if it does not match — corruption can never be restored. History is never mutated.