Docs

API documentation

Base URL: https://api.ctxvault.dev/api/v1

All authenticated endpoints accept a Authorization: Bearer cv_... header. The web app also uses a session cookie (cv_session).

Remote MCP connector (OAuth)

If you're using ctxvault inside chat products (Claude Chat / ChatGPT connectors), the connector uses OAuth against these endpoints:

GET/.well-known/oauth-protected-resource

Protected Resource Metadata used by MCP clients to discover the OAuth authorization server.

Response

{
  "resource": "https://mcp.ctxvault.dev/mcp",
  "authorization_servers": ["https://api.ctxvault.dev"],
  "scopes_supported": ["mcp"]
}
GET/.well-known/oauth-authorization-server

OAuth Authorization Server Metadata (issuer, endpoints, supported grants).

Response

{
  "issuer": "https://api.ctxvault.dev",
  "authorization_endpoint": "/oauth/authorize",
  "token_endpoint": "/oauth/token",
  "registration_endpoint": "/oauth/register"
}
POST/oauth/register

Dynamic Client Registration (used by connector clients).

Request body

{
  "client_name": "My Connector",
  "redirect_uris": ["https://client.example.com/callback"]
}

Response

{
  "client_id": "uuid",
  "client_name": "My Connector",
  "redirect_uris": ["https://client.example.com/callback"],
  "token_endpoint_auth_method": "none"
}
GET/oauth/authorize

Authorization endpoint (redirects to web login if needed, then shows consent).

Response

302 Redirect to /login?next=... (if not signed in)
POST/oauth/token

Exchange authorization code + PKCE verifier for an access token.

Request body

grant_type=authorization_code
client_id=...
redirect_uri=...
code=...
code_verifier=...

Response

{
  "access_token": "cv_...",
  "token_type": "Bearer",
  "expires_in": 31536000,
  "scope": "mcp"
}

Authentication

POST/auth/magic-link/request

Request a magic link sign-in email. Always returns 200 to avoid user enumeration.

Request body

{ "email": "dev@acme.com" }

Response

{ "message": "If this email is valid, a sign-in link has been sent." }
POST/auth/magic-link/verify

Verify a magic link token. Sets a cv_session cookie. Returns api_key only on first login.

Request body

{ "token": "cvml_..." }

Response

{
  "message": "Signed in",
  "api_key": "cv_... (first login only)",
  "project_slug": "your-default-project"
}
POST/auth/logout

Logs out the current session (clears cv_session).

Response

{ "message": "Logged out" }

Projects

GET/projectsAuth

List all projects you have access to.

Response

[
  {
    "id": "uuid",
    "slug": "my-app",
    "name": "My App",
    "created_at": "2025-01-01T00:00:00Z"
  }
]
POST/projectsAuth

Create a new project. Requires ADMIN role.

Request body

{
  "name": "My App",
  "slug": "my-app",
  "description": "Optional description"
}

Response

{
  "id": "uuid",
  "slug": "my-app",
  "name": "My App"
}
POST/me/default-projectAuth

Set (or clear) the default project for your API key.

Request body

{ "project_slug": "my-app" }

Response

{ "message": "Default project updated", "default_project_slug": "my-app" }

Memory

POST/memory/candidatesAuth

Push memory candidates. Items are embedded and stored for review. Types: decision, convention, pattern, lesson, snippet, reference.

Request body

{
  "project_slug": "my-app",
  "items": [
    {
      "type": "decision",
      "title": "Use PostgreSQL",
      "content": "Chose PostgreSQL for pgvector support.",
      "importance": 8,
      "tags": ["database", "infrastructure"]
    }
  ]
}

Response

{ "candidate_ids": ["uuid1", "uuid2"] }
POST/memory/searchAuth

Semantic search across memory items using vector similarity.

Request body

{
  "project_slug": "my-app",
  "query": "which database did we choose?",
  "k": 5
}

Response

{
  "results": [
    {
      "id": "uuid",
      "title": "Use PostgreSQL",
      "type": "decision",
      "score": 0.92,
      "status": "verified"
    }
  ]
}
GET/memory?project=my-appAuth

List memory items with optional filters: status, type.

Response

{
  "items": [...],
  "total": 42,
  "page": 1
}
GET/memory/{id}Auth

Get a single memory item by ID.

Response

{
  "id": "uuid",
  "type": "decision",
  "title": "Use PostgreSQL",
  "content": "...",
  "status": "verified",
  "importance": 8,
  "tags": ["database"],
  "created_at": "2025-01-01T00:00:00Z"
}
POST/memory/{id}/verifyAuth

Mark a memory item as verified. Requires REVIEWER role.

Response

{ "message": "Memory verified" }
POST/memory/{id}/pinAuth

Pin a memory item (prevents decay). Requires REVIEWER role.

Response

{ "message": "Memory pinned" }
POST/memory/{id}/deprecateAuth

Deprecate a memory item. Requires REVIEWER role.

Response

{ "message": "Memory deprecated" }

Knowledge Sources

Knowledge Sources let you index external repositories (starting with GitHub) and search them semantically/keyword. This is a paid feature (pro/team/enterprise).

GET/integrations/github/startAuth

Start GitHub OAuth from the dashboard (stores a token encrypted at rest). Redirect-based flow.

Response

