# How the `/api/v1` JSON API Differs from the `/web` Browser UI in ai-memory

> Discover the differences between ai-memory's /api/v1 JSON API and its /web browser UI. Understand distinct response formats, CORS handling, and client interaction patterns for programmatic vs. human access.

- Repository: [Fabio Akita/ai-memory](https://github.com/akitaonrails/ai-memory)
- Tags: api-reference
- Published: 2026-08-20

---

**The `/api/v1` endpoint is a read‑only JSON API for programmatic access, while `/web` serves a human‑friendly HTML UI—both share authentication and data layers but differ in response format, CORS handling, and client interaction patterns.**

The **ai-memory** repository provides two distinct front‑end surfaces for consuming the same underlying knowledge base. Understanding how the JSON API and browser UI diverge helps developers choose the right integration path for their use case. This guide examines the architectural differences, implementation locations, and practical usage patterns for each interface.

## Core Architectural Differences

Both surfaces are built on the same data store and authentication system, yet they serve fundamentally different purposes.

| Aspect | `/api/v1` JSON API | `/web` Browser UI |
|--------|-------------------|-------------------|
| **Primary purpose** | Machine‑friendly JSON endpoints for workspaces, projects, pages, search, graphs, and sessions | Human‑friendly HTML rendering with navigation and client‑side routing |
| **Mutations** | **Read‑only by construction**—handlers contain no writer calls | Read‑only display unless a custom SPA implements separate write calls to `/admin/*` |
| **Response format** | Pure JSON with typed structures like `WorkspaceSummary` and `PageHit` | HTML generated from markdown with `<base href>` and optional SPA meta tags |
| **Error format** | Always returns `{ "error": "…" }` | HTTP error pages or JavaScript error handling in SPAs |

## Authentication and Security

Both interfaces share identical security middleware. According to the source in [`crates/ai-memory-web/src/mount.rs`](https://github.com/akitaonrails/ai-memory/blob/main/crates/ai-memory-web/src/mount.rs), the same **bearer‑token and host‑allowlist** protection applies to `/api/v1`, `/mcp`, `/hook`, `/admin/*`, and `/web`.

Anonymous requests receive `401 Unauthorized`. Browsers can supply credentials via:

- HTTP Basic authentication prompt
- Token injection through headers or cookies

The authentication layer is implemented in the shared router setup, ensuring consistent access control across all front‑end surfaces.

## CORS and Cross‑Origin Behavior

**JSON API (`/api/v1`):** Supports an optional CORS layer configurable via `--cors-allow-origin`. This enables third‑party web applications and CLI tools running on different origins to fetch data programmatically.

**Browser UI (`/web`):** Serves same‑origin without CORS headers. Since browsers load the UI directly from the ai-memory host, cross‑origin handling is unnecessary.

This distinction is handled in [`crates/ai-memory-cli/src/commands/serve.rs`](https://github.com/akitaonrails/ai-memory/blob/main/crates/ai-memory-cli/src/commands/serve.rs), where CORS middleware is conditionally applied based on configuration flags.

## Response Formats and Caching

### JSON API Responses

Endpoints return structured data with cache control headers. Example response types from [`crates/ai-memory-store/src/reader.rs`](https://github.com/akitaonrails/ai-memory/blob/main/crates/ai-memory-store/src/reader.rs) include:

- `WorkspaceSummary` — workspace metadata and project counts
- `PageHit` — search results with relevance scores
- `BriefingSnapshot` — compiled session briefings

Cache headers vary by endpoint:
- Authenticated endpoints: `private` or `no-store`
- Public endpoints: `ETag` with conditional 304 responses

### Browser UI Responses

The built‑in UI serves:
- Static assets with standard file‑based caching
- Dynamic HTML with auth‑dependent cache busting
- Injected `<meta name="ai-memory-base-path">` for SPA path resolution

## Implementation Locations

The source code reveals clear separation of concerns:

| Component | File Path |
|-----------|-----------|
| API route registration | [`crates/ai-memory-web/src/routes/api.rs`](https://github.com/akitaonrails/ai-memory/blob/main/crates/ai-memory-web/src/routes/api.rs) |
| Response struct definitions | [`crates/ai-memory-store/src/reader.rs`](https://github.com/akitaonrails/ai-memory/blob/main/crates/ai-memory-store/src/reader.rs) |
| UI mounting and SPA handler | [`crates/ai-memory-web/src/mount.rs`](https://github.com/akitaonrails/ai-memory/blob/main/crates/ai-memory-web/src/mount.rs) |
| Custom UI directory validation | [`crates/ai-memory-cli/src/commands/serve.rs`](https://github.com/akitaonrails/ai-memory/blob/main/crates/ai-memory-cli/src/commands/serve.rs) |
| API documentation | [`docs/frontend-api.md`](https://github.com/akitaonrails/ai-memory/blob/main/docs/frontend-api.md) |

## Practical Usage Examples

### Fetching Data via the JSON API

```javascript
// Client-side fetch with dynamic base path detection
const basePath = document
  .querySelector('meta[name="ai-memory-base-path"]')
  ?.getAttribute('content') ?? '';
const API = `${location.origin}${basePath}/api/v1`;

async function getWorkspaces(token) {
  const resp = await fetch(`${API}/workspaces`, {
    headers: { Authorization: `Bearer ${token}` },
  });
  if (!resp.ok) {
    const { error } = await resp.json().catch(() => ({ error: resp.statusText }));
    throw new Error(`${resp.status}: ${error}`);
  }
  return resp.json(); // { workspaces: [...] }
}

```

### CLI Access with curl

```bash
TOKEN=$(ai-memory generate-auth-token)
curl -fsS "http://127.0.0.1:49374/api/v1/workspaces" \
  -H "Authorization: Bearer $TOKEN" | jq

```

### Accessing the Browser UI

Open `http://localhost:49374/web` directly. The server handles route mounting through [`mount.rs`](https://github.com/akitaonrails/ai-memory/blob/main/mount.rs), rendering markdown pages as HTML with navigation. No additional client code is required for the built‑in experience.

## When to Use Each Interface

**Choose `/api/v1` when:**
- Building automated tools, CLIs, or CI integrations
- Developing custom front‑ends or mobile applications
- Embedding ai-memory data into external dashboards
- Requiring typed, machine‑parseable responses

**Choose `/web` when:**
- Providing human researchers with a browsable knowledge base
- Deploying the stock wiki interface without custom development
- Serving as a fallback discovery mechanism for API consumers

## Summary

- **`/api/v1`** is a **read‑only JSON API** with optional CORS, designed for programmatic access—implemented in [`routes/api.rs`](https://github.com/akitaonrails/ai-memory/blob/main/routes/api.rs) with types from [`reader.rs`](https://github.com/akitaonrails/ai-memory/blob/main/reader.rs)
- **`/web`** is an **HTML UI** for human consumption, mounted via [`mount.rs`](https://github.com/akitaonrails/ai-memory/blob/main/mount.rs) with markdown‑to‑HTML rendering and SPA support
- Both share **identical authentication** middleware and underlying data stores
- **Mutating operations** are intentionally excluded from both front‑end surfaces; writes route through `/admin/*` or MCP tools
- The canonical API contract is documented in **[`docs/frontend-api.md`](https://github.com/akitaonrails/ai-memory/blob/main/docs/frontend-api.md)**, including pagination patterns, error handling, and endpoint specifications

## Frequently Asked Questions

### Can the JSON API modify data or is it strictly read‑only?

The `/api/v1` JSON API is **read‑only by construction**. Handlers in [`crates/ai-memory-web/src/routes/api.rs`](https://github.com/akitaonrails/ai-memory/blob/main/crates/ai-memory-web/src/routes/api.rs) contain no writer calls. All mutations flow through `/admin/*` endpoints or MCP tool interfaces. This design prevents accidental data corruption from third‑party integrations.

### Does the browser UI require a separate authentication setup?

No. The `/web` UI uses the **same bearer‑token and host‑allowlist middleware** as the JSON API. Both are mounted under the unified router in [`mount.rs`](https://github.com/akitaonrails/ai-memory/blob/main/mount.rs). Browsers authenticate via HTTP Basic prompts or pre‑injected tokens—the configuration is identical across both surfaces.

### How do I enable CORS for the JSON API in a production deployment?

Pass the `--cors-allow-origin` flag when starting the server via [`crates/ai-memory-cli/src/commands/serve.rs`](https://github.com/akitaonrails/ai-memory/blob/main/crates/ai-memory-cli/src/commands/serve.rs). This injects the appropriate `Access-Control-Allow-Origin` headers for cross‑origin fetches. The browser UI does not use or need CORS since it serves same‑origin requests.

### Can I replace the built‑in UI with my own single‑page application?

Yes. The CLI validates custom SPA directories and mounts them at `/web`. Ensure your SPA reads the `<meta name="ai-memory-base-path">` tag for correct routing, then make API calls to `/api/v1` for data. The mounting logic in [`mount.rs`](https://github.com/akitaonrails/ai-memory/blob/main/mount.rs) and directory validation in [`serve.rs`](https://github.com/akitaonrails/ai-memory/blob/main/serve.rs) support this extension pattern.