How the /api/v1 Web API Provides Read-Only Access to Memory Data in AI Memory

The /api/v1 endpoint in the AI Memory repository is a purpose-built JSON API that exposes knowledge base data through strictly read-only operations, utilizing bearer-token authentication, SHA-256 ETags, and architectural isolation from write interfaces to serve third-party front-ends safely.

The akitaonrails/ai-memory repository implements a Rust-based knowledge management system where the web API surface at /api/v1 serves as the primary interface for external tools to query memory data. This API is intentionally designed as a read-only layer, ensuring that external consumers can retrieve workspaces, projects, pages, and search results without risk of modifying the underlying knowledge base.

Read-Only by Architectural Design

The read-only guarantee stems from the API's implementation in crates/ai-memory-web/src/routes/api.rs, where every handler operates exclusively on the WebState reader and wiki components.

No Write Operations in Router Handlers

Unlike administrative interfaces, the /api/v1 route handlers never invoke writer methods. The router only accesses the reader field from the shared application state, which provides methods such as list_workspaces(), list_projects(), and search_pages() defined in crates/ai-memory-store/src/reader.rs. This architectural constraint means the API physically cannot execute creates, updates, or deletes regardless of request payload, as the WebState passed to handlers lacks write-capable dependencies.

Separation from Mutation Interfaces

