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

# Files

`/v1/files` is the reusable document corpus behind the [capability endpoints](/capabilities/extract). Register a file once and every later run takes `{"file": {"id": "…"}}`: the document is not fetched again and not parsed again.

## Files you register vs files a run creates

Both kinds are files and both are addressed by id, but they live by different rules:

|            | Registered with `POST /v1/files`               | Created inline by a run                                     |
| ---------- | ---------------------------------------------- | ----------------------------------------------------------- |
| Created by | You                                            | `{"file": {"url": …}}` on a verb, or a run's output         |
| Lifetime   | **Persistent** — until you `DELETE` it         | Expires with the run's `ttl` (default 24 hours, max 7 days) |
| Reuse      | Across any number of runs                      | Only while the run that created it lives                    |
| Best for   | Documents you'll run several capabilities over | One-shot processing                                         |

A run that creates a file inline still returns its id, so the parse is reusable inside that run's TTL — but if you plan to keep working with the document, register it first. Extending the lifetime of a run's files after the fact is what [`keep`](/developers/runs#keep-a-run) is for.

## Register by URL

The production-default path: we fetch the bytes server-side over http(s).

```bash
curl -X POST https://api.cloudraker.com/v1/files \
  -H "Authorization: Bearer $CLOUDRAKER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://www.irs.gov/pub/irs-pdf/fw9.pdf",
    "name": "w9.pdf",
    "processing": "auto"
  }'
```

```json
{
  "object": "file",
  "id": "a04d6597-4e34-4a99-94ea-964c289a4c68",
  "name": "w9.pdf",
  "mimeType": "application/pdf",
  "status": "uploading",
  "createdAt": "2026-07-25T18:00:39.453Z"
}
```

With a `url` the MIME type is sniffed from the response, so any `mimeType` you send alongside it is dropped rather than honored. Send `url` **or** `name` + `mimeType`, never a mix you expect to be respected.

**Sources must serve a `Content-Length`.** The fetch streams straight into storage, so an origin that answers with chunked transfer encoding or compressed content and no usable length fails with `502 file_upload_failed`. Static file hosts are fine; HTML pages and gzip-encoded endpoints often are not. Upload those with a presigned PUT instead.

## Presigned upload

For local files, large files, and anything not reachable by URL. No multipart, pure JSON.

#### Reserve the record

```bash
curl -X POST https://api.cloudraker.com/v1/files \
  -H "Authorization: Bearer $CLOUDRAKER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "name": "recording.mp3", "mimeType": "audio/mpeg", "processing": "transcribe_diarize" }'
```

The response carries `uploadUrl` and `uploadExpiresAt` — **15 minutes**.

#### PUT the bytes

```bash
curl -X PUT "<uploadUrl>" \
  -H "Content-Type: audio/mpeg" \
  --data-binary @./recording.mp3
```

The `Content-Type` header must equal the `mimeType` you registered **exactly** — storage signs it into the URL and rejects a mismatch. This is the single most common upload failure.

#### Poll until ready

`GET /v1/files/:id` until `status` is `ready`, then read `urls`.

## Read a file

```bash
curl https://api.cloudraker.com/v1/files/a04d6597-4e34-4a99-94ea-964c289a4c68 \
  -H "Authorization: Bearer $CLOUDRAKER_API_KEY"
```

```json
{
  "object": "file",
  "id": "a04d6597-4e34-4a99-94ea-964c289a4c68",
  "name": "w9.pdf",
  "mimeType": "application/pdf",
  "status": "ready",
  "createdAt": "2026-07-25T18:00:39.453Z",
  "urls": {
    "content": "https://cdn.cloudraker.com/…/latest?token=…&fn=w9.pdf",
    "markdown": "https://cdn.cloudraker.com/…/processed.md?token=…&fn=w9.pdf",
    "json": "https://cdn.cloudraker.com/…/processed.json?token=…&fn=w9.pdf"
  }
}
```

| `status`     | Meaning                                   |
| ------------ | ----------------------------------------- |
| `uploading`  | Registered; the bytes haven't landed yet. |
| `processing` | Bytes stored, being read.                 |
| `ready`      | Done. `urls` is present.                  |
| `failed`     | See `error`.                              |

`urls.content` is the original bytes; `urls.markdown` and `urls.json` are the parse byproducts and appear only once the document was parsed. All three are signed and short-lived (\~1 hour) — fetch the content, don't store the URL.

## List and delete

```bash
curl "https://api.cloudraker.com/v1/files?limit=50" \
  -H "Authorization: Bearer $CLOUDRAKER_API_KEY"

curl -X DELETE https://api.cloudraker.com/v1/files/a04d6597-4e34-4a99-94ea-964c289a4c68 \
  -H "Authorization: Bearer $CLOUDRAKER_API_KEY"
```

`?limit` caps the page (1–200, default 50), newest first. There is no cursor today — paging is by `limit` only. `DELETE` returns `204` and removes the parse byproducts with the file; runs that already used it keep their results.

## Processing

`processing` picks how the document is read. It applies when the file is registered and again in `file.processing` on any capability call.

| Value                | Use for                                                                       |
| -------------------- | ----------------------------------------------------------------------------- |
| `auto`               | Default for documents — picks per document and self-upgrades to OCR on scans. |
| `simple`             | Born-digital PDFs with a real text layer. Fastest.                            |
| `ocr`                | Scans and photographed pages.                                                 |
| `transcribe`         | Audio where speaker separation doesn't matter.                                |
| `transcribe_diarize` | Default for audio and video — separates speakers.                             |

Parsing is automatic: a capability parses whatever isn't parsed and never re-parses what is. Calling [parse](/capabilities/parse) first is optional, not a prerequisite.

## Reuse a file

```bash
curl -X POST https://api.cloudraker.com/v1/extract \
  -H "Authorization: Bearer $CLOUDRAKER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "file": { "id": "a04d6597-4e34-4a99-94ea-964c289a4c68" },
    "schema": { "type": "object", "properties": { "business_name": { "type": ["string", "null"] } } }
  }'
```

Parse once, run many: several narrow extractions, a redaction, and a fill can all read the same file id without re-reading the document. Send up to 100 file refs in one run with `files: [...]`.

## Next steps

#### [Templates](/capabilities/templates)

The other resource: blank forms your organization fills repeatedly.

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

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

#### [Files in spaces](/developers/files-and-uploads)

The product-side file surface, scoped to a space and indexed for search.

#### [Parse](/capabilities/parse)

Markdown and structured JSON out of any document.