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

# Ingestion Status

> Check the processing status of ingested documents. 

export const Field = ({name, type, required, recommended}) => {
  const label = required ? 'required' : recommended ? 'recommended' : null;
  const typeLabel = typeof type === 'string' ? type : null;
  const ariaParts = [name, typeLabel && `${typeLabel}`, label].filter(Boolean);
  return <span aria-label={ariaParts.join(', ')} className={label ? 'field-wrap has-field-tip' : 'field-wrap'} style={{
    position: 'relative',
    cursor: label ? 'default' : undefined
  }} tabIndex={label ? 0 : undefined}>
      <span className="field-name-row">
        <code>{name}</code>
        {required && <span className="field-req"> *</span>}
        {recommended && <span className="field-rec"> ●</span>}
      </span>
      {type && <span className="field-type">{type}</span>}
      {label && <span className="field-tip" role="tooltip">
          {label}
        </span>}
    </span>;
};

Since ingestion is asynchronous, use this endpoint to determine when context is ready to be retrieved.

Pass one or more IDs in `ids` to retrieve status. Works for documents, app sources, and memories. When passing multiple IDs on the query string, use either repeated params (`?ids=policy_main&ids=runbook_deploy`) or a single comma-joined value (`?ids=policy_main,runbook_deploy`); both forms are equivalent and can be mixed. Surrounding whitespace is trimmed and empty entries are dropped. For more information, see the [Knowledge](/essentials/v2/knowledge) and [Memories](/essentials/v2/memories) guides.

<Info>
  **Prefer webhooks over polling?** Register a webhook for `indexing.status_changed` events and HydraDB will `POST` to your endpoint when content reaches a terminal state (`completed` or `errored`). See [Webhooks](/essentials/v2/webhooks) for setup and receiver examples.
</Info>

<RequestExample>
  ```python Python SDK theme={"dark"}
  status = client.context.status(
      database="acme_corp",
      collection="team_docs",
      ids=["policy_main", "runbook_deploy"],
  )
  ```

  ```typescript TypeScript SDK theme={"dark"}
  const status = await client.context.status({
    database: "acme_corp",
    collection: "team_docs",
    ids: ["policy_main", "runbook_deploy"],
  });
  ```

  ```bash cURL theme={"dark"}
  curl -G 'https://api.hydradb.com/context/status' \
    -H "Authorization: Bearer <your_api_key>" \
    -H "API-Version: 2" \
    --data-urlencode "database=acme_corp" \
    --data-urlencode "collection=team_docs" \
    --data-urlencode "ids=policy_main,runbook_deploy"
  ```
</RequestExample>

## Query parameters

| Name                                              | Description                                                                                                                                                                                                                                                                                                      |
| ------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| <Field name="ids" type="string[]" required />     | One or more `id` values returned at ingestion. Accepts IDs for documents, app sources, or memories. Pass either repeated params (`ids=a&ids=b`) or a single comma-joined value (`ids=a,b`). Source IDs never contain commas (they are rejected at ingest), so the comma-joined form always splits unambiguously. |
| <Field name="database" type="string" required />  | Database the items belong to. Formerly `tenant_id`; the `tenant_id` alias is still accepted (deprecated).                                                                                                                                                                                                        |
| <Field name="collection" type="string or null" /> | Collection scope. If omitted, the default collection is used. Formerly `sub_tenant_id`; the `sub_tenant_id` alias is still accepted (deprecated). (default=`null`)                                                                                                                                               |

