> 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 you fill in over and over — a W-9, an onboarding packet, a claim form. Templates are persistent (no TTL), never parsed or indexed, and are referenced by [fill](/capabilities/fill) as `template: { "id": "…" }`.

Templates are deliberately a different noun from [files](/developers/files): files are the *inputs* a run reads and are subject to a TTL when a run creates them; templates are curated assets that live until you delete them.

## Add a template

Two shapes, same as files — send `url`, or `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 `uploading` → `ready`. Templates are not parsed, so they reach `ready` as soon as the bytes land — usually seconds.

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

## 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. Fields are detected when the PDF carries no fillable form. The first call can be slow; later calls reuse the result.

```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,
      "order": 0,
      "box": { "x": 58.6, "y": 118.0, "w": 517.4, "h": 14 },
      "multiline": false
    }
    // …22 more on this form
  ],
  "pageBoxes": [{ "width": 611.976, "height": 791.968 }],
  "pageCount": 6,
  "detected": false
}
```

| Field                       | What it is                                                                                                     |
| --------------------------- | -------------------------------------------------------------------------------------------------------------- |
| `fields[].name`             | The PDF's own field name — the key you send in `POST /v1/runs/:id/task` values.                                |
| `fields[].type`             | `text`, `checkbox`, and the other AcroForm types.                                                              |
| `fields[].page` / `box`     | 0-based page index and the field rectangle **in PDF points**, measured against the matching `pageBoxes` entry. |
| `pageBoxes[]` / `pageCount` | Page geometry, so you can render the form yourself.                                                            |
| `detected`                  | `false` when the PDF already had form fields; `true` when they were detected for you.                          |

`box` here is in PDF points, unlike extraction [citations](/capabilities/extract#key-fields), whose `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. That copy is fetched at run time and is **not** added to your template library — use it for a form you'll never see again, and a saved `{id}` for one you fill weekly.

The fetched copy is registered as a file in your API workspace and 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, and `POST /v1/runs/:id/keep` moves it into the space you keep the run into. Nothing to clean up. A saved template is the opposite — a persistent asset of your library that no run expiry ever deletes.

## Next steps

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

Draft a template's values from your documents, with optional review.

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

The other half: the input documents a run reads.