> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.cloudraker.com/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.cloudraker.com/_mcp/server.

# Quickstart

One `POST` turns a document into JSON with citations. This page gets you there, then shows the two moves you'll need next: not blocking on long documents, and reusing a file you've already sent.

## What you'll need

* A CloudRaker account with the **admin** role in your organization (creating keys is admin-only).
* A terminal with `curl`.

## Get a key

In the CloudRaker web app, open **Admin → API keys** and click **Create API key**. The full key value is shown **once** — copy it and store it somewhere safe. The walkthrough with screenshots is in [API keys](/admin/api-keys).

The plaintext key is returned only once and can never be retrieved again. If you lose it, revoke the key and create a new one.

```bash
export CLOUDRAKER_API_KEY="sk_…"
```

## Extract a document

The call below reads a blank IRS Form W-9 straight from a URL — no upload, no local file, nothing to set up. Replace the URL with your own document when you're ready, or download the fictional sample invoice and [upload it](/developers/files#presigned-upload) to try a business document.

```bash
curl -X POST https://api.cloudraker.com/v1/extract \
  -H "Authorization: Bearer $CLOUDRAKER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "file": { "url": "https://www.irs.gov/pub/irs-pdf/fw9.pdf", "name": "w9.pdf" },
    "schema": {
      "type": "object",
      "properties": {
        "business_name": { "type": ["string", "null"] },
        "tax_classification": { "type": ["string", "null"] }
      }
    }
  }'
```

The response is the finished run. Two things to read:

* **`output.value`** — your data, shaped like your schema.
* **`output.citations`** — for each field, which file, page, and region on the page it came from, so you can show a human the evidence. Page indexes are 0-based and boxes are normalized to the page (`0`–`1`, top-left origin).

```json
{
  "object": "extract_run",
  "id": "exr_01KYD1J8QW2RN4T6VXZ0ABCDEF",
  "status": "processed",
  "expiresAt": "2026-07-26T15:57:41.907Z",
  "statusUrl": "/v1/runs/exr_01KYD1J8QW2RN4T6VXZ0ABCDEF",
  "files": [{ "id": "b88ea8f9-20d4-4704-b379-ddee5a23c678", "name": "w9.pdf", "status": "processed" }],
  "output": {
    "value": { "business_name": null, "tax_classification": "Individual/sole proprietor or single-member LLC" },
    "citations": {
      "tax_classification": [
        { "fileId": "b88ea8f9-20d4-4704-b379-ddee5a23c678", "page": 0, "bbox": { "x": 0.086, "y": 0.379, "width": 0.261, "height": 0.016 }, "text": "Individual/sole proprietor or single-member LLC", "confidence": 5 }
      ]
    },
    "documents": [{ "fileId": "b88ea8f9-20d4-4704-b379-ddee5a23c678", "name": "w9.pdf", "status": "done", "value": { "business_name": null, "tax_classification": "Individual/sole proprietor or single-member LLC" } }]
  }
}
```

`null` means the field wasn't in the document — which is why every field in the schema is declared nullable. That and the other four schema rules are in the [extraction schema dialect](/capabilities/extract/schema).

## Don't block on slow documents

The call above is synchronous: it holds until the run finishes, up to **60 seconds** by default and **120** at most (`?wait=`). When the cap is reached you don't get a timeout error — you get a `202` with a handle to the same run:

```json
{
  "object": "extract_run",
  "id": "exr_01KYD1J8QW2RN4T6VXZ0ABCDEF",
  "status": "processing",
  "statusUrl": "/v1/runs/exr_01KYD1J8QW2RN4T6VXZ0ABCDEF"
}
```

Long audio, hundred-page scans, and large batches will normally land here. If your caller can't hold a request open, ask for the handle up front with `?wait=0`:

```bash
curl -X POST "https://api.cloudraker.com/v1/extract?wait=0" \
  -H "Authorization: Bearer $CLOUDRAKER_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: invoice-4471" \
  -d '{ "file": { "url": "https://www.irs.gov/pub/irs-pdf/fw9.pdf" }, "schema": { "type": "object", "properties": { "business_name": { "type": ["string", "null"] } } } }'
```

Sending an `Idempotency-Key` makes retries safe: a replay returns the original run and an `idempotent-replay: true` response header instead of starting a second one.

## Track a run

```bash
curl "https://api.cloudraker.com/v1/runs/exr_01KYD1J8QW2RN4T6VXZ0ABCDEF?wait=30" \
  -H "Authorization: Bearer $CLOUDRAKER_API_KEY"
```

`GET /v1/runs/:id` returns the same run body as the original call, and takes the same `?wait=` — so you can long-poll rather than hammering it. `status` moves through:

| Status        | Meaning                                                      |
| ------------- | ------------------------------------------------------------ |
| `queued`      | Accepted, not started yet.                                   |
| `processing`  | Reading the document or running the capability.              |
| `processed`   | Finished. `output` is present.                               |
| `failed`      | Terminal failure. Per-file causes are on `files[].error`.    |
| `cancelled`   | You cancelled it.                                            |
| `expired`     | Past its `ttl` — the run and its files are gone.             |
| `needs_input` | Waiting on a human step. Not reachable for extract or parse. |

Runs clean themselves up. `ttl` (seconds, default **24 hours**, max **7 days**) sets when the run and its files are purged; `expiresAt` on the run body tells you when. Cancelling, purging early, downloading a produced file, and keeping a result in the product are all on the [Runs](/developers/runs) page.

Rather than polling at all, point `webhook` at your endpoint and get told when the run reaches a terminal state — see [Webhooks](/developers/webhooks).

## Reuse a file

Every run returns file ids. Pass one back as `{"id": …}` and the document is not fetched or parsed again — the second extraction starts from the parse that already happened, which is both faster and cheaper than sending the URL twice.

```bash
curl -X POST https://api.cloudraker.com/v1/extract \
  -H "Authorization: Bearer $CLOUDRAKER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "file": { "id": "b88ea8f9-20d4-4704-b379-ddee5a23c678" },
    "schema": { "type": "object", "properties": { "requester_name": { "type": ["string", "null"] } } }
  }'
```

The same is true across capabilities: [parse](/capabilities/parse) a document once, then run several narrow extractions against its file id. Send up to 100 files in one run with `files: [...]` instead of `file`.

File ids live as long as the run that created them. A `DELETE` on the run, or its `ttl` elapsing, removes the files too — so reuse them within the window, or set a longer `ttl` on the first call.

## Where to go next

#### [Extract](/capabilities/extract)

Every configuration field — actions, instructions, `unit`, judging, batches.

#### [Redact, fill, sign](/capabilities/redact)

The other capabilities: [redact](/capabilities/redact), [fill](/capabilities/fill), [sign](/capabilities/sign).

#### [Pipelines](/capabilities/pipeline)

Several capabilities over one file set, in a single call.

#### [Saved actions](/capabilities/actions)

Save a configuration once and call it by name.

#### [Files](/developers/files)

Register a document once — by URL or presigned upload — and reuse it.

#### [Runs](/developers/runs)

Statuses, outputs, TTL, and keeping a result in the product.

#### [Webhooks](/developers/webhooks)

Signed events instead of polling, with saved endpoints and a delivery log.

#### [Errors](/developers/errors)

The error envelope, the codes, and which failures are worth retrying.