> ## Documentation Index
> Fetch the complete documentation index at: https://docs.craftkit.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Render a template

> POST /v1/templates/:slug/render — validate data against the manifest and enqueue an async render.

<Info>**POST** `https://api.craftkit.dev/v1/templates/:slug/render`</Info>

Validates `data` against the template's published manifest and enqueues a render job. Returns
`202` with a poll URL. Rendering is **asynchronous** — there is no synchronous mode (see
[Render lifecycle](/guides/render-lifecycle)).

## Authorization

<ParamField header="Authorization" type="string" required>
  `Bearer ck_live_…` — a project API key.
</ParamField>

<ParamField header="Idempotency-Key" type="string">
  Optional. Retrying with the same key returns the original render instead of creating a duplicate.
  Takes precedence over the body `jobId`. See [Idempotency](/guides/idempotency).
</ParamField>

## Path parameters

<ParamField path="slug" type="string" required>The template slug.</ParamField>

## Body

<ParamField body="data" type="object" required>
  Variable values. Scalars nest by dot-path (`{ "customer": { "name": "…" } }`); loops are keyed
  by their dot-free top-level key. Keys absent from the manifest are **stripped**. Loop arrays are
  capped at 10,000 items. See [Variables & loops](/guides/variables-and-loops).
</ParamField>

<ParamField body="jobId" type="string">
  Optional idempotency key (fallback when no `Idempotency-Key` header is sent).
</ParamField>

<ParamField body="options" type="object">
  <Expandable title="options">
    <ParamField body="sync" type="boolean" default="false">
      Accepted by the schema but **not honored** — every render is async. Poll the result.
    </ParamField>

    <ParamField body="versionNumber" type="number">Pin to a specific published version. Defaults to current.</ParamField>
    <ParamField body="filename" type="string">Override the asset filename (max 120 chars).</ParamField>
  </Expandable>
</ParamField>

## Response

`202` when a new render is queued, or `200` when an idempotency key matched an existing render.

<ResponseField name="id" type="string" />

<ResponseField name="status" type="string">`queued` for a fresh render; the existing render's current status on an idempotent replay.</ResponseField>
<ResponseField name="pollUrl" type="string">`GET` this to poll the render.</ResponseField>
<ResponseField name="downloadUrl" type="string | null">`null` until the render succeeds.</ResponseField>

<ResponseField name="errorMessage" type="string | null" />

<ResponseField name="createdAt" type="string" />

## Errors

| Status | code                   | Meaning                                                |
| ------ | ---------------------- | ------------------------------------------------------ |
| 400    | `invalid_json`         | Body is not valid JSON.                                |
| 400    | `invalid_request`      | Body failed schema validation (`issues` included).     |
| 400    | `invalid_input_data`   | `data` did not match the manifest (`issues` included). |
| 401    | `unauthorized`         | Missing/invalid/revoked key.                           |
| 404    | `template_not_found`   | No such template in this key's project.                |
| 404    | `version_not_found`    | Pinned `versionNumber` does not exist.                 |
| 409    | `no_published_version` | Template has no published version.                     |
| 503    | `queue_unavailable`    | Render queue is temporarily unreachable — retry.       |

```bash cURL theme={null}
curl -X POST https://api.craftkit.dev/v1/templates/charter-handover/render \
  -H "Authorization: Bearer $CRAFTKIT_API_KEY" \
  -H "Idempotency-Key: handover-BK-12345-checkout" \
  -H "Content-Type: application/json" \
  -d '{
    "data": {
      "booking": { "code": "BK-12345" },
      "handover": { "kind": "checkout", "date": "2026-06-04", "signedBy": "Jane Doe" },
      "areas": [ { "areaKey": "hull", "condition": "damage" } ]
    },
    "options": { "filename": "charter-handover-BK-12345.pdf" }
  }'
```

```json 202 theme={null}
{
  "id": "…",
  "status": "queued",
  "pollUrl": "https://api.craftkit.dev/v1/renders/…",
  "downloadUrl": null,
  "errorMessage": null,
  "createdAt": "2026-06-05T10:00:00.000Z"
}
```
