> ## 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.

# Search & Recall

> Endpoints for querying knowledge graphs and retrieving data

These endpoints query your knowledge graphs. For the full parameter reference, see [Search Basics](/guides/search-basics).

## Recall

**`POST /api/v1/recall`** — Retrieve information from the knowledge graph.

Auto-routes the query to the best retrieval strategy. This is the primary search endpoint.

```bash theme={null}
curl -X POST https://your-tenant.aws.cognee.ai/api/v1/recall \
  -H "X-Api-Key: your-key" \
  -H "Content-Type: application/json" \
  -d '{"query": "What entities are in my data?"}'
```

`query` is a **required** body field: a request that omits it is rejected with `400` and a `detail` array naming the missing field, rather than being answered — see [Requests without a `query`](#requests-without-a-query) for the error shape and the history of the removed default.

The request body accepts an `include_references` boolean (default `true`). When enabled, completion-style answers get a deterministic `Evidence:` block appended to the answer text, citing the source chunks or graph context. The response schema is unchanged. Set `include_references` to `false` to restore the exact prior answer text.

```bash theme={null}
curl -X POST https://your-tenant.aws.cognee.ai/api/v1/recall \
  -H "X-Api-Key: your-key" \
  -H "Content-Type: application/json" \
  -d '{"query": "What entities are in my data?", "include_references": false}'
```

**`GET /api/v1/recall`** — Retrieve recall history for the authenticated user.

### Recall and search history

Recall records the questions it answers. A `POST /api/v1/recall` that runs graph retrieval writes its question and answer into the same history that `POST /api/v1/search` uses, so recall traffic — including questions from agents and the [Search UI](/cognee-cloud/ui/search), which both call recall — appears in both `GET /api/v1/recall` and `GET /api/v1/search`.

What a recall records:

* **The search type that ran.** If you omit `search_type`, recall auto-routes the question, and the history row stores the type the router chose, such as `GRAPH_COMPLETION`.
* **One question-and-answer entry per dataset that answered.** A recall spanning several datasets records a separate pair for each, attributed to that dataset, rather than one combined entry. Recalls whose results carry no dataset — which is what happens when [access control](/cognee-cloud/functionality/permissions-and-access-control) is disabled — are recorded without dataset attribution.
* **Unanswered questions too.** A recall that matched nothing still records one entry, unattributed, with empty answer text.

History is written after retrieval finishes, so the recorded search type and dataset reflect what actually ran. The write is not best-effort: if it fails, the request fails rather than returning an answer that was never recorded. Set `COGNEE_LOG_SEARCH_HISTORY` to `false` to stop recording history altogether.

### Recall prerequisites

Recall reads from an existing knowledge graph — it does not create one. Before recall (or search) returns anything, the dataset must already be ingested **and** processed:

1. [`POST /api/v1/remember`](/cognee-cloud/functionality/data-ingestion#remember), **or**
2. [`POST /api/v1/add`](/cognee-cloud/functionality/data-ingestion#add) followed by [`POST /api/v1/cognify`](/cognee-cloud/functionality/knowledge-processing#cognify).

If you recall before the graph exists, the endpoint returns:

| Status | Body                                                                                                                                               | Meaning                                                                                                                                                                                                                                                                                                                                                                                                                                                |
| ------ | -------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `422`  | `{"detail": "Recall prerequisites not met: no database/default user found. Initialize Cognee before recalling by: ... [RecallPreconditionError]"}` | No graph has been built yet for this user/dataset — ingest and cognify first. The `detail` string carries the full remediation steps.                                                                                                                                                                                                                                                                                                                  |
| `402`  | `{"detail": "LLM provider requires payment or token budget is exhausted. [LLMPaymentRequiredError]"}`                                              | The configured LLM provider (or LiteLLM proxy) reported that its token budget is exhausted. Handle 402 by surfacing a top-up / billing flow rather than retrying.                                                                                                                                                                                                                                                                                      |
| `403`  | `{"detail": "Request owner does not have necessary permission: [read] for all datasets requested. [PermissionDeniedError]"}`                       | At least one dataset you named is not readable by you. When no dataset is named and you can read none at all, the message reads `Request owner does not have permission: [read] for any dataset.` instead.                                                                                                                                                                                                                                             |
| `409`  | `{"error": "An error occurred during recall."}`                                                                                                    | An unexpected, non-Cognee error interrupted the request server-side.                                                                                                                                                                                                                                                                                                                                                                                   |
| `422`  | `{"detail": "response_schema: unsupported JSON Schema keyword: allOf [CogneeValidationError]"}`                                                    | The supplied [`response_schema`](#structured-output-with-response_schema) falls outside the supported subset, or exceeds the depth/property budgets. Every message from this path is prefixed with `response_schema:` — for example `recursive reference '#/$defs/Node'`, `nesting deeper than 10 levels`, or `more than 200 properties in total`. The schema is rebuilt before retrieval starts, so a rejected schema costs no retrieval or LLM work. |

<Note>
  Errors raised inside Cognee reach the caller with their own status code and a single `detail` field of the form `"<message> [<ErrorName>]"` — see [Error Handling](/api-reference/introduction#error-handling).
</Note>

### Structured output with `response_schema`

The request body accepts an optional `response_schema` object: a JSON Schema describing the shape you want the completion to conform to, typically produced client-side with `MyModel.model_json_schema()`. The server rebuilds a Pydantic model from it and validates the completion against that model, so each result carries the validated payload in its `structured` field. Only completion-style search types support it.

```python theme={null}
from pydantic import BaseModel

class NLPFacts(BaseModel):
    field_name: str
    parent_disciplines: list[str]

NLPFacts.model_json_schema()
# {'properties': {'field_name': {'title': 'Field Name', 'type': 'string'},
#                 'parent_disciplines': {'items': {'type': 'string'}, ...}},
#  'required': ['field_name', 'parent_disciplines'],
#  'title': 'NLPFacts', 'type': 'object'}
```

```bash theme={null}
curl -X POST https://your-tenant.aws.cognee.ai/api/v1/recall \
  -H "X-Api-Key: your-key" \
  -H "Content-Type: application/json" \
  -d '{
        "query": "What is NLP and which disciplines does it belong to?",
        "response_schema": {
          "type": "object",
          "title": "NLPFacts",
          "properties": {
            "field_name": {"type": "string"},
            "parent_disciplines": {"type": "array", "items": {"type": "string"}}
          },
          "required": ["field_name", "parent_disciplines"]
        }
      }'
```

The Python SDK sends this field for you: when [`recall(response_model=...)`](/python-api/recall#structured-output-with-response_model) runs against a remote server, the client forwards `response_model.model_json_schema()` as `response_schema`.

#### Supported schema subset

The server accepts only the structural subset that Pydantic itself emits:

| Supported                                                          | Rejected with `422`                                           |
| ------------------------------------------------------------------ | ------------------------------------------------------------- |
| Root `"type": "object"` with non-empty `properties`                | Any other root type, or an object with no declared properties |
| Primitives: `string`, `integer`, `number`, `boolean`, `null`       | Missing or unrecognized `type` on a node                      |
| `array` with an `items` schema                                     | `array` without `items`                                       |
| `enum` of non-empty strings, integers, or booleans                 | Empty enums or enums of other value types                     |
| `anyOf` unions and optionals, and list-valued `type`               | `allOf`, `oneOf`, `not`, `patternProperties`                  |
| Nested objects via `#/$defs/...` or `#/definitions/...` references | Recursive, unresolvable, or otherwise-prefixed `$ref` values  |

Two budgets guard the service against abusive schemas: nesting may not exceed **10 levels**, and the schema may not declare more than **200 properties in total**.

<Warning>
  Value constraints such as `minLength`, `minimum`, or `pattern` are **not** enforced server-side, and Python-side custom validators do not travel with the schema — only the structure is reconstructed. To run your full validation logic, rehydrate the result against your own class on the client: `NLPFacts.model_validate(result["structured"])`.
</Warning>

## Search

**`POST /api/v1/search`** — Search for nodes in the graph database.

Provides direct control over the retrieval strategy. Accepts a `search_type` parameter to select a specific search mode.

```bash theme={null}
curl -X POST https://your-tenant.aws.cognee.ai/api/v1/search \
  -H "X-Api-Key: your-key" \
  -H "Content-Type: application/json" \
  -d '{
    "query": "What did Einstein develop?",
    "search_type": "GRAPH_COMPLETION",
    "datasets": ["physics_data"]
  }'
```

Available search types are documented in [Search Types](/core-concepts/main-operations/legacy-operations/search).

The request body also accepts an `include_references` boolean (default `true`), which behaves the same as on `POST /api/v1/recall`: it appends an `Evidence:` block to completion-style answer text. Set it to `false` to disable.

`query` is **required** here as well, on the same terms as on `POST /api/v1/recall` — see [Requests without a `query`](#requests-without-a-query).

**`GET /api/v1/search`** — Retrieve search history for the authenticated user.

Searches are recorded per dataset. A `POST /api/v1/search` spanning several datasets records one question-and-answer entry for each dataset that answered, rather than a single combined entry, so history grows in proportion to the datasets a search touches. See [Recall and search history](#recall-and-search-history) for the full recording rules, which are shared by both endpoints.

### Requests without a `query`

`query` is a required body field on both `POST /api/v1/recall` and `POST /api/v1/search`. A body that omits it fails request validation before any retrieval runs, and Cognee returns `400` — not the `422` that FastAPI emits by default — with the validation errors in `detail`:

```json theme={null}
{
  "detail": [
    {
      "type": "missing",
      "loc": ["body", "query"],
      "msg": "Field required",
      "input": {}
    }
  ],
  "body": {}
}
```

The fix is to send an explicit `query` string. This matters most for integrations written against earlier releases, where both endpoints declared `query` with a default of `"What is in the document?"`: a `{}` body returned `200` with an answer to that placeholder question, searched across every dataset the caller could read. Those calls now fail loudly instead of returning an answer to a question nobody asked. Requests that already pass a real `query` — including every example on this page — are unaffected.

The placeholder string is still the schema example for the field, so the interactive reference and Swagger "Try it out" keep prefilling it in the request body. It is an example you can edit or replace, not a value the server substitutes when you leave `query` out.

The Python SDK is unaffected: [`recall()`](/python-api/recall) and `search()` already take the query as a required positional argument.

## Visualize

**`GET /api/v1/visualize`** — Generate an HTML visualization of a dataset's knowledge graph.

Requires a `dataset_id` query parameter (UUID). Returns a self-contained HTML page with an interactive graph.

```bash theme={null}
curl "https://your-tenant.aws.cognee.ai/api/v1/visualize?dataset_id=<uuid>" \
  -H "X-Api-Key: your-key"
```

See also the [Knowledge Graph UI](/cognee-cloud/ui/knowledge-graph) for the built-in visualization.

**`POST /api/v1/visualize/multi`** — Generate a combined visualization from multiple users' datasets.

<Info>
  `recall` is recommended for most use cases. Use `search` when you need to specify a particular retrieval strategy.
</Info>