<ResponseExample>
  ```json Success theme={"dark"}
  {
    "success": true,
    "data": {
      "statuses": [
        {
          "id": "policy_main",
          "indexing_status": "completed",
          "error_code": "",
          "success": true,
          "message": "Processing status retrieved successfully"
        },
        {
          "id": "runbook_deploy",
          "indexing_status": "graph_creation",
          "error_code": "",
          "success": true,
          "message": "Processing status retrieved successfully"
        },
        {
          "id": "typo_in_id",
          "indexing_status": "errored",
          "error_code": "FILE_NOT_FOUND",
          "error_message": "ID not found",
          "success": false,
          "message": "Processing status retrieved successfully"
        }
      ]
    },
    "error": null,
    "meta": {
      "request_id": "9d13aef4-02f4-4e73-8c62-4c2601d04f9d",
      "latency_ms": 12.3
    }
  }
  ```

  ```json Failure theme={"dark"}
  {
    "success": false,
    "data": null,
    "error": {
      "code": "DATABASE_NOT_FOUND",
      "message": "Database not found"
    },
    "meta": {
      "request_id": "9d13aef4-02f4-4e73-8c62-4c2601d04f9d",
      "latency_ms": 4.8
    }
  }
  ```
</ResponseExample>

## Status item fields

Each entry in `data.statuses` describes one requested `id`:

