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

# API Reference

> Complete REST API documentation for Mengram with all endpoints, parameters, and response formats.

## Base URL

```
https://mengram.io
```

## Authentication

All `/v1/*` endpoints require a Bearer token:

```
Authorization: Bearer om-your-api-key
```

Get your API key at [mengram.io](https://mengram.io/#signup).

***

## Memory — Core

### POST /v1/add

Add memories from a conversation. Automatically extracts entities, facts, episodes, and procedures in the background.

```bash theme={null}
curl -X POST https://mengram.io/v1/add \
  -H "Authorization: Bearer om-..." \
  -H "Content-Type: application/json" \
  -d '{
    "messages": [
      {"role": "user", "content": "I use Python and Railway"},
      {"role": "assistant", "content": "Noted."}
    ],
    "user_id": "default"
  }'
```

| Parameter | Type | Default | Description |
| - | - | - | - |
| `messages` | array | required | Chat messages with `role` and `content` |
| `user_id` | string | `"default"` | User identifier for multi-user isolation |
| `agent_id` | string | null | Agent identifier |
| `run_id` | string | null | Session/run identifier |
| `app_id` | string | null | Application identifier |
| `expiration_date` | string | null | ISO datetime — facts auto-expire after this |
| `source` | string | null | Provenance source (e.g. `"discord"`, `"slack"`, `"email"`, `"api"`) |
| `metadata` | object | null | Arbitrary provenance metadata (stored on entities and facts) |
| `agent_mode` | boolean | false | Extract from all speakers (user + assistant). **Auto-enabled when `agent_id` is set.** |

Response: `{"status": "accepted", "job_id": "job-..."}`

### POST /v1/add\_text

Add memories from plain text instead of chat messages.

```json theme={null}
{"text": "Meeting notes: migrating to PostgreSQL 16", "user_id": "default", "source": "slack", "metadata": {"channel": "#engineering"}}
```

Same optional parameters as `/v1/add` (including `source` and `metadata`).

### POST /v1/add\_file

Upload a file (PDF, DOCX, TXT, MD) and extract structured memories. PDFs use two-pass vision AI extraction. Each page/chunk counts as 1 add from your quota.

**Content-Type:** `multipart/form-data` (not JSON)

```bash theme={null}
curl -X POST https://mengram.io/v1/add_file \
  -H "Authorization: Bearer om-..." \
  -F "file=@meeting-notes.pdf" \
  -F "user_id=default"
```

| Parameter | Type | Default | Description |
| - | - | - | - |
| `file` | file | required | File to upload (.pdf, .docx, .txt, .md) |
| `user_id` | string | `"default"` | User identifier |
| `agent_id` | string | null | Agent identifier |
| `run_id` | string | null | Session/run identifier |
| `app_id` | string | null | Application identifier |

**File size limits:** Free 10MB, Pro 50MB, Business 100MB.

Response (202):

```json theme={null}
{
  "status": "accepted",
  "job_id": "job-...",
  "file_type": "pdf",
  "page_count": 12,
  "quota_used": 12,
  "message": "Processing meeting-notes.pdf (12 pages/chunks) in background."
}
```

### GET /v1/memories

List all entities for a user. Supports pagination.

| Parameter | Type | Default | Description |
| - | - | - | - |
| `user_id` | string | `"default"` | User whose memories to list |
| `limit` | int | 100 | Max results |
| `offset` | int | 0 | Pagination offset |

### GET /v1/memories/full

Get all memories with full facts, relations, and knowledge in a single request.

| Parameter | Type | Default | Description |
| - | - | - | - |
| `user_id` | string | `"default"` | User whose memories to list |
| `limit` | int | 100 | Max results |
| `offset` | int | 0 | Pagination offset |

### GET /v1/memory/:name

Get details for a specific entity including facts, relations, knowledge, and metadata.

Response includes a `metadata` object with provenance information (source, agent\_id, etc.).

### DELETE /v1/memory/:name

Delete a specific entity and all its data.

### DELETE /v1/account

Permanently delete your account and **all** associated data — entities, facts, relations, knowledge, embeddings, episodes, procedures, conversation chunks, webhooks, teams you created, API keys, and usage history. Irreversible, immediate, and synchronous. Returns per-table deletion counts so you can verify completion.

```bash theme={null}
curl -X DELETE "https://mengram.io/v1/account?confirm=you@example.com" \
  -H "Authorization: Bearer om-..."
```

| Parameter | Type | Description |
| - | - | - |
| `confirm` | string | **Required.** Must exactly match your account email |

An active paid subscription is canceled in the billing provider first; if that cancellation fails, deletion aborts (502) so you're never billed for an account whose data is gone. Works identically on self-hosted deployments.

### DELETE /v1/memories/all

Delete ALL memories for a user. Irreversible.

***

## Search

### POST /v1/search

Semantic search across the knowledge graph with LLM re-ranking.

```json theme={null}
{"query": "database preferences", "user_id": "default", "limit": 5, "graph_depth": 2}
```

| Parameter | Type | Default | Description |
| - | - | - | - |
| `query` | string | required | Natural language search query |
| `user_id` | string | `"default"` | User whose memories to search |
| `limit` | int | 5 | Max results |
| `graph_depth` | int | 2 | Knowledge graph traversal depth (0-4) |
| `agent_id` | string | null | Filter by agent |
| `run_id` | string | null | Filter by run |
| `app_id` | string | null | Filter by app |
| `filters` | object | null | Metadata key-value filters (JSONB containment) |
| `max_tokens` | int | null | Room the reply may take, in estimated tokens (50–50,000). Results are cut in rank order to fit — entity by entity, fact by fact — and the response adds a `budget` report. |

**A recall that fits.** With `max_tokens`, the response carries what was cut, so the cut is never silent:

```json theme={null}
{"query": "what does this customer prefer?", "user_id": "cust_1042", "limit": 5, "max_tokens": 600}
```

```json theme={null}
{
  "results": [...],
  "budget": {
    "max_tokens": 600, "used_tokens": 512, "method": "estimate",
    "kept":    {"entities": 3, "facts": 14},
    "dropped": {"entities": 2, "facts": 9, "relations": 1, "knowledge": 2}
  }
}
```

Tokens are estimated (about four characters per token for Latin text, fewer for other scripts) — the server does not know which model reads the reply. Budget around 15% under your real limit.

**Where each fact came from.** Every result carries `facts_meta`, one entry per fact, aligned with `facts`:

```json theme={null}
{
  "entity": "app", "type": "project", "score": 0.91,
  "facts": ["deploys to Fly.io from main", "uses PostgreSQL 16"],
  "facts_meta": [
    {"source": "codex", "os": "linux", "cwd": "/home/ali/app", "session": "s-41",
     "when": "2026-09-15", "recalled": 3, "last_recalled": "2026-09-16"},
    {"source": "api", "when": "2026-09-10", "recalled": 0}
  ]
}
```

`source` is what the writer declared on `/v1/add` (`source` and `metadata`); the CLI hooks send `claude-code`, `codex` or `cursor` with the session, working directory and OS, the MCP server sends `mcp`, everything else is `api`. `recalled` and `last_recalled` count retrievals, so a fact nobody has asked for in months is visible as such. Facts are never rewritten; the tag the hooks show (`(codex, 2026-09-15)`) is built from this at read time.

**A host does not inherit another host's paths.** Send `X-Mengram-Host: <os>/<tool>` (for example `linux/claude-code`; the hooks do) and facts tied to another machine or tool are left out: a `/Users/...` path recorded on a Mac, a `~/.cursor/hooks.json` fact recorded from Cursor. Each result then says how many were withheld in `facts_left_out_for_host`. Without the header nothing is filtered, and facts saved without provenance are never filtered. From Python: `CloudMemory(api_key, host="linux/claude-code")`.

### POST /v1/search/all

Unified search across all 3 memory types.

```json theme={null}
{"query": "deployment", "user_id": "default", "limit": 5, "max_tokens": 800}
```

`max_tokens` works here too: one budget across the sections, spent in the order a task needs them — facts about the entities, then what happened, then how it was done, then raw conversation last. The `budget` report also counts `episodes`, `procedures` and `chunks`.

`chunks` (default `1`, `0` to `10`) is how many raw conversation chunks may come back as the fallback for facts extraction missed. One is the default because on a 90-day history five of them were three quarters of the tokens handed to the model while one kept recall of old facts unchanged; `0` turns the fallback off.

Response:

```json theme={null}
{
  "semantic": [...],
  "episodic": [...],
  "procedural": [...]
}
```

### POST /v1/ask

<Tip>**Pro / Growth / Business only.** Free and Starter plans return 403.</Tip>

Ask your memory a question and get a synthesized answer with citations — not a raw fact list. Mengram embeds the query, retrieves the top relevant facts, and uses Cohere Chat (`command-a-03-2025`) to write a grounded answer with native source attribution.

Counts as 1 search against your monthly quota.

```bash theme={null}
curl -X POST https://mengram.io/v1/ask \
  -H "Authorization: Bearer om-..." \
  -H "Content-Type: application/json" \
  -d '{"query": "what programming languages do I use?", "user_id": "default"}'
```

| Parameter | Type | Default | Description |
| - | - | - | - |
| `query` | string | required | Natural language question |
| `user_id` | string | `"default"` | User whose memories to use |
| `max_facts` | int | 15 | How many top facts to feed Cohere as documents (capped at 30 internally) |

Response:

```json theme={null}
{
  "answer": "You use Python and Rust. Python is your daily language and Rust is your favorite. You also use Java for enterprise systems.",
  "citations": [
    {
      "text": "Python and Rust",
      "start": 8,
      "end": 23,
      "sources": [
        {"entity": "Python", "fact": "uses Python daily for backend development"},
        {"entity": "Rust", "fact": "Rust is favorite language"}
      ]
    },
    {
      "text": "Java for enterprise systems",
      "start": 92,
      "end": 119,
      "sources": [
        {"entity": "Ali Baizhanov", "fact": "specializes in Java/Spring Boot for enterprise"}
      ]
    }
  ],
  "facts_used": 22
}
```

| Field | Type | Description |
| - | - | - |
| `answer` | string | Synthesized answer text. Empty string if Cohere can't answer from retrieved facts. |
| `citations` | array | Citation objects linking spans of `answer` back to specific facts. May be empty. |
| `citations[].text` | string | The cited substring as it appears in `answer` |
| `citations[].start` | int | Start character offset in `answer` |
| `citations[].end` | int | End character offset in `answer` |
| `citations[].sources` | array | Facts that support this citation (entity name + fact text) |
| `facts_used` | int | How many facts were passed to Cohere (capped at 30) |

**When `answer` is empty / `citations` is empty:** Cohere chose not to answer from the retrieved facts (e.g. no relevant data, or query was ambiguous). This is **not an error** — it's an honest "I don't know" rather than a hallucinated response.

**Multilingual:** Works natively across all 23 supported languages. Russian/Chinese/Japanese/Spanish queries return answers in the query language with citations to the original (often English) facts.

### GET /v1/timeline

Temporal search — find facts within a time range.

| Parameter | Type | Default | Description |
| - | - | - | - |
| `after` | string | null | ISO datetime start |
| `before` | string | null | ISO datetime end |
| `user_id` | string | `"default"` | User to search |
| `limit` | int | 20 | Max results |

***

## Cognitive Profile

### GET /v1/profile

Generate a Cognitive Profile — a ready-to-use system prompt summarizing a user from memory.

| Parameter | Type | Default | Description |
| - | - | - | - |
| `user_id` | string | `"default"` | User to profile |
| `force` | boolean | false | Regenerate (bypass cache) |

### GET /v1/profile/:user\_id

Generate a profile for a specific sub-user.

***

## Rules Generation

### GET /v1/rules

Generate a CLAUDE.md, .cursorrules, or .windsurfrules file from memory.

| Parameter | Type | Default | Description |
| - | - | - | - |
| `format` | string | `"claude_md"` | Output format: `claude_md`, `cursorrules`, `windsurf` |
| `force` | boolean | false | Regenerate (bypass cache) |
| `user_id` | string | `"default"` | User whose memories to use |

Response: `{"format": "claude_md", "content": "# Project Rules\n..."}`

***

## Episodic Memory

### GET /v1/episodes

List recent episodes. Each episode has a summary, context, outcome, and participants. Paginated — the response includes `total`, `limit`, and `offset` so you can page through everything.

| Parameter | Type | Default | Description |
| - | - | - | - |
| `limit` | int | 20 | Max results per page (1–500) |
| `offset` | int | 0 | Pagination offset |
| `after` | string | null | ISO datetime filter start |
| `before` | string | null | ISO datetime filter end |
| `user_id` | string | `"default"` | User to query |

### GET /v1/episodes/search

Semantic search over episodic memories.

| Parameter | Type | Default | Description |
| - | - | - | - |
| `query` | string | required | Search query |
| `limit` | int | 5 | Max results |
| `after` | string | null | ISO datetime filter start |
| `before` | string | null | ISO datetime filter end |
| `user_id` | string | `"default"` | User to search |

***

## Procedural Memory

### GET /v1/procedures

List learned workflows and procedures. Paginated — the response includes `total`, `limit`, and `offset`.

| Parameter | Type | Default | Description |
| - | - | - | - |
| `limit` | int | 20 | Max results per page (1–500) |
| `offset` | int | 0 | Pagination offset |
| `user_id` | string | `"default"` | User to query |

### GET /v1/procedures/search

Semantic search over procedural memories.

| Parameter | Type | Default | Description |
| - | - | - | - |
| `query` | string | required | Search query |
| `limit` | int | 5 | Max results |
| `user_id` | string | `"default"` | User to search |

### PATCH /v1/procedures/:id/feedback

Record success or failure for a procedure. On failure with context, triggers experience-driven evolution (Pro and above).

This is not the only way a procedure evolves. Mengram also infers failures from episodes as they are added and revises the matching procedure on its own, which in practice is the more common path. A revision only earns a new version number once the current one has succeeded at least once — a version nobody ran is a hypothesis, so it is edited in place rather than superseded.

| Parameter | Type | Default | Description |
| - | - | - | - |
| `success` | boolean | required | Whether the procedure worked |
| `context` | string | null | What went wrong (triggers evolution) |
| `failed_at_step` | int | null | Which step number failed |
| `user_id` | string | `"default"` | User to query |

Failure-driven revisions record the **violated assumption** (the specific belief that turned out false — not just the step number) in the evolution history, and derive a **precondition check** that accumulates in the procedure's `metadata.preconditions` — so recall returns not just the steps but what to verify before trusting them.

### GET /v1/procedures/:id/history

Get version history for a procedure — how it evolved over time.

### GET /v1/procedures/:id/evolution

Get the evolution log — what changed at each version and why.

***

## Entity Management

### DELETE /v1/entity/:name

Delete an entity and all its facts, relations, knowledge, and embeddings.

### PATCH /v1/entity/:name/type

Fix an entity's type classification.

```json theme={null}
{"type": "technology"}
```

Valid types: `person`, `project`, `technology`, `company`, `concept`, `unknown`.

### POST /v1/entity/:name/dedup

LLM-powered deduplication of facts on a single entity.

***

## Memory Management

### POST /v1/dedup

Find and merge duplicate entities using word-boundary matching.

### POST /v1/dedup\_all

Deduplicate facts across ALL entities for the user.

### POST /v1/merge

Merge source entity into target. Source gets deleted, all data moves to target.

| Parameter | Type | Default | Description |
| - | - | - | - |
| `source` | string | required | Entity to merge from |
| `target` | string | required | Entity to merge into |
| `user_id` | string | `"default"` | User |

### POST /v1/merge\_user

Merge the generic "User" entity into the primary person entity.

### POST /v1/identity

Pin which entity is **you**. Extraction context, "User" merging, and profile generation anchor to the pinned entity instead of guessing by heuristics — fixes identity drift when third parties (collaborators, tool authors) are frequently co-mentioned in your conversations.

```bash theme={null}
curl -X POST "https://mengram.io/v1/identity?entity=YourName" \
  -H "Authorization: Bearer om-..."
```

| Parameter | Type | Default | Description |
| - | - | - | - |
| `entity` | string | required | Exact name of the entity that represents you |
| `user_id` | string | `"default"` | Sub-user scope |

Returns `{"status": "pinned", "entity": "...", "entity_id": "..."}`. Pinning clears the flag from any previously pinned entity. 404 if the entity doesn't exist.

### POST /v1/archive\_fact

Archive a specific fact (soft-delete).

```json theme={null}
{"entity_name": "PostgreSQL", "fact_content": "Uses version 15"}
```

***

## Insights & Reflections

### POST /v1/reflect

Manually trigger memory reflection. Generates AI insights from facts.

### GET /v1/reflections

Get all reflections. Optional `scope` filter: `entity`, `cross`, `temporal`. Each item includes its `id` for individual deletion.

### DELETE /v1/reflections/:id

Delete a single reflection by id. Use when a generated reflection is wrong or polluted — the next reflection pass regenerates from clean facts.

```bash theme={null}
curl -X DELETE "https://mengram.io/v1/reflections/<id>" \
  -H "Authorization: Bearer om-..."
```

Returns `{"status": "deleted", "reflection_id": "..."}`, or 404 if the id doesn't exist for this user.

### GET /v1/insights

Get formatted AI insights for dashboard display.

***

## Agents

### POST /v1/agents/run

Run memory agents in the background. Returns a job\_id.

| Parameter | Type | Default | Description |
| - | - | - | - |
| `agent` | string | `"all"` | Agent to run: `curator`, `connector`, `digest`, or `all` |
| `auto_fix` | boolean | false | Auto-archive bad facts |
| `user_id` | string | `"default"` | User to run agents for |

### GET /v1/agents/history

Get agent run history. Optional `agent` filter and `limit` parameter.

### GET /v1/agents/status

Check which agents are due to run.

***

## Smart Triggers

### GET /v1/triggers

Get smart triggers for the authenticated user — reminders, contradictions, patterns.

| Parameter | Type | Default | Description |
| - | - | - | - |
| `include_fired` | boolean | false | Include already-fired triggers |
| `limit` | int | 50 | Max results |
| `user_id` | string | `"default"` | User to query |

### GET /v1/triggers/:user\_id

Get triggers for a specific sub-user.

### POST /v1/triggers/process

Process all pending triggers — sends webhooks for triggered items.

### DELETE /v1/triggers/:trigger\_id

Dismiss a specific trigger without firing its webhook.

### POST /v1/triggers/detect/:user\_id

Manually run trigger detection for a user. Returns detailed results.

***

## Knowledge Graph

### GET /v1/graph

Get the knowledge graph for visualization. Returns nodes and edges.

| Parameter | Type | Default | Description |
| - | - | - | - |
| `user_id` | string | `"default"` | User to query |

### GET /v1/feed

Activity feed — recent facts with timestamps.

| Parameter | Type | Default | Description |
| - | - | - | - |
| `limit` | int | 50 | Max items |
| `user_id` | string | `"default"` | User to query |

***

## Webhooks

### POST /v1/webhooks

Create a webhook.

```json theme={null}
{
  "url": "https://your-app.com/hook",
  "name": "Production",
  "event_types": ["memory_add", "memory_update", "memory_delete"],
  "secret": "your-hmac-secret"
}
```

### GET /v1/webhooks

List all webhooks.

### PUT /v1/webhooks/:id

Update a webhook (url, name, event\_types, active).

### DELETE /v1/webhooks/:id

Delete a webhook.

***

## Teams

### POST /v1/teams

Create a team. Returns team info with invite code.

```json theme={null}
{"name": "Engineering", "description": "Shared engineering memory"}
```

### GET /v1/teams

List your teams.

### POST /v1/teams/join

Join a team via invite code.

```json theme={null}
{"invite_code": "abc123"}
```

### GET /v1/teams/:team\_id/members

Get team members.

### POST /v1/teams/:team\_id/share

Share a memory entity with a team.

```json theme={null}
{"entity_name": "PostgreSQL"}
```

### POST /v1/teams/:team\_id/unshare

Make a shared memory personal again.

### POST /v1/teams/:team\_id/leave

Leave a team.

### DELETE /v1/teams/:team\_id

Delete a team (owner only).

***

## API Keys

### GET /v1/keys

List all API keys for your account.

### POST /v1/keys

Create a new API key.

```json theme={null}
{"name": "production-key"}
```

### DELETE /v1/keys/:key\_id

Revoke a specific API key.

### PATCH /v1/keys/:key\_id

Rename an API key.

```json theme={null}
{"name": "new-name"}
```

***

## Jobs

### GET /v1/jobs/:id

Check status of a background job.

Response: `{"status": "completed|processing|failed", ...}`

***

## Billing

### GET /v1/billing

Get current subscription plan, usage, and quotas.

### POST /v1/billing/checkout

Create a Paddle checkout session for plan upgrade.

```json theme={null}
{"plan": "pro"}
```

### POST /v1/billing/portal

Create a Paddle customer portal session for managing subscription.

***

## Statistics

### GET /v1/stats

Get usage statistics for the authenticated user. `facts` counts **active** facts only (matching what export and list endpoints return); facts archived by conflict resolution/dedup are reported separately as `archived_facts`.

### GET /v1/me

Get current account info (email, plan, user\_id).

***

## Voice (Vapi)

Webhook adapters that turn Vapi's tool-call and end-of-call events into Mengram memory operations. See the full guide at [Vapi Integration](/vapi).

### POST /v1/voice/vapi/recall

Called by Vapi as a custom tool. Returns a concise context string the assistant verbalizes at the start of a call.

**Request body** (Vapi sends both shapes; either accepted):

```json theme={null}
{
  "message": {
    "type": "tool-calls",
    "toolCallList": [{
      "id": "call_abc",
      "name": "recall_caller",
      "arguments": { "phone": "+15551234567" }
    }],
    "call": {
      "customer": { "number": "+15551234567" }
    }
  }
}
```

Or the OpenAI-nested form (`toolCalls` with `function.name` + `function.arguments` — the latter may arrive as a JSON string):

```json theme={null}
{
  "message": {
    "type": "tool-calls",
    "toolCalls": [{
      "id": "call_abc",
      "type": "function",
      "function": {
        "name": "recall_caller",
        "arguments": "{\"phone\": \"+15551234567\"}"
      }
    }]
  }
}
```

**Phone resolution order:** tool arguments → `message.call.customer.number` → "Unknown caller" fallback.

**Response** (200 — Vapi tool-result format, `result` MUST be a string):

```json theme={null}
{
  "results": [{
    "toolCallId": "call_abc",
    "result": "Known about caller (Sarah Johnson): Sarah Johnson: prefers morning slots before 11 AM | Sarah Johnson: gets anxiety with novocaine"
  }]
}
```

If `message.type` is anything other than `tool-calls` (Vapi sends many event types to the same server URL), the endpoint returns `200 {"status":"ignored","reason":"..."}` rather than 4xx — so the assistant isn't marked broken when lifecycle events arrive.

**Quota:** 1 search per call.

### POST /v1/voice/vapi/save

Called by Vapi at end of call. Routes the final transcript through Mengram's extraction pipeline, keyed per caller via `sub_user_id=voice:<E.164>`.

**Request body:**

```json theme={null}
{
  "message": {
    "type": "end-of-call-report",
    "endedReason": "customer-ended-call",
    "call": {
      "id": "...",
      "customer": { "number": "+15551234567" }
    },
    "transcript": "Agent: ...\nCaller: ..."
  }
}
```

The transcript can also live at `message.artifact.transcript` — Mengram reads whichever is present.

**Response** (202 — extraction runs in the background like `/v1/add`):

```json theme={null}
{
  "status": "accepted",
  "job_id": "job-xxxx",
  "sub_user_id": "voice:+15551234567"
}
```

**Only `end-of-call-report` triggers extraction.** Partial `transcript` events (Vapi streams these mid-call) and other lifecycle events are ignored with `{"status":"ignored"}` so the extraction pipeline doesn't fire repeatedly per call.

**Quota:** 1 add per call.

***

## Error Responses

All endpoints return structured JSON errors.

### 401 Unauthorized

Invalid or missing API key.

```json theme={null}
{"detail": "Invalid API key"}
```

### 402 Quota Exceeded

Monthly plan limit reached. Includes upgrade URL and retry timing.

```json theme={null}
{
  "error": "quota_exceeded",
  "action": "add",
  "limit": 50,
  "used": 50,
  "plan": "free",
  "upgrade_url": "https://mengram.io/checkout?token=...",
  "message": "Monthly add limit reached (50). Upgrade to Starter ($5/mo) at ...",
  "retry_after": 864000
}
```

The response also includes a `Retry-After` header (seconds until monthly reset).

| Field | Type | Description |
| - | - | - |
| `error` | string | Always `"quota_exceeded"` |
| `action` | string | Which action was blocked: `add`, `search`, `add_file` |
| `limit` | int | Monthly limit for this action |
| `used` | int | Current usage count |
| `plan` | string | Current plan: `free`, `starter`, `pro`, `business` |
| `upgrade_url` | string | Direct upgrade link (includes signed checkout token) |
| `message` | string | Human-readable message with next plan and price |
| `retry_after` | int | Seconds until quota resets (end of month) |

### 429 Rate Limited

Too many requests. Retry after the `Retry-After` header value.

```json theme={null}
{"detail": "Rate limit exceeded"}
```

***

## Response Headers

Every authenticated response includes rate limit and quota usage headers.

### Rate Limiting

| Header | Description |
| - | - |
| `X-RateLimit-Limit` | Requests allowed per minute |
| `X-RateLimit-Remaining` | Requests remaining this minute |
| `X-RateLimit-Reset` | Seconds until rate limit resets |

### Quota Usage

| Header | Description |
| - | - |
| `X-Quota-Add-Used` | Add calls used this month |
| `X-Quota-Add-Limit` | Add calls allowed this month |
| `X-Quota-Search-Used` | Search calls used this month |
| `X-Quota-Search-Limit` | Search calls allowed this month |

SDKs expose quota headers via the `.quota` property — see [Python SDK](/python-sdk#quota-usage) and [JavaScript SDK](/javascript-sdk#quota-usage).

***

## Health

### GET /v1/health

Health check. Returns basic status for unauthenticated requests; detailed diagnostics for authenticated.

<Tip>
  For interactive API docs, see [Swagger UI](https://mengram.io/swagger) or [ReDoc](https://mengram.io/redoc).
</Tip>


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