(redirect to GitHub)
POST/integrations/github/startAuth

Fetch-friendly start endpoint: sets an HttpOnly state cookie and returns the GitHub OAuth URL.

Response

{ "url": "https://github.com/login/oauth/authorize?..." }
GET/integrations/github/reposAuth

List repositories accessible to your connected GitHub account.

Response

{
  "repos": [
    { "full_name": "owner/repo", "html_url": "https://github.com/owner/repo", "private": false, "default_branch": "main" }
  ]
}
POST/knowledge-sourcesAuth

Create a GitHub knowledge source. The backend will enqueue an initial sync run.

Request body

{
  "provider": "github",
  "name": "CtxVault repo",
  "config": {
    "repo": "ajibadedapo/ctxvault",
    "ref": "main"
  }
}

Response

{
  "id": "uuid",
  "provider": "github",
  "name": "CtxVault repo",
  "status": "ACTIVE",
  "last_sync_at": null
}
POST/knowledge-sources/{id}/syncAuth

Trigger a re-sync (enqueue a new sync run).

Response

{ "id": "uuid", "status": "PENDING" }
POST/knowledge/searchAuth

Search indexed knowledge chunks. Uses semantic search when embeddings exist, keyword fallback otherwise.

Request body

{
  "query": "where is the deployment workflow defined?",
  "k": 5
}

Response

{
  "semantic_used": true,
  "results": [
    {
      "path": ".github/workflows/deploy.yml",
      "score": 0.83,
      "content": "..."
    }
  ]
}

Context Pack

POST/context-packAuth

Generate a context pack --- a token-budgeted bundle of relevant memories ready to inject into your LLM prompt.

Request body

{
  "project_slug": "my-app",
  "query": "how do we handle authentication?",
  "max_tokens": 2000
}

Response

{
  "pack": "## Project Context\n\n### Decisions\n- Use JWT for auth...",
  "token_count": 1850,
  "truncated": false,
  "items": [...]
}

Usage

GET/usage?project=my-appAuth

Get per-project usage counters (memory count, artifact bytes, knowledge indexed bytes) plus plan limits for the current tier.

Response

{
  "tier": "pro",
  "usage": {
    "project_id": "uuid",
    "memory_items_count": 128,
    "artifacts_count": 3,
    "artifacts_bytes": 10485760,
    "knowledge_sources_count": 1,
    "knowledge_chunks_count": 420,
    "knowledge_chunk_bytes": 7340032,
    "updated_at": "2026-02-15T00:00:00Z"
  },
  "limits": {
    "knowledge_sources_max": 5,
    "knowledge_chunk_bytes_max": 52428800
  }
}

API Keys

POST/api-keysAuth

Create a new API key. Requires ADMIN role. Roles: READER, REVIEWER, ADMIN.

Request body

{
  "name": "ci-pipeline",
  "role": "READER",
  "allowed_projects": ["my-app"]
}

Response

{
  "id": "uuid",
  "key": "cv_...",
  "prefix": "cv_abc12",
  "name": "ci-pipeline",
  "role": "READER",
  "message": "Save this key --- it cannot be recovered"
}
GET/api-keysAuth

List all API keys. Requires ADMIN role.

Response

[
  {
    "id": "uuid",
    "prefix": "cv_abc12",
    "name": "ci-pipeline",
    "role": "READER",
    "last_used_at": "2025-01-01T00:00:00Z"
  }
]
DELETE/api-keys/{id}Auth

Revoke an API key. Requires ADMIN role.

Response

{ "message": "API key revoked" }

Health

GET/health

Check server health. Returns status of database, pgvector, and object storage.

Response

{
  "status": "ok",
  "checks": {
    "db": "ok",
    "pgvector": "ok",
    "storage": "ok"
  }
}

OpenClaw agent

Base URL: https://api.ctxvault.dev/openclaw

GET/openclaw/health

Checks OpenClaw service health and reports planner/memory availability.

Response

{
  "status": "ok",
  "service": "openclaw",
  "version": "0.2.0",
  "shell_enabled": false,
  "openai_planner_enabled": true,
  "ctxvault_enabled": true
}
POST/openclaw/api/v1/agent/run

Runs the agent synchronously. Use mode=plan for planning only, or mode=execute for full execution.

Request body

{
  "goal": "Fetch API health and summarize result",
  "mode": "execute",
  "use_memory": true
}

Response

{
  "ok": true,
  "mode": "execute",
  "planner": "openai",
  "plan": [{ "id": "step-1", "tool": "http" }],
  "execution": { "steps": [] },
  "summary": "Run completed"
}
POST/openclaw/api/v1/agent/jobs

Queues an asynchronous agent job.

Request body

{
  "goal": "Collect status from internal services",
  "mode": "execute"
}

Response

{
  "job_id": "uuid",
  "status": "queued"
}
GET/openclaw/api/v1/agent/jobs/{id}

Retrieves a single job state and output/error once done.

Response

{
  "id": "uuid",
  "status": "completed",
  "input": { "goal": "..." },
  "output": { "ok": true }
}
GET/openclaw/api/v1/agent/memory/status

Reports whether ContextVault memory integration is enabled for OpenClaw.

Response

{
  "enabled": true,
  "base_url": "https://api.ctxvault.dev",
  "project": "my-project"
}