Choose OAuth or a scoped environment-secret handoff according to the client and API surface.
Two authenticated surfaces
The hosted MCP endpoint and the REST API authenticate differently. Pick the one that matches the client you are wiring, and never place a credential in public configuration or a generated URL.
- MCP — OAuth where the client supports it, otherwise Authorization: Bearer ${XMEMO_KEY}.
- REST data plane — X-API-Key: <your-assigned-api-key> (Authorization: Bearer <token> is also accepted by the server). POST /v1/agents/register is the unauthenticated self-registration exception when its onboarding conditions allow it.
- Identity headers are attribution only and never grant access.
Base URL
Set BASE_URL to the deployment origin. The hosted product uses https://xmemo.dev; the committed OpenAPI document also declares http://localhost:8000 for local development and https://api.memory-os.example.com as an example server. REST data-plane calls use /v1 paths.
BASE_URL="${BASE_URL:-https://xmemo.dev}"
curl -sS "$BASE_URL/v1/recall?query=connection%20check&limit=1" \
-H "X-API-Key: $XMEMO_KEY"
Most REST requests carry the API key header. Requests without a valid credential are rejected before any memory is read or written; POST /v1/agents/register is the documented self-registration exception.
X-API-Key: <your-assigned-api-key>
MCP authentication
OAuth clients only need the hosted server URL — the grant supplies memory:read and memory:write. Direct and headless clients read the token from the environment instead.
{
"servers": {
"XMemo": {
"type": "http",
"url": "https://xmemo.dev/mcp"
}
}
}
Scopes
The server evaluates the credential's scopes and the requested memory space independently. Use memory:read for recall, search, context, list, and project reads; use memory:write for writes and mutations. Knowledge operations strictly require knowledge:read and reject memory:read tokens with 403. Advanced direct tokens may use narrower capabilities such as memory:update, memory:delete, memory:restore, memory:redact, or memory:hard_delete. Legacy REST aliases read:memories and write:memories remain compatibility values; scope never widens owner, team, or token-space authorization.
- Read: memory:read.
- Write: memory:write; mutation operations may require a narrower capability when the token profile supports it.
- Knowledge: knowledge:read; strictly required for knowledge search and listing (memory:read tokens return 403).
- Project/team access: the token's owner or bound team and live role must also authorize the requested scope/team_id.
- Attribution headers and source fields identify a caller; they are not scopes and do not grant access.
Error schema
The OpenAPI paths declare HTTPValidationError for request validation (422) and otherwise leave most response schemas untyped. The default REST error remains a JSON object with a detail value. Recognized authorization failures may also be requested as RFC 9457-style application/problem+json; use the code field for machine handling rather than matching prose.
{
"detail": "invalid_token"
}
{
"type": "urn:xmemo:problem:invalid_token",
"title": "Invalid access token",
"status": 401,
"code": "invalid_token",
"detail": "The presented access token is missing, expired, revoked, or otherwise invalid."
}
Rate limits
OpenAPI does not publish rate-limit quotas. The runtime uses a 60-second fixed window when enabled (enabled by default outside development/local/test): the data-plane category is 600 requests per minute, memory writes use a 180-per-minute endpoint policy, and memory search/recall/context reads use a 300-per-minute endpoint policy. Operators can override these values with the MEMORY_OS_RATE_LIMIT_* environment variables; do not hard-code a quota in a client.
- 429 response: { detail: Rate limit exceeded, category, policy, limit, window_seconds, retry_after_seconds }.
- 429 headers: Retry-After, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, and X-RateLimit-Policy.
- Successful responses also expose the X-RateLimit-* limit, remaining, reset, and policy headers when the limiter is enabled.