Any mutation operations—including page creation, editing, deletion, linting, or consolidation—are routed exclusively through /admin/* endpoints (CLI access) or MCP (Model Context Protocol) tools. This strict separation ensures that the public web API remains a read-only surface by construction, with write functionality isolated behind additional authorization layers.

Authentication and Row-Level Security

Requests to /api/v1 undergo the same bearer-token and host-allowlist middleware that protects MCP, hook, and admin routes, as configured in crates/ai-memory-cli/src/commands/serve.rs.

Owner Filtering with owner_filter_for

After authentication, the helper function owner_filter_for (defined in crates/ai-memory-web/src/routes/api.rs) derives an OwnerFilter that restricts query results to rows owned by the authenticated caller plus explicitly shared rows. This prevents cross-tenant data leakage while allowing collaborative access where authorized.

Hand-off Redaction

Sensitive hand-off data undergoes additional filtering unless the caller possesses root operator privileges or specific authorization permissions. This ensures that automated observations and internal session notes remain private even within shared workspaces.

Cache Optimization and Performance

The API implements sophisticated HTTP caching to minimize redundant database queries and improve front-end responsiveness.

ETag and Conditional Requests

For page retrieval endpoints, the system generates a SHA-256 ETag based on content hash. Clients can include this value in If-None-Match headers to receive 304 Not Modified responses when content remains unchanged, reducing bandwidth consumption for frequently accessed documentation.

Cache-Control Directives

  • Public data endpoints (workspaces, projects, pages, global search) return Cache-Control: private, max-age=N, allowing browser caching for a configured duration.
  • Identity-dependent endpoints (hand-offs, briefings, session listings) return Cache-Control: private, no-store to prevent cached responses from leaking across user sessions.

Uniform Schema and Scoping Rules

All endpoints return consistent JSON structures defined by types such as WorkspaceSummary, PageSummary, ApiPage, and ApiSearchHit. Errors follow a uniform format: { "error": "human-readable message" } with appropriate HTTP status codes.

Global vs. Scoped Queries

  • Global operations (GET /api/v1/search) operate across all accessible workspaces.
  • Scoped queries require both workspace and project parameters; partial scopes return 400 Bad Request.
  • Multi-scope search (POST /api/v1/search) accepts up to 25 discrete scope objects in the request body, enabling complex cross-project queries while maintaining performance boundaries.

Client Integration Examples

JavaScript Client Implementation

const basePath = document.querySelector('meta[name="ai-memory-base-path"]')
                ?.getAttribute('content') ?? '';
const API = `${location.origin}${basePath}/api/v1`;
const TOKEN = localStorage.getItem('ai-memory-token');

async function apiGet(path, params) {
  const url = new URL(`${API}${path}`, location.origin);
  if (params) Object.entries(params).forEach(([k, v]) =>
    v != null && url.searchParams.set(k, v));
  const resp = await fetch(url, {
    headers: {
      Accept: 'application/json',
      ...(TOKEN ? { Authorization: `Bearer ${TOKEN}` } : {})
    }
  });
  if (!resp.ok) {
    const { error } = await resp.json().catch(() => ({ error: resp.statusText }));
    throw new Error(`${resp.status}: ${error}`);
  }
  return resp.json();
}

// Read workspace overview
const overview = await apiGet(
  '/workspaces/default/projects/ai-memory/overview',
  { limit: 10 }
);
console.log('Recent activity:', overview.briefing.activity_7d);

Command-Line Usage


# List accessible workspaces

curl -fsS "http://127.0.0.1:49374/api/v1/workspaces" \
     -H "Authorization: Bearer $TOKEN" | jq

# Retrieve page with ETag inspection

curl -I "http://127.0.0.1:49374/api/v1/workspaces/default/projects/ai-memory/pages/README.md" \
     -H "Authorization: Bearer $TOKEN"

# Multi-scope POST search (maximum 25 scopes)

curl -fsS -X POST "http://127.0.0.1:49374/api/v1/search" \
     -H "Authorization: Bearer $TOKEN" \
     -H "Content-Type: application/json" \
     -d '{"q":"memory","scopes":[{"workspace":"default","project":"ai-memory"}],"limit":10}' | jq

Summary

  • Architectural read-only guarantee: The /api/v1 surface in crates/ai-memory-web/src/routes/api.rs only accesses WebState.reader, preventing any mutation operations by design.
  • Security middleware: Bearer-token authentication combined with owner_filter_for ensures row-level security and prevents cross-tenant data access.
  • Performance optimization: SHA-256 ETag headers and granular Cache-Control directives optimize bandwidth for public data while protecting private session information.
  • Flexible scoping: Supports both global search across workspaces and precise multi-scope queries (up to 25 projects) via GET and POST endpoints.
  • Strict separation of concerns: Write operations remain isolated to /admin/* routes and MCP tools, ensuring the web API cannot modify the knowledge base even if authentication is compromised.

Frequently Asked Questions

How does the API prevent accidental write operations?

The API enforces read-only access architecturally by only exposing the reader and wiki components of WebState to route handlers in crates/ai-memory-web/src/routes/api.rs. Because the handler functions never receive access to write-capable stores, the code physically cannot execute INSERT, UPDATE, or DELETE operations regardless of request method or payload content. All mutations must route through separate /admin/* endpoints or MCP tool interfaces that require distinct authorization.

What authentication is required to access memory data?

All /api/v1 endpoints require a bearer token passed in the Authorization header, processed by the same middleware stack used for MCP and administrative routes. After validation, the owner_filter_for helper function restricts queries to resources owned by the authenticated user or explicitly shared with them. Tokens can be generated via the CLI using ai-memory generate-auth-token for programmatic access.

How does caching work for sensitive vs. public data?

Public data endpoints—such as workspace listings, project pages, and global search—attach Cache-Control: private, max-age=N headers and SHA-256 ETag values to enable browser caching and conditional requests. Identity-dependent endpoints including hand-offs and session observations use Cache-Control: private, no-store to ensure browsers never cache user-specific data, preventing potential information leakage across browser sessions or shared devices.

Can I search across multiple projects simultaneously?

Yes. While scoped queries require both workspace and project parameters for single-project access, the POST /api/v1/search endpoint accepts an array of up to 25 scope objects in the request body. Each scope specifies a workspace-project pair, enabling complex cross-project research queries while maintaining the architectural guarantee that the search remains strictly read-only and respects row-level security filters for each project in the scope list.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →