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

# API Reference

> Complete API documentation for Cognee's knowledge graph platform

# Cognee API Reference

Welcome to the Cognee API documentation. This comprehensive reference covers all endpoints for building, managing, and querying your memory using Cognee's powerful platform.

## Getting Started

Before using the API, you need to choose how to run Cognee. You have two main options:

<CardGroup cols={2}>
  <Card title="Cognee Cloud" href="/cognee-cloud/overview" icon="cloud">
    **Managed Cloud Platform**

    Production-ready, fully managed service with automatic scaling and enterprise features.
  </Card>

  <Card title="Local Docker Setup" icon="docker">
    **Self-Hosted Development**

    Run Cognee locally using Docker for development, testing, and custom deployments.
  </Card>
</CardGroup>

## Setup Options

<Tabs>
  <Tab title="Cognee Cloud">
    **Managed Service - Recommended for Production**

    1. **Sign up** at [platform.cognee.ai](https://platform.cognee.ai/)
    2. **Create API Key** in your dashboard
    3. **Start using** the API immediately

    ```bash theme={null}
    # Your per-tenant API base URL — copy it from the API Keys page
    BASE_URL="https://your-tenant.aws.cognee.ai"

    # Authentication
    curl -H "X-Api-Key: YOUR-API-KEY" \
         -H "Content-Type: application/json" \
         $BASE_URL/health
    ```

    <Info>
      Cognee Cloud provides enterprise-grade infrastructure with automatic scaling, managed databases, and 24/7 monitoring.
    </Info>
  </Tab>

  <Tab title="Local Docker">
    **Self-Hosted - Perfect for Development**

    Quick start with Docker (single command):

    ```bash theme={null}
    # Create environment file
    echo 'LLM_API_KEY="your_openai_api_key"' > .env

    # Run Cognee container
    docker run --env-file ./.env -p 8000:8000 --rm -it cognee/cognee:main
    ```

    Or use Docker Compose — the [Docker Deployment guide](/how-to-guides/cognee-sdk/deployment/docker) has a copy-pasteable minimal Compose file for the prebuilt image, plus the repository's profile-based setup (UI, MCP, external databases).

    <Note>
      Local setup uses embedded databases by default (SQLite, LanceDB, NetworkX) for easy development.
    </Note>
  </Tab>
</Tabs>

## API Base URLs

<Warning>
  All Cognee API endpoints use the `/api/v1` prefix (e.g., `/api/v1/add`, `/api/v1/search`, `/api/v1/cognify`). The path `/api` **without** the version suffix is not a valid route and will return a 404 error. Always include `/api/v1` in your requests.
</Warning>

<AccordionGroup>
  <Accordion title="Production (Cognee Cloud)" defaultOpen>
    ```
    https://your-tenant.aws.cognee.ai
    ```

    Your tenant's API base URL is shown on the [API Keys](/cognee-cloud/ui/api-keys) page.

    **Authentication**: X-Api-Key header
    **Rate Limits**: Usage-based — requests draw on your workspace's prepaid token credits
    **Availability**: 99.9% uptime SLA
  </Accordion>

  <Accordion title="Local Development">
    ```
    http://localhost:8000
    ```

    **Authentication**: Optional (can be disabled for local development)
    **Rate Limits**: None
    **Availability**: Depends on your local setup
  </Accordion>
</AccordionGroup>

## Authentication

<Tabs>
  <Tab title="Cognee Cloud">
    **API Key Authentication**

    All requests require an API key in the header:

    ```http theme={null}
    X-Api-Key: YOUR-API-KEY
    Content-Type: application/json
    ```

    Get your API key from the [Cognee Cloud dashboard](https://platform.cognee.ai/).
  </Tab>

  <Tab title="Local Docker">
    **Optional Authentication**

    Local development typically runs without authentication:

    ```http theme={null}
    Content-Type: application/json
    ```

    To enable authentication locally, set `REQUIRE_AUTHENTICATION=true` in your `.env` file, then call `POST /api/v1/auth/register` to create a user and `POST /api/v1/auth/login` to obtain a Bearer token. See the [Deploy REST API Server](/guides/deploy-rest-api-server#authentication) guide for full details.
  </Tab>
</Tabs>

## Core API Endpoints

The Cognee API provides endpoints for the complete knowledge graph lifecycle:

<CardGroup cols={2}>
  <Card title="Data Ingestion" icon="plus">
    **`POST /api/v1/add`**

    Add text, documents, or structured data to your knowledge base.
  </Card>

  <Card title="Knowledge Processing" icon="brain">
    **`POST /api/v1/cognify`**

    Transform raw data into structured knowledge graphs with entities and relationships.
  </Card>

  <Card title="Semantic Search" icon="search">
    **`POST /api/v1/search`**

    Query your knowledge graph using natural language or structured queries.
  </Card>

  <Card title="Data Management" icon="trash">
    **`DELETE /api/v1/datasets`**

    Remove specific data items or entire datasets from your knowledge base.
  </Card>

  <Card title="Agent Management" icon="robot">
    **`/api/v1/agents/*`**

    Create and manage agent identities (with API keys), and register/unregister
    agent connections. See [Agent Management](/guides/deploy-rest-api-server#agent-management)
    and [Agent Mode](/guides/deploy-rest-api-server#agent-mode).
  </Card>
</CardGroup>

## API Features

<AccordionGroup>
  <Accordion title="Multiple Search Types">
    Choose from different search modes based on your needs:

    * **`GRAPH_COMPLETION`** (default): LLM-powered responses with graph context
    * **`RAG_COMPLETION`**: LLM answer from retrieved chunks
    * **`CHUNKS`**: Raw text segments matching your query
    * **`SUMMARIES`**: Pre-generated hierarchical summaries
    * **`TRIPLET_COMPLETION`**: Triple-based retrieval + LLM completion
    * **`CHUNKS_LEXICAL`**: Lexical (BM25-style ranking) chunk search
    * **`CODING_RULES`**: Code-focused retrieval (coding rules / codebase)
    * **`TEMPORAL`**: Time-aware retrieval
    * **`GRAPH_COMPLETION_COT`**, **`GRAPH_COMPLETION_CONTEXT_EXTENSION`**, **`GRAPH_SUMMARY_COMPLETION`**: Advanced graph modes
    * **`CYPHER`**, **`NATURAL_LANGUAGE`**: Direct or inferred Cypher (disabled when `ALLOW_CYPHER_QUERY=false`)
    * **`FEELING_LUCKY`**: Auto-select search type

    Search also supports **`wide_search_top_k`**, **`triplet_distance_penalty`**, **`retriever_specific_config`**, and **`verbose`** for advanced control in the Python API. The HTTP `POST /api/v1/search` endpoint does not currently accept these advanced parameters. See [Search Basics](/guides/search-basics) and [Search](/core-concepts/main-operations/legacy-operations/search).
  </Accordion>

  <Accordion title="Flexible Data Formats">
    Support for various input formats locally and strings on Cognee Cloud:

    * **Text**: Raw text strings, documents, articles
    * **Structured**: JSON, CSV, XML data
    * **Code**: Source code files and repositories
    * **URLs**: Web pages and online content
  </Accordion>

  <Accordion title="Remember Endpoint Parameters">
    Cognee exposes two HTTP remember endpoints, and each accepts a subset of the Python SDK [`remember()`](/python-api/remember) arguments.

    **`POST /api/v1/remember`** ingests data and builds the knowledge graph in one call. It accepts the form fields `data` (file uploads), `labels`, `external_metadata`, `datasetName`, `datasetId`, `session_id`, `node_set`, `run_in_background`, `custom_prompt`, `chunk_size`, `chunks_per_batch`, `ontology_key`, `graph_model` (a JSON-serialised schema), and `content_type`. Either `datasetName` or `datasetId` is required.

    `labels` and `external_metadata` attach a label and a metadata object to each uploaded file. Each is sent as one JSON array whose entries pair positionally with `data` (`labels=["finance", ""]`, `external_metadata=[{"source": "crm"}, null]`), and both are also accepted by `POST /api/v1/add`. They are rejected with `400` when combined with `session_id` or `content_type`, since those paths do not create the `Data` records the values are stored on. See [how per-file labels and metadata work](/cognee-cloud/functionality/data-ingestion#how-per-file-labels-and-metadata-work).

    With `content_type=skills`, the endpoint also accepts two form fields for ingesting a skill **inline** instead of uploading a `SKILL.md` file (a no-code path): `skills_text` (the `SKILL.md` markdown body as a string) and `skill_name` (the resulting skill name/slug, defaults to `skill`). When `skills_text` is set and no files are uploaded, the text is written to a `SKILL.md` and ingested through the same skills pipeline as the file-upload path.

    Both the inline and the file-upload skills paths stage the materialized `SKILL.md` under a **per-dataset staging directory** derived from the dataset id, rather than a fresh temporary directory per request. A skill's id is derived from its dataset, its source directory and its name, so the stable staging location makes ingestion **idempotent by name** (the `skill_name` field on the inline path; the uploaded `SKILL.md`'s parent-folder name on the upload path): re-ingesting the same name into the same dataset updates the existing skill node in place (refreshed content and embedding) instead of adding a duplicate. The same name sent to a *different* dataset is still a distinct skill — that is what lets the same skill be attached to several datasets. Path-based (folder) skill ingestion, where you pass a directory that already contains `SKILL.md`, is unaffected: its source directory was always its own path. The staging directory is removed once ingestion finishes; only its path is stable.

    **`POST /api/v1/remember/entry`** stores a typed memory entry (`qa`, `trace`, `feedback`, or `skill_run`). Session-backed entries (`qa`, `trace`, `feedback`) require `session_id`; `skill_run` is graph-backed and can be recorded without one. It accepts only `entry`, `dataset_name`, `session_id`, and `skill_improvement` — it does **not** accept `node_set`. Applying a skill-improvement proposal happens here, by passing `skill_improvement`.

    Some SDK parameters cannot be sent over HTTP because they take live Python objects rather than JSON values: a custom `chunker` instance and a `graph_model` class (the HTTP endpoint takes only a JSON-serialised graph schema — custom-task-name-to-instance mapping is not implemented over HTTP). The `self_improvement`, `session_ids`, and other power-user keyword options (`preferred_loaders`, `incremental_loading`, `importance_weight`, `vector_db_config`, `graph_db_config`, …) are likewise SDK-only. Use the [Python SDK](/python-api/remember) when you need them.
  </Accordion>

  <Accordion title="Skills and Proposals Endpoints">
    **`POST /api/v1/skills`** ingests a single skill from inline `SKILL.md` markdown using a JSON body (the JSON-native companion to `POST /api/v1/remember` with `content_type=skills`, for no-code clients). The body accepts `skills_text` (required, the `SKILL.md` markdown), `skill_name` (optional, defaults to `skill`), and either `dataset_name` or `dataset_id` (one is required; the dataset is created if needed). It reuses the same skills ingestion pipeline as `remember`, including its idempotency: posting the same `skill_name` to the same dataset again updates that skill rather than creating a second one. Ingestion requires `write` permission on the target dataset.

    **`DELETE /api/v1/skills/{skill_id}`** permanently removes one skill from a dataset. It requires a `dataset_id` query parameter (the dataset the skill is scoped to) and **`delete` permission** on that dataset — a separate grant from the `write` permission ingestion needs and the `read` permission the list and fetch routes need (dataset permissions are independent grants, not an ordered hierarchy). The delete is hard, not a deactivation: it removes the skill's graph node together with its edges and its `Skill_search_text` vector embedding (the embedding cleanup is best-effort — a vector-store failure is logged without failing the request), so the skill cannot be recovered afterwards (re-ingest the `SKILL.md` to bring it back). A soft delete would leave a hidden node behind that a later re-ingest of the same name would silently resurrect, now that skill ids are stable. On success it returns `200` with `{"status": "deleted", "id": ..., "dataset_id": ...}`; `403` when you are not authorized to delete in the dataset, `404` when no skill with that id is scoped to it, and `409` when the deletion itself fails.

    **`GET /api/v1/proposals/{proposal_id}`** returns a single stored skill-improvement proposal for review (read-only — it never mutates the graph). It requires a `dataset_id` query parameter (the dataset the proposal is scoped to; list yours via `GET /api/v1/datasets`). The response includes the proposal's `status` (`proposed` or `applied`), `confidence`, `rationale`, `model_name`, and the before/after procedures (`old_procedure` / `proposed_procedure`). Use it to inspect a proposal before deciding whether to apply it — applying still happens via `POST /api/v1/remember/entry` with `skill_improvement`. Returns `403` when you are not authorized for the dataset and `404` when the proposal is not found.
  </Accordion>
</AccordionGroup>

## Data Deletion

Cognee provides granular control over data deletion through the `datasets` endpoints.

<CodeGroup>
  ```bash List Datasets theme={null}
  # List datasets you can access
  curl "http://localhost:8000/api/v1/datasets" \
    -H "Authorization: Bearer $TOKEN"
  ```

  ```bash List Dataset Data theme={null}
  # List data items in a dataset
  curl "http://localhost:8000/api/v1/datasets/{dataset_id}/data" \
    -H "Authorization: Bearer $TOKEN"
  ```

  ```bash Delete Data Item theme={null}
  # Delete a specific data item from a dataset
  curl -X DELETE "http://localhost:8000/api/v1/datasets/{dataset_id}/data/{data_id}" \
    -H "Authorization: Bearer $TOKEN"
  ```

  ```bash Delete Dataset theme={null}
  # Delete an entire dataset and all its contents
  curl -X DELETE "http://localhost:8000/api/v1/datasets/{dataset_id}" \
    -H "Authorization: Bearer $TOKEN"
  ```

  ```bash Delete All theme={null}
  # Delete all datasets you have delete permission on
  curl -X DELETE "http://localhost:8000/api/v1/datasets" \
    -H "Authorization: Bearer $TOKEN"
  ```
</CodeGroup>

<Note>
  Deletion requires the `delete` permission on the target dataset. See [Permissions](/core-concepts/multi-user-mode/permissions-system/overview) for details.\
  `DELETE /api/v1/delete` is deprecated. Use the `datasets` endpoints above instead.
</Note>

## Quick Example

Here's a complete example using the API:

<CodeGroup>
  ```python Python theme={null}
  import requests

  # Configuration
  BASE_URL = "http://localhost:8000"  # or your per-tenant URL (https://your-tenant.aws.cognee.ai) for Cognee Cloud
  API_KEY = "your-api-key"  # only for Cognee Cloud

  headers = {
      "Content-Type": "application/json",
      "X-Api-Key": API_KEY  # only for Cognee Cloud
  }

  # 1. Add data
  add_response = requests.post(
      f"{BASE_URL}/api/v1/add",
      json={"data": "AI is transforming how we work and live."},
      headers=headers
  )

  # 2. Process into knowledge graph
  cognify_response = requests.post(
      f"{BASE_URL}/api/v1/cognify",
      json={"datasets": ["main_dataset"]},
      headers=headers
  )

  # 3. Search the knowledge graph
  search_response = requests.post(
      f"{BASE_URL}/api/v1/search",
      json={
          "query": "What is AI?",
          "search_type": "GRAPH_COMPLETION"
      },
      headers=headers
  )

  print(search_response.json())
  ```

  ```curl cURL theme={null}
  # 1. Add data
  curl -X POST "http://localhost:8000/api/v1/add" \
    -H "Content-Type: application/json" \
    -d '{"data": "AI is transforming how we work and live."}'

  # 2. Process into knowledge graph
  curl -X POST "http://localhost:8000/api/v1/cognify" \
    -H "Content-Type: application/json" \
    -d '{"datasets": ["main_dataset"]}'

  # 3. Search the knowledge graph
  curl -X POST "http://localhost:8000/api/v1/search" \
    -H "Content-Type: application/json" \
    -d '{
      "query": "What is AI?",
      "search_type": "GRAPH_COMPLETION"
    }'
  ```
</CodeGroup>

## Interactive API Explorer

<Card title="OpenAPI Specification" icon="play">
  **Try the API interactively**

  All endpoints on the left side of the page are automatically generated from our OpenAPI specification, providing interactive examples and real-time testing capabilities.
</Card>

<Tabs>
  <Tab title="Cognee Cloud">
    **Interactive Swagger Endpoint Docs**

    Our endpoints are also documented in Swagger with live testing capabilities. You can access the Swagger docs for Cognee Cloud at:

    ```bash theme={null}
    https://api.aws.cognee.ai/docs
    ```
  </Tab>

  <Tab title="Local Docker">
    **Interactive Swagger Endpoint Docs**

    Our endpoints are also documented in Swagger with live testing capabilities. After you have started your local Cognee instance, you can access the Swagger docs at:

    ```bash theme={null}
    http://localhost:8000/docs
    ```
  </Tab>
</Tabs>

## Error Handling

When a request fails inside Cognee itself — permission denied, exhausted token budget, unmet prerequisites, missing dataset — the response carries that error's own HTTP status code and a single `detail` field holding the error message followed by the error class name:

```json theme={null}
{
  "detail": "<message> [<ErrorName>]"
}
```

Routes still fall back to a generic body for unexpected, non-Cognee errors — `500` with `{"error": "Internal server error", "detail": "..."}` for search, and `409` with `{"error": "..."}` for recall, remember, and improve.

All API endpoints return standard HTTP status codes. Use the troubleshooting notes below when a request does not behave as expected.

<AccordionGroup>
  <Accordion title="400 Bad Request">
    A `400 Bad Request` usually means the request shape is invalid.

    Check the following:

    * **Malformed JSON**: Make sure the request body is valid JSON and that quotes, commas, and braces are correct.
    * **Wrong content type**: JSON requests should include `Content-Type: application/json`.
    * **Missing required fields**: Compare your payload with the endpoint schema in the generated API reference below. In particular, `POST /api/v1/recall` and `POST /api/v1/search` require a `query` string — a body that omits it is rejected with `400` instead of being answered against a default question. Earlier releases declared a default of `"What is in the document?"` on that field, so a `{}` body returned `200`; the placeholder is now only a schema example, and callers must send their own `query`.
    * **Wrong parameter names**: Confirm field names such as `query`, `datasets`, or `search_type` exactly match the documented request body.
  </Accordion>

  <Accordion title="401 Unauthorized">
    A `401 Unauthorized` error means the server did not accept your authentication credentials.

    Check the following:

    * **Wrong auth method**: Cognee Cloud uses `X-Api-Key: YOUR-API-KEY`. Self-hosted instances use `Authorization: Bearer <token>` after `POST /api/v1/auth/login` when authentication is enabled.
    * **Missing or expired token**: If you are running locally with authentication enabled, register a user, log in again, and retry with a fresh Bearer token.
    * **Testing `GET /api/v1/users/me` without auth**: This endpoint is mainly useful when you are explicitly testing authentication. For unauthenticated local development, use other endpoints instead.
    * **Backend access control enabled**: If `ENABLE_BACKEND_ACCESS_CONTROL=true`, authentication is still required even when `REQUIRE_AUTHENTICATION=false`.

    For local auth setup, see [Deploy REST API Server](/guides/deploy-rest-api-server#authentication).
  </Accordion>

  <Accordion title="402 Payment Required">
    A `402 Payment Required` means the LLM token budget for the request is exhausted. The provider (or the LiteLLM proxy enforcing a per-key/per-user spend cap) signalled that no budget remains. Search, recall, remember, and improve surface it with this body:

    ```json theme={null}
    {
      "detail": "LLM provider requires payment or token budget is exhausted. [LLMPaymentRequiredError]"
    }
    ```

    `POST /api/v1/cognify` and the LLM endpoints still return the legacy body `{"error": "Token budget exhausted", "detail": "..."}` — see [Knowledge Processing](/cognee-cloud/functionality/knowledge-processing).

    This status is **terminal** — do the following:

    * **Do not retry**: The request is excluded from automatic retries and re-submitting it will fail the same way until budget is restored.
    * **Top up the budget**: Add token credits (or raise the spend cap) for the LLM provider or LiteLLM proxy, then re-run the request.
    * **Distinguish from 429**: A `429` is transient throttling to back off on, while a `402` requires a budget change before the request can succeed.
  </Accordion>

  <Accordion title="403 Forbidden">
    A `403 Forbidden` means you are authenticated but lack the required permission on the datasets the request touches. Cognee returns it with the standard error body:

    ```json theme={null}
    {
      "detail": "Request owner does not have permission: [read] for any dataset. [PermissionDeniedError]"
    }
    ```

    The bracketed permission type reflects the operation — `read` for search and recall, `write` for remember and improve. A second variant, `Request owner does not have necessary permission: [read] for all datasets requested.`, means at least one dataset you named is not accessible.

    Check the following:

    * **Dataset ownership**: Confirm the dataset exists under your user or tenant, and that it was shared with you if it belongs to someone else.
    * **Named datasets**: When you pass `datasets` or `dataset_ids`, every entry must be accessible — one inaccessible entry fails the whole request.
    * **Not a prerequisites problem**: `POST /api/v1/recall` has always returned `403` for permission failures, but earlier releases dressed it in a misleading `{"error": "Recall prerequisites not met", "hint": "..."}` body suggesting you ingest and cognify first. The `403` now carries the real permission message. (Earlier versions of these docs described recall permission failures as a `200` with an empty list; that behavior never shipped.)
  </Accordion>

  <Accordion title="404 Not Found">
    A `404 Not Found` usually means the route or resource does not exist.

    Check the following:

    * **Wrong path prefix**: Use `/api/v1/...`, not `/api/...`. For example, `/api/users/me` returns a 404, while `/api/v1/users/me` is the correct path.
    * **Wrong HTTP method**: Confirm you are using the method documented for the endpoint, such as `POST` for `/api/v1/search`.
    * **Missing resource**: Dataset IDs, user IDs, or other resource identifiers may be validly formatted but not present in the current environment.
  </Accordion>

  <Accordion title="409 Conflict — ambiguous data id">
    A `409` with `AmbiguousDataIdError` in the `detail` field means you looked up a data item by id **without naming a dataset**, and that id matches documents in several datasets. This only happens to ids issued before the Cognee 1.5.0 [dataset-scoping upgrade](/python-api/run-migrations#dataset-scoping-upgrade): a record that was shared by several datasets was split into one document per dataset, and each split document still answers to the pre-split id.

    The error message lists every candidate as `(dataset, data_id)` pairs. Either repeat the call with a `dataset_id` to pick one, or use the candidate list to migrate your stored id mapping to the per-dataset ids once. An id with a single surviving match resolves directly and never triggers this error.

    (Recall, remember, and improve also return a generic `409` fallback body for unexpected errors — see above.)
  </Accordion>

  <Accordion title="429 Too Many Requests">
    A `429 Too Many Requests` response means you have hit a rate limit.

    Try the following:

    * **Retry with backoff**: Wait briefly before retrying, and increase the delay if the limit persists.
    * **Reduce burst traffic**: Spread out large batches of requests instead of sending them all at once.
    * **Handle retries in code**: Add retry logic so temporary throttling does not break your application flow.
  </Accordion>

  <Accordion title="500 Internal Server Error">
    A `500 Internal Server Error` usually indicates a server-side failure.

    Check the following:

    * **Server logs**: Inspect the API server logs first to find the underlying exception.
    * **Provider configuration**: Verify your LLM, graph database, and vector database settings are valid.
    * **Problem isolation**: Retry with a smaller input or a simpler request to determine whether the issue is data-specific.
    * **Authentication and permissions side effects**: If the error appears only in multi-user mode, verify your auth and permissions configuration.
  </Accordion>
</AccordionGroup>

<Warning>
  Always implement proper error handling in your applications to gracefully handle API failures and rate limits.
</Warning>

## Next Steps

<CardGroup cols={2}>
  <Card title="Explore Endpoints" icon="list">
    **API Documentation**

    Browse all available endpoints with interactive examples below.
  </Card>

  <Card title="Community Support" href="https://discord.gg/m63hxKsp4p" icon="discord">
    **Get Help**

    Join our Discord community for support and discussions.
  </Card>
</CardGroup>
