docs/open-source/features/rest-api.mdx
The Mem0 REST API server exposes every OSS memory operation over HTTP. Run it alongside your stack to add, search, update, and delete memories from any language that speaks REST.
<Info> **You’ll use this when…** - Your services already talk to REST APIs and you want Mem0 to match that style. - Teams on languages without the Mem0 SDK still need access to memories. - You plan to explore or debug endpoints through the built-in OpenAPI page at `/docs`. </Info> <Warning> **First time self-hosting, or upgrading from a pre-1.x build?** Start at [Self-Hosted Setup](/open-source/setup). It walks through the stack, the setup wizard, and the upgrade path for deployments that relied on open endpoints or `ADMIN_API_KEY`. This page covers the API surface and auth modes only. </Warning> <Warning> **OSS vs Platform API paths:** The self-hosted OSS server does **not** use the `/v1/` prefix. For example, the endpoint is `POST /memories`, not `POST /v1/memories/`. The [API Reference](/api-reference) documents the hosted platform at `api.mem0.ai` which uses `/v1/` paths — those do not apply to the OSS server. </Warning> <Warning> Enable API key authentication (see below) and HTTPS before exposing the server to anything beyond your internal network. </Warning>user_id, agent_id, or run_id.X-API-Key headers. Legacy ADMIN_API_KEY is still supported./docs for interactive testing and schema reference.```bash
OPENAI_API_KEY=your-openai-api-key
JWT_SECRET=$(openssl rand -base64 48)
```
2. Bootstrap the stack in one command:
```bash
cd server
make bootstrap # starts Compose, creates an admin, issues the first API key
```
Or to start the stack only and finish setup via the browser wizard at http://localhost:3000:
```bash
cd server
docker compose up -d
```
3. API is at http://localhost:8888. Code edits auto-reload.
</Tab>
</Tabs>
<Tabs>
<Tab title="Pull image">
docker pull mem0/mem0-api-server
</Tab>
<Tab title="Build locally">
docker build -t mem0-api-server .
</Tab>
</Tabs>
1. Create a `.env` file with `OPENAI_API_KEY` and `JWT_SECRET`.
2. Run the container:
```bash
docker run -p 8000:8000 --env-file .env mem0-api-server
```
3. Visit `http://localhost:8000`.
**Run directly (no Docker)**
<Warning>
This path skips Docker and assumes Postgres is already running and reachable at `POSTGRES_HOST:POSTGRES_PORT`. For a single-command local setup with Postgres included, use Docker Compose above.
</Warning>
```bash
pip install -r requirements.txt
uvicorn main:app --reload
```
Auth is on by default. Protected endpoints require either a JWT (from the dashboard login flow) or an X-API-Key header. The / redirect, /docs, and /openapi.json routes stay open so you can reach the OpenAPI explorer.
| Mode | How to send it | When to use it |
|---|---|---|
| Bearer JWT | Authorization: Bearer <access_token> | Dashboard sessions; tokens come from POST /auth/login and refresh via POST /auth/refresh |
| Per-user API key | X-API-Key: m0sk_... | Programmatic access scoped to a single dashboard user |
Legacy ADMIN_API_KEY | X-API-Key: <env value> | Back-compat for deployments that set the ADMIN_API_KEY env var |
AUTH_DISABLED=true | — | Local development only; bypasses auth entirely |
The /docs OpenAPI explorer supports both auth modes. Click Authorize at the top of the page and paste either Bearer <access_token> (JWT) or your X-API-Key value. Protected endpoints return 401 until you authorize.
Register the first admin (only works when no user exists yet), then log in:
# First admin only — returns 403 after the first admin is registered
curl -X POST http://localhost:8888/auth/register \
-H "Content-Type: application/json" \
-d '{"name": "Admin", "email": "[email protected]", "password": "strong-password"}'
curl -X POST http://localhost:8888/auth/login \
-H "Content-Type: application/json" \
-d '{"email": "[email protected]", "password": "your-password"}'
Use the returned access_token as a bearer token:
curl -X POST http://localhost:8888/memories \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <access_token>" \
-d '{
"messages": [{"role": "user", "content": "I love pizza."}],
"user_id": "alice"
}'
When the access token expires, exchange the refresh token at POST /auth/refresh.
Create a key from the dashboard API Keys page, or call POST /api-keys with a JWT. The full m0sk_... value is returned once at creation time — store it securely.
curl -X POST http://localhost:8888/memories \
-H "Content-Type: application/json" \
-H "X-API-Key: m0sk_your_key_here" \
-d '{
"messages": [{"role": "user", "content": "I love pizza."}],
"user_id": "alice"
}'
Per-user keys inherit the creating user's scope. List or revoke them via GET /api-keys and DELETE /api-keys/{id}.
ADMIN_API_KEYSet the ADMIN_API_KEY environment variable and send it as X-API-Key. The request is treated as admin-level and is not tied to a dashboard user. This mode is kept for back-compat with older self-hosted deployments — prefer JWT or per-user keys for new setups.
ADMIN_API_KEY=your-long-admin-key
curl -X POST http://localhost:8888/memories \
-H "Content-Type: application/json" \
-d '{
"messages": [
{"role": "user", "content": "I love fresh vegetable pizza."}
],
"user_id": "alice"
}'
curl -X POST http://localhost:8888/search \
-H "Content-Type: application/json" \
-d '{
"query": "vegetable",
"user_id": "alice"
}'
http://localhost:8888/docs (Compose) or http://localhost:8000/docs (raw Docker / uvicorn).POST /search).The OSS REST server exposes the following endpoints. None use the /v1/ prefix.
| Method | Path | Description |
|---|---|---|
POST | /configure | Set memory configuration. Rejects unbundled providers with a 400 |
GET | /configure | Get the current memory configuration |
GET | /configure/providers | List the LLM and embedder providers bundled in the container |
POST | /memories | Create memories |
GET | /memories | Get all memories (filter by user_id, agent_id, or run_id) |
GET | /memories/{memory_id} | Get a specific memory |
PUT | /memories/{memory_id} | Update a memory |
DELETE | /memories/{memory_id} | Delete a specific memory |
DELETE | /memories | Delete all memories for an identifier |
GET | /memories/{memory_id}/history | Get memory history |
POST | /search | Search memories |
POST | /reset | Reset all memories |
| Method | Path | Description |
|---|---|---|
GET | /auth/setup-status | Returns {needsSetup: bool}. Open, no auth required |
POST | /auth/register | Register the first admin. Registration closes after the first admin is created; additional accounts are provisioned by the existing admin. |
POST | /auth/login | Exchange email and password for access and refresh JWTs |
POST | /auth/refresh | Exchange a refresh token for a new access token |
GET | /auth/me | Get the current authenticated user (JWT required) |
PATCH | /auth/me | Update the caller's name or email. 409 if the new email is already in use |
POST | /auth/change-password | Change the caller's password. 401 if the current password is wrong; new password must be at least 8 characters |
All /api-keys endpoints require a JWT.
| Method | Path | Description |
|---|---|---|
GET | /api-keys | List the caller's API keys |
POST | /api-keys | Create a new key; the full m0sk_... value is returned once |
DELETE | /api-keys/{id} | Revoke an API key |
| Method | Path | Description |
|---|---|---|
GET | /requests?limit=N | Recent API call log (JWT or admin key) |
| Method | Path | Description |
|---|---|---|
GET | /entities | Distinct user_id / agent_id / run_id values with memory counts |
DELETE | /entities/{entity_type}/{entity_id} | Cascade-delete all memories for an entity; entity_type is user, agent, or run |
The /auth/*, /api-keys, /requests, and /entities routes are new to the self-hosted server and primarily back the dashboard, but you can call them directly from your own tooling.
/docs to confirm the server is reachable.POST /memories → GET /memories/{id} → DELETE /memories/{id}.AUTH_DISABLED=true in production. If you rely on ADMIN_API_KEY, use a long value (16+ chars) or prefer per-user API keys.