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

# Templates

A **template** is an organization-level document that you fill in many times. Examples: a W-9, an onboarding packet, a claim form. Templates are persistent and have no TTL. CloudRaker never parses or indexes them. [Fill](/paperwork/capabilities/fill) references a template as `template: { "id": "…" }`.

Templates are a different noun from [files](/paperwork/developers/files) by design. Files are the *inputs* a run reads. A file that a run creates is subject to a TTL. Templates are curated assets that live until you delete them.

## Add a template

There are two shapes, the same as files. Send `url`, or send `name` + `mimeType` for a presigned upload.

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

```bash title="Presigned upload"
# 1. reserve the record
curl -X POST https://api.cloudraker.com/v1/templates \
  -H "Authorization: Bearer $CLOUDRAKER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "name": "claim-form.pdf", "mimeType": "application/pdf" }'

# 2. PUT the bytes to the returned uploadUrl, with the SAME Content-Type
curl -X PUT "<uploadUrl>" \
  -H "Content-Type: application/pdf" \
  --data-binary @./claim-form.pdf
```

```json
{
  "object": "template",
  "id": "23e0a865-0be9-45b1-a491-f1b6bd58a31a",
  "name": "w9-template.pdf",
  "mimeType": "application/pdf",
  "kind": "pdf-form",
  "status": "uploading",
  "createdAt": "2026-07-25T18:01:28.026Z"
}
```

`status` moves from `uploading` to `ready`. CloudRaker does not parse templates, so a template reaches `ready` when the bytes land. This usually takes seconds.

| Field                           | What it is                                                                                                                                               |
| ------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `object`                        | Always `template`.                                                                                                                                       |
| `id`                            | Pass this as `template: { "id": … }`. Ids are opaque strings. Do not parse them.                                                                         |
| `kind`                          | What the template is. `pdf-form` today.                                                                                                                  |
| `status`                        | `uploading`, `processing`, `ready`, or `failed`.                                                                                                         |
| `uploadUrl` / `uploadExpiresAt` | Only on the presigned shape. Valid for 15 minutes. The PUT's `Content-Type` must equal the registered `mimeType` exactly, or storage rejects the upload. |

## Read, list, delete

```bash
# one template — includes a signed downloadUrl (~1 hour)
curl https://api.cloudraker.com/v1/templates/23e0a865-0be9-45b1-a491-f1b6bd58a31a \
  -H "Authorization: Bearer $CLOUDRAKER_API_KEY"

# the library — picker rows, newest first, no download URLs
curl "https://api.cloudraker.com/v1/templates?limit=50" \
  -H "Authorization: Bearer $CLOUDRAKER_API_KEY"

# remove one
curl -X DELETE https://api.cloudraker.com/v1/templates/23e0a865-0be9-45b1-a491-f1b6bd58a31a \
  -H "Authorization: Bearer $CLOUDRAKER_API_KEY"
```

`?limit` caps the page (1–200, default 50). There is no cursor. The list is a single newest-first page. `DELETE` returns `204`.

## Inspect the fields

`POST /v1/templates/:id/inspect` returns the field inventory with page geometry, a values schema, and a content hash. CloudRaker detects fields when the PDF carries no fillable form. It also reads each field's printed caption as its `label`. The first call can be slow. Later calls reuse the result. Templates over 32 MB answer `413 template_too_large`.

Inspect is the configure-time step of [fill](/paperwork/capabilities/fill#configure-a-form-once). Curate the returned `fields` — labels, descriptions, `ignore` flags — and save them with the `templateHash` on a fill config. A fill run never re-inspects the form.

```bash
curl -X POST https://api.cloudraker.com/v1/templates/23e0a865-0be9-45b1-a491-f1b6bd58a31a/inspect \
  -H "Authorization: Bearer $CLOUDRAKER_API_KEY"
```

```jsonc
{
  "fields": [
    {
      "name": "topmostSubform[0].Page1[0].f1_01[0]",
      "type": "text",
      "label": "1 Name of entity/individual. An entry is required.",
      "required": false,
      "page": 0,
      "box": { "x": 58.6, "y": 118.0, "width": 517.4, "height": 14 },
      "ignore": false
    }
    // …22 more on this form
  ],
  "schema": { "type": "object", "properties": { "values": { /* one property per field */ } }, "required": ["values"] },
  "pageBoxes": [{ "width": 611.976, "height": 791.968 }],
  "pageCount": 6,
  "detected": false,
  "templateHash": "9c56cc51b374c3ba189210d5b6d4bf57790d351c96c47c02190ecf1e430635ab"
}
```

| Field                            | What it is                                                                                                                                                         |
| -------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `fields[].name`                  | The PDF's own field name. This is the key `values` takes on `POST /v1/fill`.                                                                                       |
| `fields[].type`                  | `text`, `checkbox`, and the other AcroForm types. Choice fields also carry `options[]`.                                                                            |
| `fields[].label` / `description` | The human caption, read from the form or inferred from the page. `description` starts as the section heading; overwrite it with your own guidance when you curate. |
| `fields[].page` / `box`          | The 0-based page index and the field rectangle **in PDF points**, measured against the matching `pageBoxes` entry.                                                 |
| `fields[].ignore`                | `false` on every inspected field. Set it to `true` when you curate a field no run should touch.                                                                    |
| `schema`                         | A JSON Schema describing the exact `values` object the fields accept.                                                                                              |
| `pageBoxes[]` / `pageCount`      | Page geometry, so you can render the form yourself.                                                                                                                |
| `detected`                       | `false` when the PDF already had form fields. `true` when CloudRaker detected them for you.                                                                        |
| `templateHash`                   | sha256 of the prepared template bytes. Save it with the curated fields to spot a stale curation after the template changes.                                        |

`box` here is in PDF points. Extraction [citations](/paperwork/capabilities/extract#key-fields) differ: their `bbox` is normalized to `0`–`1`.

## Fill from a template

```bash
curl -X POST https://api.cloudraker.com/v1/fill \
  -H "Authorization: Bearer $CLOUDRAKER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "template": { "id": "23e0a865-0be9-45b1-a491-f1b6bd58a31a" },
    "files": [{ "id": "a04d6597-4e34-4a99-94ea-964c289a4c68" }]
  }'
```

Fill also accepts `template: { "url": "…" }` for a one-off form. CloudRaker fetches that copy at run time and does **not** add it to your template library. Use a `url` for a form you will never see again. Use a saved `{id}` for a form you fill weekly.

CloudRaker registers the fetched copy as a file in your API workspace. It shows up in `GET /v1/files` while the run is alive, but it belongs to that run. The run's TTL reclaims it along with the run's other files. `POST /v1/runs/:id/keep` moves it into the space you keep the run into. There is nothing to clean up. A saved template is the opposite: a persistent asset of your library. No run expiry ever deletes it.

## Next steps

#### [Fill](/capabilities/fill)

Fill a template from exact values, or draft them from your documents.

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

The other half: the input documents a run reads.