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

# Parse

`POST /v1/parse` takes one document and returns readable markdown plus a structured JSON representation with layout and page information. No schema, no configuration — use it when you want the document's content, not specific fields out of it.

## How it works

1. You send a **file** — a URL, or the id of a file you already have.
2. CloudRaker fetches the bytes and reads the document: born-digital PDFs directly, scans through OCR, office files through conversion, and audio through transcription.
3. The call **holds until parsing finishes** — up to `?wait=` seconds (60 by default, 120 max). Finished in time gives `200` with download URLs; otherwise `202` with a run id to poll.
4. The run and its files expire on their own (`ttl`, 24 hours by default).

Extraction parses too, so you don't need to call this first — [`POST /v1/extract`](/capabilities/extract) does it as part of the run.

## Quickstart

The sample below uses a blank IRS Form W-9 as a public, stable test document, so the call works with no local files.

```bash title="curl"
curl -X POST https://api.cloudraker.com/v1/parse \
  -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" }
  }'
```

```ts title="TypeScript"
const res = await fetch("https://api.cloudraker.com/v1/parse", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.CLOUDRAKER_API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    file: { url: "https://www.irs.gov/pub/irs-pdf/fw9.pdf", name: "w9.pdf" },
  }),
});

const run = await res.json();
const markdown = run.output?.markdownUrl
  ? await (await fetch(run.output.markdownUrl)).text()
  : undefined;
```

```python title="Python"
import os, requests

res = requests.post(
    "https://api.cloudraker.com/v1/parse",
    headers={"Authorization": f"Bearer {os.environ['CLOUDRAKER_API_KEY']}"},
    json={"file": {"url": "https://www.irs.gov/pub/irs-pdf/fw9.pdf", "name": "w9.pdf"}},
)

run = res.json()
markdown_url = run.get("output", {}).get("markdownUrl")
markdown = requests.get(markdown_url).text if markdown_url else None
```

The TypeScript and Python samples are plain HTTP so they run with nothing installed. This endpoint is also a top-level method on both [SDKs](/developers/sdks) as of 0.3.0 — `client.parse(…)`; that page has a full worked example.

## Example response

```json
{
  "object": "parse_run",
  "id": "par_01KYD1M2XT5Q8VB3NRWY7CDEFG",
  "status": "processed",
  "expiresAt": "2026-07-26T15:57:41.907Z",
  "statusUrl": "/v1/runs/par_01KYD1M2XT5Q8VB3NRWY7CDEFG",
  "files": [
    { "id": "4c9de1b7-8a30-42f5-b0e6-1d7f5c2a9b44", "name": "w9.pdf", "status": "processed" }
  ],
  "file": { "id": "4c9de1b7-8a30-42f5-b0e6-1d7f5c2a9b44", "name": "w9.pdf", "status": "processed" },
  "output": {
    "markdownUrl": "https://cdn.cloudraker.com/acme/4c9de1b7-8a30-42f5-b0e6-1d7f5c2a9b44/processed.md?token=…&fn=w9.pdf",
    "jsonUrl": "https://cdn.cloudraker.com/acme/4c9de1b7-8a30-42f5-b0e6-1d7f5c2a9b44/processed.json?token=…&fn=w9.pdf"
  }
}
```

## Key fields

| Field                | What it is                                                                                        |
| -------------------- | ------------------------------------------------------------------------------------------------- |
| `object`             | Always `parse_run`.                                                                               |
| `id`                 | The run id (`par_…`). Use it with [`GET /v1/runs/:id`](/developers/quickstart#track-a-run).       |
| `status`             | `queued`, `processing`, `processed`, `failed`, `cancelled`, `expired`, or `needs_input`.          |
| `expiresAt`          | When the run and its files are purged. Controlled by `ttl`.                                       |
| `files[]`            | The input file with its own `status` and, on failure, `error`. `file` is an alias for `files[0]`. |
| `output.markdownUrl` | Time-limited download URL for the markdown rendering.                                             |
| `output.jsonUrl`     | Time-limited download URL for the structured JSON — text blocks with page and position.           |

`output` appears only once `status` is `processed`. The download URLs are short-lived; fetch the content rather than storing the URL.

Reuse the returned file id (`files[0].id`) in later calls — pass `{"file": {"id": "<file id>"}}` to [extract](/capabilities/extract) and the document is not fetched or parsed again.

## Configuration

| Field      | Type                                  | What it does                                                                                        |
| ---------- | ------------------------------------- | --------------------------------------------------------------------------------------------------- |
| `file`     | `{url, name?, processing?}` or `{id}` | **Required.** The document to parse.                                                                |
| `metadata` | object                                | Your own key/values, echoed back on the run body (not on webhook deliveries). Max 10 KB serialized. |
| `webhook`  | `{url}` or `{id}`                     | Where to deliver the terminal event instead of polling. See [Webhooks](/developers/webhooks).       |
| `ttl`      | integer seconds, 1–604800             | How long the run and its file live. Default 24 hours, max 7 days.                                   |

`processing` on the file ref picks how the document is read:

| Value                | Use for                                            |
| -------------------- | -------------------------------------------------- |
| `auto`               | Default — picks per document.                      |
| `simple`             | Born-digital PDFs with a real text layer. Fastest. |
| `ocr`                | Scans and photographed pages.                      |
| `transcribe`         | Audio, one speaker or speaker labels not needed.   |
| `transcribe_diarize` | Audio where you need speaker separation.           |

## Sync vs async

Identical to [extract](/capabilities/extract#sync-vs-async): synchronous by default, `?wait=` between `0` and `120` seconds, and a `202` handle instead of a timeout error when the cap is reached.

```json
{
  "object": "parse_run",
  "id": "par_01KYD1M2XT5Q8VB3NRWY7CDEFG",
  "status": "processing",
  "statusUrl": "/v1/runs/par_01KYD1M2XT5Q8VB3NRWY7CDEFG"
}
```

Long audio and large scanned documents will normally come back as `202` — pass `?wait=0` and poll or use a webhook for those.

## Save as an action

Parsing has no configuration to save, so there's nothing to turn into an action — it doesn't appear in `GET /v1/actions/catalog` either. The [saved-configuration path](/capabilities/actions) applies to extract, redact, fill, and sign.

## Next steps

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

Get specific fields as JSON, with a citation behind each one.

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

Register a file, upload the bytes, and reuse it across runs.

#### [Quickstart](/developers/quickstart)

Key, first call, reusing files, and tracking runs.

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

Get told when a run finishes instead of polling.