MemoryNode API usage
Canonical HTTP reference for the memorynode-api Cloudflare Worker. Source of truth for behavior is code in apps/api/src/. The regenerated docs/external/openapi.yaml documents the public product surface (run pnpm openapi:gen) — internal, operator, and advanced routes may still exist in the Worker but are omitted from that contract.
- Production base:
https://api.memorynode.ai - Hosted MCP base:
https://mcp.memorynode.ai(same Worker) - Staging base:
https://api-staging.memorynode.ai - Local dev:
http://127.0.0.1:8787
Product focus: make users feel remembered for Indian SaaS founders shipping AI chat or copilots inside their product (PRODUCT.md).
Advanced surfaces (connectors read settings, audit exports, pruning metrics, admin routes, etc.) may exist on the Worker for operators; they are omitted from the published OpenAPI contract — see section 10.
OpenAPI is a subset: openapi.yaml covers Tier A memory/search/context/usage only. Dashboard session routes, billing, and hosted MCP are documented in this file (§7) — not in OpenAPI. Do not generate a client from OpenAPI alone for console setup or PayU checkout.
1. Authentication
Dispatched in apps/api/src/auth.ts and apps/api/src/lifecycle/handleRequestImpl.ts.
| Mode | Trigger | Validation | Uses |
|---|---|---|---|
| API key (K) | Authorization: Bearer <key> or x-api-key: <key> | SHA-256 of key + API_KEY_SALT then authenticate_api_key(p_key_hash) RPC | All /v1/* tenant routes |
| Dashboard session (S) | Cookie: mn_dash_session=<opaque> + x-csrf-token | Row in dashboard_sessions + CSRF double-submit | /v1/* tenant routes from browser |
| Admin (A) | x-admin-token | Equality against MASTER_ADMIN_TOKEN or HMAC-SHA256 signed form; optional IP allowlist (ADMIN_ALLOWED_IPS); ADMIN_BREAK_GLASS | /admin/*, /v1/admin/* |
| PayU webhook (H) | form body | Reverse SHA-512 over PayU response fields using PAYU_MERCHANT_SALT (see payuReconcile.ts) | POST /v1/billing/webhook only |
| Internal MCP (I) | x-internal-mcp: 1 + x-internal-secret: <MCP_INTERNAL_SECRET> | Constant-time compare | Internal hosted-MCP → REST subrequests |
| Public (P) | — | — | /healthz, /ready, /v1/health |
Customers: create and revoke keys only via the console dashboard routes (POST /v1/dashboard/api-keys, GET /v1/dashboard/api-keys, POST /v1/dashboard/api-keys/revoke) while signed in — see §6.7. Do not use /v1/api-keys in app code or quickstarts.
Operators: POST /v1/api-keys, GET /v1/api-keys, and POST /v1/api-keys/revoke require x-admin-token (MASTER_ADMIN_TOKEN). They are internal/operator-only and are not in the generated OpenAPI contract.
All API keys are rate-limited at 15 RPM for the first 48 h after api_keys.created_at; after that the default is 60 RPM per key. See packages/shared/src/plans.ts.
Webhook forwarding uses internal headers after signature verification, but that internal token path is route-bound to POST /v1/memories and is not accepted as a general-purpose auth bypass on other routes.
1.1 Auth quick reference (which client uses what)
| You are building… | Use | Do not use |
|---|---|---|
| Production SaaS backend (Node, Python, etc.) | API key (K) on POST /v1/memories and POST /v1/search | Dashboard session cookie from the browser |
| MemoryNode console (Playground, setup) | Dashboard session (S) — POST /v1/dashboard/init then cookie + CSRF on mutating calls | Pasting a live API key into Playground |
| Creating keys for your app | Dashboard session → POST /v1/dashboard/api-keys | POST /v1/api-keys (operator x-admin-token only) |
| Cursor / Claude Desktop / agent IDE | API key (K) via REST/SDK first; optional MCP (MCP_SERVER.md) | MCP as the only integration path for your product backend |
| PayU billing callback | PayU webhook (H) on POST /v1/billing/webhook | API key or session |
| On-call / cron / hygiene | Admin (A) on /admin/* | Customer-facing docs or quickstarts |
Integrator rule: ship with REST + @memorynodeai/sdk (transport: "rest" default). Use the same owner_id as your app's logged-in user id.
Contributor map (monorepo layers, not customer copy): docs/internal/ARCHITECTURE.md.
2. API surface tiers
Use this map when writing docs, SDK examples, and console copy. Tier A is what new developers should see first. Tier B is for advanced integrations. Tier C is operator-only — never put Tier C routes in customer quickstarts.
Tier A — Customer activation (OpenAPI + quickstart)
| Route | Purpose |
|---|---|
POST /v1/memories | Save memory |
POST /v1/search | Recall memory |
POST /v1/context | Assembled context for prompts |
GET /v1/usage/today | Plan caps vs usage |
POST /v1/dashboard/init | Console one-shot setup (session cookie + workspace) |
GET /v1/dashboard/workspaces | List workspaces for signed-in user |
POST /v1/dashboard/api-keys | Create API key (plaintext returned once) |
GET /v1/dashboard/api-keys | List masked keys |
POST /v1/dashboard/api-keys/revoke | Revoke a key |
GET /v1/billing/status | Entitlement / plan status |
POST /v1/billing/checkout | PayU checkout form |
GET /v1/health, GET /healthz | Health |
GET /v1/memories, GET/DELETE /v1/memories/:id | List / read / delete |
Hosted MCP (/v1/mcp) | Secondary — 7 tools; see MCP_SERVER.md (not in OpenAPI v1) |
Tier B — Power-user (Worker + this doc; not quickstart-first)
| Route | Purpose |
|---|---|
POST /v1/ingest | Advanced ingest dispatch |
POST /v1/memories/conversation | Transcript ingest |
Tier C — Internal / operator only (not in public OpenAPI)
| Route family | Auth | Notes |
|---|---|---|
/admin/*, /v1/admin/* | x-admin-token | Webhook reprocess, usage reconcile, session cleanup, memory hygiene/retention, billing health |
POST /v1/workspaces | Admin API key or operator tooling | Legacy workspace create |
GET/POST /v1/api-keys, POST /v1/api-keys/revoke | x-admin-token | Operator key management — not for customers |
POST /v1/billing/webhook | PayU signature | Server-to-server only |
GET /v1/dashboard/overview-stats | Dashboard session | Console-only metrics |
3. Middleware order
From handleRequestImpl in apps/api/src/lifecycle/handleRequestImpl.ts (health short-circuit in healthRoutes.ts):
- Request-id resolve, CORS + security headers ensemble.
- Short-circuit health endpoints (
/healthz,/ready,/v1/health). - CORS deny if
Originis not inALLOWED_ORIGINS(except hosted MCP paths). enforceRuntimeConfigGuardsandensureRateLimitDo.OPTIONSshort-circuit.assertBodySize(bounded byMAX_BODY_BYTES/MAX_IMPORT_BYTES).KNOWN_PATH_ALLOWED_METHODS405 gate withAllow:header.- Production dashboard
ALLOWED_ORIGINSgate. createSupabaseClient(env)+db_access_path_selectedlog.- Hosted MCP path → IP rate limit →
handleHostedMcpRequest. - Dashboard session POST/logout inline.
- Enforce route-level auth and handler dispatch via
route(). - Build
handlerDeps, instantiate factories, callroute(). 404ifroute()returns null.- Catch:
ApiError-shaped response witherror_code; else500 INTERNAL. - Finally:
emitAuditLogandrequest_completedstructured log.
4. Error envelope
Errors emitted by the outer catch in handleRequestImpl (apps/api/src/lifecycle/handleRequestImpl.ts) use:
{ "error": { "code": "STRING_CODE", "message": "human readable" } }
Typical codes: BAD_REQUEST, UNAUTHORIZED, FORBIDDEN, NOT_FOUND, PAYLOAD_TOO_LARGE, RATE_LIMITED, CAP_EXCEEDED, TRIAL_EXPIRED, COST_BUDGET_EXCEEDED, INTERNAL. Correlate responses with the x-request-id header.
5. Rate limits, concurrency, quotas
All defined in apps/api/src/auth.ts, apps/api/src/usage/quotaReservation.ts, and packages/shared/src/plans.ts.
| Control | Default | Source |
|---|---|---|
| Per-key RPM | 60 (15 for new keys, 48 h) | RATE_LIMIT_MAX, RATE_LIMIT_RPM_NEW_KEY |
| Per-workspace RPM | 120 (300 for scale) | WORKSPACE_RPM_DEFAULT, WORKSPACE_RPM_SCALE |
| Per-workspace in-flight | 8 | WORKSPACE_CONCURRENCY_MAX, TTL 30000 ms |
| Cost/minute burst | 15 INR | WORKSPACE_COST_PER_MINUTE_CAP_INR |
| Daily and period caps | atomic via Postgres | reserve_usage_if_within_cap / commit_usage_reservation |
| Global AI cost budget | fail-closed (prod) | AI_COST_BUDGET_INR, 60 s cache |
When entitlement verification is unavailable, quota-consuming routes move into temporary read-only degradation (ENTITLEMENT_DEGRADED, HTTP 503) until billing checks recover.
Trial gate (quota-consuming routes)
After auth, handlers resolve entitlement and today's usage, then run the trial gate before cap reservation:
| Step | Module |
|---|---|
| Quota resolve | apps/api/src/usage/quotaResolution.ts |
| Usage lookup | apps/api/src/usage/dailyUsage.ts |
| Trial gate | apps/api/src/trialWrites.ts + packages/shared/src/trialAccess.ts |
| Cap reserve | apps/api/src/usage/quotaReservation.ts |
Trial workspaces: blocked when 14 days pass or trial usage limits are hit → HTTP 402 TRIAL_EXPIRED (includes upgrade_required). Paid plans at cap → daily_cap_exceeded / CAP_EXCEEDED instead.
Hosted MCP write tools use the same trial rule before mutating; see MCP_SERVER.md.
Chat completions provider (Worker)
Optional multi-vendor chat routing (default OpenAI): CHAT_PROVIDER = openai | anthropic | gemini in apps/api/src/env.ts. Keys: ANTHROPIC_API_KEY, GEMINI_API_KEY (Google AI Studio); OPENAI_API_KEY still powers embeddings when EMBEDDINGS_MODE=openai and powers chat when CHAT_PROVIDER=openai. Optional CHAT_MODEL overrides the default cheap model for the active chat provider. Implementation: apps/api/src/llm/chatComplete.ts.
Embeddings are not swapped when changing CHAT_PROVIDER. The memory_chunks table stores embedding_provider, embedding_dimension, and embedding_version per chunk; vector search only compares rows matching the query embedding dimension (default 1536 for legacy OpenAI/stub). No bulk re-embed is required for existing data.
Memory lifecycle intelligence (automatic)
MemoryNode applies deterministic lifecycle rules on ingest, search, and nightly hygiene — no extra routes beyond normal writes and search.
| Signal | Behavior |
|---|---|
| Dedupe | Canonical hash, normalized near-text, or embedding similarity can return an existing memory_id with deduped: true and optional dedupe_kind (near, semantic) |
| Confidence / volatility | Persisted on the memory row; used in Worker ranking (not in raw SQL recall scores) |
| Ephemeral TTL | High-volatility text may get expires_at; expired rows move to archived via the hygiene job |
| Supersession | replaces_memory_id, conflict resolution, evolution merges, and admin hygiene set lifecycle_state: replaced |
| Retrieval learning | Search/context bump implicit learning signals on the Worker (no public POST /v1/feedback in v1). Log x-request-id for support. |
Implementation: apps/api/src/memories/memoryPolicyEngine.ts, apps/api/src/pipelines/search/ranking.ts, migrations 076–078.
What shows up in HTTP responses today:
| Surface | Fields |
|---|---|
POST /v1/memories (dedupe hit) | { memory_id, stored: true, deduped: true, dedupe_kind? } |
POST /v1/memories (new row) | memory_id, stored, chunks, extraction, optional intelligence.conflict_state, optional trace.memory_evolution_*, optional superseded_memory_id |
POST /v1/search | results, pagination — no retrieval_trace in the JSON body |
POST /v1/context | context_text, citations, pagination — same search pipeline, assembled for prompts |
Retrieval architecture: Postgres RPCs (match_chunks_vector, match_chunks_text) perform recall only (similarity / ts_rank + filters). Confidence, lifecycle, type, learning, and freshness ranking run in the Worker after RRF fusion (078_search_recall_only_rpcs.sql). |
Debugging without custom tooling:
- Log
x-request-idon every call (support correlation). - Search body field
explain: trueaddsranking_reasonstring arrays on each hit (and optionalranking_reasonson the response). Intended for development and support — see DEBUGGING.md. Slight extra work on the Worker; omit in hot paths if you do not need reasons. - Chunk rows store
embedding_provider,embedding_dimension,embedding_version(default 1536-dim OpenAI/stub behavior).
6. Plans
From packages/shared/src/plans.ts. PlanId = "trial" | "build" | "deploy" | "scale".
Self-serve checkout currently offers Build only; Deploy and Scale quota rows are reference material for written-agreement tiers.
| Plan | INR | Period (d) | Writes | Reads | Embed tok | Gen tok | Storage GB | Retention (d) | Workspace RPM |
|---|---|---|---|---|---|---|---|---|---|
| trial | 0 | 14 | 100 | 500 | 50 000 | 0 | 0.1 | 30 | 60 |
| build | 1 499 | 30 | 1 000 | 2 500 | 500 000 | 150 000 | 1 | 90 | 120 |
| deploy | 4 999 | 30 | 5 000 | 15 000 | 3 000 000 | 2 500 000 | 5 | 180 | 120 |
| scale | 14 999 | 30 | 20 000 | 50 000 | 10 000 000 | 8 000 000 | 20 | 365 | 300 |
Overage rates per 1 k / per 1 M tok / per GB-mo are hard-coded per plan in plans.ts:87-203.
7. Routes (tenant-facing)
Dispatch is in apps/api/src/router.ts. K = API key. S = dashboard session.
7.1 Memories
| Method | Path | Auth | Purpose |
|---|---|---|---|
| POST | /v1/memories | K/S | Create a memory; embed, chunk; extract defaults to false — set extract: true to opt in to LLM child-memory extraction when plan allows |
| POST | /v1/memories/conversation | K/S | Create from transcript or messages (transforms → /v1/memories) |
| GET | /v1/memories | K/S | Paginated list, filters: namespace, user_id, owner_id, owner_type, memory_type, start_time, end_time, metadata |
| GET | /v1/memories/:id | K/S | Single memory |
| DELETE | /v1/memories/:id | K/S | Cascade delete with chunks |
| POST | /v1/ingest | K/S | Advanced ingest dispatch → memory / conversation / document-as-text |
7.2 Search and context
| Method | Path | Auth | Purpose |
|---|---|---|---|
| POST | /v1/search | K/S | Embed query, pgvector search, optional rerank; header x-save-history: true inserts search_query_history |
| POST | /v1/context | K/S | Search + context assembly with citations |
Search request fields (`POST /v1/search`, `POST /v1/context`)
Validated in apps/api/src/contracts/search.ts, normalized in apps/api/src/search/normalizeRequest.ts, executed in apps/api/src/pipelines/search/executeSmartMemorySearch.ts.
| Field | Values | What it does |
|---|---|---|
search_mode | hybrid (default), vector, keyword | Recall strategy: hybrid runs vector + keyword SQL recall with RRF fusion; vector is embedding match only; keyword is full-text match only (no query embed). |
retrieval_profile | balanced (default), recall, precision | Score floor preset for min_score (not a separate API mode). recall defaults to a lower floor (0.08, capped at 0.2); precision defaults higher (0.32, floored at 0.25); balanced uses your min_score or no extra default. |
min_score | 0–1 optional | Drop hits below this ranking-derived score after fusion. |
explain | true / omit | When true, each result may include ranking_reason (string codes). retrieval_trace is not returned on the public search body. |
top_k, page, page_size, filters | — | Pagination and metadata/time/type filters (see schema). |
Default smart search (recommended): omit search_mode (uses hybrid) and omit retrieval_profile (uses balanced). The Worker runs the memory planner, SQL recall, fusion, optional rerank (plan-gated), and Worker-side ranking in executeSmartMemorySearch.ts.
Not a request field: recall_only — Postgres RPCs perform recall-only scoring; final ranking always runs in the Worker (ranking_layer: "worker" in internal diagnostics only).
Explain / debug: set explain: true on the search body. For routing debug in non-production, optional request header x-mn-debug-routing: 1 adds x-mn-resolved-container-tag and related headers (see §9).
Owner identity (`owner_id` / `user_id`)
Memories and search are scoped per end-user within your workspace:
- Pass
owner_id(oruser_id, same value) = your SaaS app's logged-in user id for every write and read in production. - Use
owner_type(user|team|app) when you scope memories to teams or app-level actors; default isuser. - If
user_idandowner_idare both omitted, the API uses the canonical demo ownerdefault-user(packages/shared/src/ownerDefaults.ts) — fine for Playground and quickstarts only. - Multi-tenant products must not mix real users under
default-user; session 1 and session 2 will not see each other's memories unless they share that id. - In dev and staging only, when the default owner was applied because you omitted owner fields, responses may include
x-mn-default-owner-used: true. Production does not emit this header.
7.3 Usage
| Method | Path | Auth | Purpose |
|---|---|---|---|
| GET | /v1/usage/today | K/S | Caps vs consumed reads/writes/tokens; includes entitlement_active and entitlement_source (billing) |
7.5 Workspaces and API keys
Customers (Tier A): use dashboard session routes in §7.7 (below):
GET/POST /v1/dashboard/workspacesGET/POST /v1/dashboard/api-keys,POST /v1/dashboard/api-keys/revoke
The console App connection page (/app-connection) is the supported UI for creating keys. Plaintext keys are returned once on create; list responses are masked (key_prefix, key_last4 only).
Operators (Tier C): POST /v1/workspaces, GET/POST /v1/api-keys, and POST /v1/api-keys/revoke require x-admin-token. They use the same hashing and masked storage shape as the dashboard create_api_key RPC but are not customer-facing and must not appear in quickstart snippets or public OpenAPI.
7.6 Billing
Active path: PayU checkout in INR (POST /v1/billing/checkout → POST /v1/billing/webhook). Customer plan codes and period caps come from packages/shared/src/plans.ts via the entitlements row (resolveQuotaForWorkspace in apps/api/src/usage/quotaResolution.ts). Legacy Stripe and Launch plan names are historical only — not offered in checkout.
Internal USD/INR cost guards (AI_COST_BUDGET_INR, WORKSPACE_COST_PER_MINUTE_CAP_INR) are operator spend ceilings, not customer checkout currency.
PayU checkout is the supported billing path (POST /v1/billing/checkout).
| Method | Path | Auth | Notes |
|---|---|---|---|
| GET | /v1/billing/status | K/S | select entitlements |
| POST | /v1/billing/checkout | K/S | Body: {plan, firstname?, email?, phone?}. Inserts payu_transactions, computes SHA-512 request hash, returns {url, method:"POST", fields} for the PayU form. |
| POST | /v1/billing/webhook | H | PayU callback. Verifies reverse SHA-512 (or HMAC-SHA256 fallback), calls PayU verify API, upserts entitlements. |
7.7 Dashboard
Browser console routes use the dashboard session cookie (S) and request-scoped Supabase execution. Mutating POST routes also require a valid x-csrf-token (double-submit with the session bootstrap). JSON bodies use { ok: true, data: … } on success or { ok: false, error: { code, message, details? } } on failure unless noted.
| Method | Path | Auth | Notes |
|---|---|---|---|
| POST | /v1/dashboard/init | Supabase JWT in body | { access_token, workspace_name? }. Resolves or creates workspace, sets dashboard session cookie, returns { workspace_id, name, created, workspaces, csrf_token }. Preferred console setup path. |
| POST | /v1/dashboard/session | Supabase JWT in body | {access_token, workspace_id}; verifies via SUPABASE_JWT_SECRET, inserts dashboard_sessions, sets HttpOnly cookie, returns csrf_token. Used for workspace switch / session rebind after init (returning users). |
| POST | /v1/dashboard/bootstrap | — | Retired (removed). Use /v1/dashboard/init instead. |
| POST | /v1/dashboard/logout | S | Deletes session, clears cookie. |
| GET | /v1/dashboard/overview-stats | S | dashboard_console_overview_stats RPC. |
| GET | /v1/dashboard/workspaces | S | Lists workspaces the signed-in user belongs to (id, name, role). |
| POST | /v1/dashboard/workspaces | S + CSRF | { name }; create_workspace RPC. |
| GET | /v1/dashboard/api-keys | S | Query workspace_id? (defaults to active session workspace; must match session). list_api_keys RPC. |
| POST | /v1/dashboard/api-keys | S + CSRF | { workspace_id, name }; create_api_key RPC (returns plaintext key once). |
| POST | /v1/dashboard/api-keys/revoke | S + CSRF | { api_key_id }; revoke_api_key RPC. |
Not shipped in v1: team invites and member management (/v1/dashboard/invites, /v1/dashboard/members, …) are not routed on the public Worker yet. The console does not expose team UI. Do not call these paths until documented in a future release.
7.8 Health
| Method | Path | Auth | Notes |
|---|---|---|---|
| GET | /healthz | P | Validates critical env, returns version + embedding_model. |
| GET | /ready | P | Circuit-breaker-wrapped get_api_key_salt RPC. |
| GET | /v1/health | P | Same payload as /healthz. |
7.9 Admin
All auth with x-admin-token.
| Method | Path | Notes |
|---|---|---|
| POST | /admin/webhooks/reprocess | Rerun reconcilePayUWebhook for deferred events |
| POST | /admin/usage/reconcile | process_usage_reservation_refunds() RPC |
| POST | /admin/sessions/cleanup | Delete expired dashboard_sessions |
| POST | /admin/memory-hygiene | find_near_duplicate_memories(...); query: dry_run, limit, workspace_id |
| POST | /admin/memory-retention | Archive per retention; query: limit |
| GET | /v1/admin/billing/health | Billing health view |
7.10 MCP (secondary)
REST + SDK remain the primary integration path for SaaS backends. Hosted MCP is for builder tools (Cursor, Claude Desktop).
POST /v1/mcp,POST /mcp→ Streamable HTTP JSON-RPC (handleHostedMcpRequestin apps/api/src/handlers/mcp/hosted.ts).GET /v1/mcp,GET /mcp→ browser landing or SSE.DELETE /v1/mcp,DELETE /mcp→ close session.- Session header
mcp-session-idafterinitialize. 409 when the session registry points to another isolate — clients must re-initializeand retry (see MCP_SERVER.md). MCP_ADVANCED_TOOLS_ENABLEDdefaults off in production; P1 memory/search tools do not require it.
See docs/MCP_SERVER.md for tools, policy, and production vars.
8. Canonical flows
8.1 `POST /v1/memories`
auth → rate limit → concurrency lease → quota reserve → embed (EMBEDDINGS_MODE, versioned chunk metadata) → dedupe / conflict / evolution passes → insert memories + memory_chunks → optional LLM extraction via CHAT_PROVIDER (up to 10 child memories) → commit reservation → audit.
resolveQuotaForWorkspace uses the billing entitlement row source (entitlements).
Entitlement source changes are audited in workspace_entitlement_audit and write-protected after create.
8.2 `POST /v1/search`
auth → rate limit → read reservation → optional query embed → SQL recall (vector and/or keyword RPCs) → Worker RRF fusion + ranking (+ optional rerank) → implicit retrieval-learning signals → JSON { results, page, page_size, total, has_more } (no retrieval_trace in body). Header x-save-history: true stores history without trace snapshot.
8.3 `POST /v1/billing/checkout`
Insert payu_transactions row → build SHA-512 request hash (buildPayURequestHashInput) → return {url, method:"POST", fields}. The dashboard auto-submits the form.
8.4 `POST /v1/billing/webhook`
Verify reverse SHA-512 (or HMAC-SHA256 fallback) → verifyPayUTransactionViaApi with retry and timeout → upsertWorkspaceEntitlementFromTransaction → 200. Idempotent via payu_webhook_events.
Operator verification (no new tooling):
- Staging drill:
pnpm payu:smoke,pnpm payu:webhook-test(see DEPLOYMENT.md). - Checkout:
POST /v1/billing/checkoutreturns PayU form fields; dashboard submits to PayU; return URL hits console billing page. - Deferred webhooks:
POST /admin/webhooks/reprocesswithx-admin-tokenrerunsreconcilePayUWebhook(see runbook §33). - Correlation: every response includes
x-request-id; search logs forbilling_webhook_*,webhook_failed, or entitlement errors on that id. - Health:
GET /v1/admin/billing/health(admin token).
9. Client headers you may see
| Header | Meaning |
|---|---|
x-request-id | Correlation id on every response |
x-mn-default-owner-used | true when owner_id / user_id was omitted and default-user was applied (dev/staging only) |
x-mn-resolved-container-tag | Resolved tenant container (non-prod debug, or with x-mn-debug-routing: 1) |
x-mn-routing-mode | Isolation routing mode (non-prod debug) |
Retry-After | Seconds (429 responses) |
10. Operator and internal routes (not in OpenAPI)
These routes may exist on the Worker for operators and internal tooling. They are not part of the public product surface and are omitted from OpenAPI.
| Method | Path | Auth | Notes |
|---|---|---|---|
| GET | /v1/connectors/settings | K/S | Operator-only connector settings — not customer-facing |
11. Changes and drift
docs/external/openapi.yaml is generated from code by apps/api/scripts/generate_openapi.mjs. CI enforces OpenAPI drift with pnpm openapi:check. The generator intentionally documents a reduced product surface (core memory, search, context, usage, billing checkout/status, dashboard init/session/workspaces/api-keys, health, MCP). Operator routes (/admin/*, /v1/admin/*, PayU webhooks, connectors, audit, pruning, etc.) remain in the Worker and are described in this file where relevant, but are not duplicated as paths in OpenAPI.
Keep API truth docs aligned in the same PR (see .cursor/rules/documentation-governance.mdc).
Recent backend hardening keeps API behavior unchanged while making optional internals fail-safe in degraded or stubbed environments: learned-adjustment lookup, monthly LLM usage reads, retrieval-attribute loading, and async feedback persistence now no-op safely when dependent storage/query capabilities are unavailable. The dev/CI smoke path (pnpm smoke:ci, which boots wrangler dev with SUPABASE_MODE=stub) also auto-registers the in-memory Supabase stub on first request when stage is non-production; production stages reject SUPABASE_MODE=stub outright in apps/api/src/db/createSupabaseClient.ts so no external API behavior is affected.
Admin and billing webhook routes are served directly by the main Worker.