| Field             | Type    | Description                                                                                                                                                                  |
| ----------------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `id`              | string  | The source, app-source, or memory ID you asked about (echoed back).                                                                                                          |
| `indexing_status` | string  | One of the [status values](#status-values) below. `errored` is terminal.                                                                                                     |
| `error_code`      | string  | Machine-readable reason an entry is `errored`; **empty string (`""`) when the entry is not errored.** See [`error_code` values](#error-code-values).                         |
| `error_message`   | string  | Human-readable explanation that accompanies a non-empty `error_code`; empty otherwise.                                                                                       |
| `success`         | boolean | `false` when `indexing_status` is `errored`, otherwise `true`. Describes the item, **not** the HTTP request - a `200` response can contain `errored` items.                  |
| `message`         | string  | Status of the *lookup* itself ("Processing status retrieved successfully"). It does **not** describe the ingestion outcome - read `indexing_status` / `error_code` for that. |

### Error code values

`error_code` is the field that lets you tell a **caller mistake** apart from a **real ingestion failure** - a distinction you cannot make from `indexing_status: "errored"` alone. It is empty on any non-errored entry.

| `error_code`               | Meaning                                                                                                                                                 | What to do                                                                                                                                                                                                 |
| -------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `FILE_NOT_FOUND`           | No source with this `id` exists in the given `database`/`collection` - usually a typo or an `id` that was never ingested (or whose status has expired). | Fix the `id`, or (re-)ingest the source. Not a processing failure - retrying the status call will not change it.                                                                                           |
| `INVALID_FILE_ID`          | The `id` was empty or blank.                                                                                                                            | Send a non-empty `id`.                                                                                                                                                                                     |
| *ingestion-pipeline codes* | A genuine processing failure (e.g. `PARSE_FAILED`, `UNSUPPORTED_FORMAT`, `PROCESSING_FAILED`, `EMBEDDING_FAILED`, …).                                   | Act on the specific code - see the [Error Responses reference](/api-reference/v2/error-responses#common-error-codes). Many are re-ingest-and-retry; some are terminal (unsupported format, empty content). |

<Info>
  Branch on `error_code`, not on the text in `message` or `error_message`. `message` describes the lookup, not the ingestion result, and human-readable text may change. The full list of codes an `errored` entry can carry is in the [Error Responses reference](/api-reference/v2/error-responses#common-error-codes).
</Info>

## Status values

```mermaid theme={"dark"}
flowchart LR
    classDef standard fill:#0f172a,stroke:#334155,stroke-width:2px,color:#f8fafc;
    classDef innovation fill:#CC4515,stroke:#FF571A,stroke-width:3px,color:#ffffff,font-weight:bold;
    classDef success fill:#0f172a,stroke:#10b981,stroke-width:2px,color:#f8fafc;
    classDef failure fill:#0f172a,stroke:#ef4444,stroke-width:2px,color:#f8fafc;

    Q([queued])
    P([processing])
    G([graph_creation])
    C([completed])
    E([errored])

    Q --> P
    P --> G
    G --> C
    P -.failure.-> E
    G -.failure.-> E

    class Q,P standard;
    class G innovation;
    class C success;
    class E failure;

    linkStyle default stroke:#64748b,stroke-width:2px;
```

| Status           | Searchable? | Meaning                                                                                                                                        |
| ---------------- | ----------- | ---------------------------------------------------------------------------------------------------------------------------------------------- |
| `queued`         | No          | Accepted by the server, not yet picked up by a worker.                                                                                         |
| `processing`     | No          | Content is being parsed, chunked, and embedded.                                                                                                |
| `graph_creation` | **Yes**     | Indexed and retrievable; the knowledge graph is still being built. Already searchable via `/query`, but graph context may still be incomplete. |
| `completed`      | Yes         | Fully indexed and graphed. Ready for all retrieval modes.                                                                                      |
| `errored`        | No          | Processing failed. Inspect `error_code` and `error_message`.                                                                                   |

The normal progression is `queued` → `processing` → `graph_creation` → `completed`. Treat `errored` as terminal.

## Polling patterns

### Stop when content is searchable

Use this for normal RAG/search flows. `graph_creation` means chunks are indexed and can be retrieved.

<CodeGroup>
  ```python Python theme={"dark"}
  import time

  ids = ["policy_main", "runbook_deploy"]

  while True:
      response = client.context.status(
          database="acme_corp",
          collection="team_docs",
          ids=ids,
      )
      statuses = [s.indexing_status for s in response.data.statuses]

      if all(s in ("graph_creation", "completed") for s in statuses):
          break
      if any(s == "errored" for s in statuses):
          raise RuntimeError("Context processing failed")

      time.sleep(5)
  ```

  ```typescript TypeScript theme={"dark"}
  const ids = ["policy_main", "runbook_deploy"];

  while (true) {
    const response = await client.context.status({
      database: "acme_corp",
      collection: "team_docs",
      ids: ids,
    });

    const statuses = response.data.statuses.map((s) => s.indexingStatus);
    if (statuses.every((s) => s === "graph_creation" || s === "completed")) break;
    if (statuses.some((s) => s === "errored")) throw new Error("Context processing failed");

    await new Promise((r) => setTimeout(r, 5000));
  }
  ```
</CodeGroup>

### Stop when graph processing is complete

Use this before graph-heavy operations such as `/context/relations` or when you require complete `graph_context`.

```python theme={"dark"}
while True:
    response = client.context.status(
        database="acme_corp",
        collection="team_docs",
        ids=["policy_main", "runbook_deploy"],
    )
    statuses = [s.indexing_status for s in response.data.statuses]

    if all(s == "completed" for s in statuses):
        break
    if any(s == "errored" for s in statuses):
        raise RuntimeError("Graph processing failed")

    time.sleep(5)
```

Typical processing time:

* **Memories** (text, markdown, conversation pairs): seconds
* **Small documents** (under 50 pages): 1–5 minutes
* **Large documents** (50+ pages): 5–15 minutes

## Behavior notes

<Info>
  **`graph_creation` is searchable.** Items in this state are already retrievable via `/query`. Wait for `completed` only when you specifically need full graph traversal (`graph_context: true`).
</Info>

* **Unknown IDs return as `errored`:** If you pass an ID that does not exist (e.g., a typo), HydraDB returns an entry with `indexing_status: "errored"` and `error_code: "FILE_NOT_FOUND"` rather than silently dropping it. Use `error_code` to distinguish this from a genuine ingestion failure - see [`error_code` values](#error-code-values).

## Errors

Common codes: `400 INVALID_PARAMETERS`, `404 DATABASE_NOT_FOUND`, `422 VALIDATION_ERROR`. See [Error Responses](/api-reference/v2/error-responses) for the full list.

<div className="api-before-related-resources" />

<Tip>
  **Related Resources**

  * **Before this:** [Ingest Context](/api-reference/v2/endpoint/ingest-context) - to get the IDs
  * **After completion:** [Query](/api-reference/v2/endpoint/query)
  * **After completion:** [Fetch Content](/api-reference/v2/endpoint/fetch-content)
  * **After completion:** [Context Relations](/api-reference/v2/endpoint/source-relations)
  * **Read more:** [Usage → Knowledge](/essentials/v2/knowledge)
  * **Read more:** [Usage → Memories](/essentials/v2/memories)
</Tip>


## OpenAPI

````yaml api-reference/v2/openapi.json GET /context/status
openapi: 3.1.0
info:
  contact:
    email: support@hydradb.com
    name: HydraDB Support
  description: >-
    HydraDB Application API — knowledge ingestion, search, and memory
    management.
  license:
    name: Proprietary
  title: HydraDB Application API
  version: 0.1.0
servers:
  - description: Production server
    url: https://api.hydradb.com
security: []
externalDocs:
  description: ''
  url: ''
paths:
  /context/status:
    get:
      tags:
        - context
      summary: Check processing status
      description: Return the processing status for one or more source IDs.
      parameters:
        - description: Single source ID
          in: query
          name: id
          schema:
            example: HydraDoc1234
            type: string
        - description: One or more source IDs
          in: query
          name: ids
          schema:
            example:
              - HydraDoc1234
              - HydraDoc4567
            items:
              type: string
            type: array
        - description: Database (canonical name for the tenant scope)
          in: query
          name: database
          required: true
          schema:
            example: acme_corp
            type: string
        - description: Collection (canonical name for the sub-tenant scope)
          in: query
          name: collection
          schema:
            example: team_docs
            type: string
        - description: Deprecated alias for database
          in: query
          name: tenant_id
          schema:
            deprecated: true
            example: tenant_1234
            type: string
            x-deprecated: 'true'
        - description: Deprecated alias for collection
          in: query
          name: sub_tenant_id
          schema:
            deprecated: true
            example: sub_tenant_4567
            type: string
            x-deprecated: 'true'
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/handler.Envelope-ingestion_V2BatchProcessingStatus
          description: OK
        '400':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/handler.ErrorResponse'
          description: Bad Request
      security:
        - BearerAuth: []
components:
  schemas:
    handler.Envelope-ingestion_V2BatchProcessingStatus:
      properties:
        data:
          $ref: '#/components/schemas/ingestion.V2BatchProcessingStatus'
          example:
            statuses:
              - error_code: ''
                error_message: ''
                id: HydraDoc1234
                indexing_status: completed
                message: Source processed successfully.
                success: true
        error:
          $ref: '#/components/schemas/handler.apiError'
          description: Error message, empty string on success.
          example:
            code: DATABASE_NOT_FOUND
            message: Database not found
        meta:
          $ref: '#/components/schemas/handler.responseMeta'
          example:
            collection: team_docs
            database: acme_corp
            latency_ms: 12.3
            request_id: 9d13aef4-02f4-4e73-8c62-4c2601d04f9d
            source_type: file
            sub_tenant_id: sub_tenant_4567
            tenant_id: tenant_1234
        success:
          description: Whether the request succeeded.
          example: true
          type: boolean
      type: object
    handler.ErrorResponse:
      properties:
        detail:
          $ref: '#/components/schemas/handler.ErrorDetail'
          description: Structured error detail with code, message, and deprecation hints.
          example:
            deprecated: true
            deprecated_field: tenant_id
            error_code: VALIDATION_ERROR
            message: Request validation failed
            preferred_field: database
            success: true
      type: object
    ingestion.V2BatchProcessingStatus:
      properties:
        statuses:
          description: Per-source indexing status results.
          example:
            - error_code: ''
              error_message: ''
              id: HydraDoc1234
              indexing_status: completed
              message: Source processed successfully.
              success: true
          items:
            $ref: '#/components/schemas/ingestion.V2ProcessingStatus'
          type: array
          uniqueItems: false
      type: object
    handler.apiError:
      properties:
        code:
          description: Machine-readable error code (e.g. `DATABASE_NOT_FOUND`).
          example: DATABASE_NOT_FOUND
          type: string
        message:
          description: Human-readable description of the error.
          example: Database not found
          type: string
      type: object
    handler.responseMeta:
      properties:
        collection:
          description: >-
            Collection scope. Defaults to the default collection when omitted.
            Formerly `sub_tenant_id`; the `sub_tenant_id` alias is still
            accepted (deprecated).
          example: team_docs
          type: string
        database:
          description: >-
            Owning database. Formerly `tenant_id`; the `tenant_id` alias is
            still accepted (deprecated).
          example: acme_corp
          type: string
        deprecation:
          description: >-
            Deprecation lists any migration nudges that apply to this request —
            the

            caller used a legacy /tenants route, a legacy
            tenant_id/sub_tenant_id field,

            or the deprecated sub_tenant_ids selector. It is a non-breaking
            signal (the

            status code is unchanged); omitempty keeps it absent for
            fully-migrated

            requests. A list so independent deprecations coexist without
            clobbering.
          items:
            $ref: '#/components/schemas/handler.deprecationNotice'
          type: array
          uniqueItems: false
        latency_ms:
          description: Server-side processing time in milliseconds.
          example: 12.3
          type: number
        request_id:
          description: Unique identifier for this request, useful for support and tracing.
          example: 9d13aef4-02f4-4e73-8c62-4c2601d04f9d
          type: string
        source_type:
          description: Type of the parent source (e.g. `file`, `slack`, `notion`).
          example: file
          type: string
        sub_tenant_id:
          deprecated: true
          example: sub_tenant_4567
          type: string
          x-deprecated: 'true'
        tenant_id:
          deprecated: true
          example: tenant_1234
          type: string
          x-deprecated: 'true'
      type: object
    handler.ErrorDetail:
      properties:
        deprecated:
          description: Whether this response concerns a deprecated field or route.
          example: true
          type: boolean
        deprecated_field:
          description: The deprecated field name.
          example: tenant_id
          type: string
        error_code:
          description: Machine-readable error classification code.
          example: VALIDATION_ERROR
          type: string
        message:
          description: Human-readable description of the error.
          example: Request validation failed
          type: string
        preferred_field:
          description: The canonical replacement for the deprecated field.
          example: database
          type: string
        success:
          description: Always false for error responses.
          example: true
          type: boolean
      type: object
    ingestion.V2ProcessingStatus:
      properties:
        error_code:
          description: >-
            Machine-readable code for the indexing failure, empty string on
            success.
          example: ''
          type: string
        error_message:
          description: >-
            Human-readable description of the indexing failure, empty string on
            success.
          example: ''
          type: string
        id:
          description: Unique identifier for this resource.
          example: HydraDoc1234
          type: string
        indexing_status:
          description: >-
            Current processing state: `queued`, `processing`, `completed`, or
            `failed`.
          example: completed
          type: string
        message:
          description: Human-readable status description.
          example: Source processed successfully.
          type: string
        success:
          description: Whether the request succeeded.
          example: true
          type: boolean
      type: object
    handler.deprecationNotice:
      properties:
        deprecated:
          description: Whether this response concerns a deprecated field or route.
          example: true
          type: boolean
        deprecated_field:
          description: The deprecated field name.
          example: tenant_id
          type: string
        deprecated_since:
          description: API version when the field was deprecated.
          example: 2.0.1
          type: string
        message:
          description: Migration guidance message.
          example: tenant_id is deprecated; use database instead.
          type: string
        preferred_field:
          description: The canonical replacement for the deprecated field.
          example: database
          type: string
      type: object
  securitySchemes:
    BearerAuth:
      bearerFormat: API key
      description: 'API key sent as a Bearer token: "Bearer prefix.secret"'
      scheme: bearer
      type: http

````