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

# Run a full ingestion

> Chain convert, split, shape, and extract into one managed job

An ingestion runs the full `convert → split → shape → extract` pipeline as a single managed job and loads the result into a workspace. You get orchestration, retries, and cancellation handling without chaining the tools yourself.

## Prerequisites

* An AiQL API key in the `AIQL_API_KEY` environment variable
* A workspace ID (see [Quickstart](/quickstart) to create one)
* A URL to the file AiQL can reach

## Start the ingestion

Pass the file `url` and the workspace ID in the `AiQL-Workspace` header. Unlike the individual tools, ingestions operate on a workspace.

<CodeGroup>
  ```bash curl theme={null}
  curl -X POST https://api.aiql.io/ingestions \
    -H "Authorization: Bearer $AIQL_API_KEY" \
    -H "AiQL-Workspace: YOUR_WORKSPACE_ID" \
    -H "Content-Type: application/json" \
    -d '{"url": "https://example.com/report.pdf"}'
  ```

  ```python Python theme={null}
  import os
  from aiql import AiQL

  client = AiQL(api_key=os.environ["AIQL_API_KEY"])

  ingestion = client.ingestions.create(
      workspace_id="YOUR_WORKSPACE_ID",
      url="https://example.com/report.pdf",
  )
  print(ingestion.id)
  ```

  ```typescript TypeScript theme={null}
  import { AiQL } from "@aiql.io/sdk";

  const client = new AiQL({ apiKey: process.env.AIQL_API_KEY });

  const ingestion = await client.ingestions.create({
    workspaceId: "YOUR_WORKSPACE_ID",
    url: "https://example.com/report.pdf",
  });
  console.log(ingestion.id);
  ```
</CodeGroup>

## Poll for completion

Ingestions run asynchronously. Poll until the status reports the job is done. See the [status lifecycle](/ingestion-status) for every state an ingestion can report and the transitions between them.

<CodeGroup>
  ```bash curl theme={null}
  curl https://api.aiql.io/ingestions/YOUR_INGESTION_ID \
    -H "Authorization: Bearer $AIQL_API_KEY" \
    -H "AiQL-Workspace: YOUR_WORKSPACE_ID"
  ```

  ```python Python theme={null}
  ingestion = client.ingestions.get(ingestion.id)
  print(ingestion.status)
  ```

  ```typescript TypeScript theme={null}
  const status = await client.ingestions.get(ingestion.id);
  console.log(status.status);
  ```
</CodeGroup>

## Handle interruptions

Cancel a running ingestion, or retry one that failed. A cancelled job is only billed for the steps that finished; a retry only bills for the steps it re-runs.

<CodeGroup>
  ```bash curl theme={null}
  curl -X POST https://api.aiql.io/ingestions/YOUR_INGESTION_ID/cancel \
    -H "Authorization: Bearer $AIQL_API_KEY" \
    -H "AiQL-Workspace: YOUR_WORKSPACE_ID"

  curl -X POST https://api.aiql.io/ingestions/YOUR_INGESTION_ID/retry \
    -H "Authorization: Bearer $AIQL_API_KEY" \
    -H "AiQL-Workspace: YOUR_WORKSPACE_ID"
  ```

  ```python Python theme={null}
  client.ingestions.cancel(ingestion.id)

  client.ingestions.retry(ingestion.id)
  ```

  ```typescript TypeScript theme={null}
  await client.ingestions.cancel(ingestion.id);

  await client.ingestions.retry(ingestion.id);
  ```
</CodeGroup>

## Next step

Once the ingestion finishes, query the data in your workspace. See the [Quickstart](/quickstart#run-a-query) for a query example.

<Note>
  An ingestion is billed as the sum of the steps it runs: `convert` per page, plus `split`, `shape`, and `extract` per 1,000 words. See [Pricing](/pricing) for details.
</Note>
