Skip to main content
PUT https://api.craftkit.dev/v1/templates/{slug}
Create-or-republish the template at slug — the idempotent companion to POST /v1/templates. It re-runs the same manifest → layout synthesis as create, so a template authored before a layout feature shipped (for example image blocks) can be regenerated in place instead of orphaning its slug to a -v2.
  • Template does not exist → it is created and published as version 1 → 201.
  • Template exists → a new version (n+1) is published and becomes current → 200.
Use it from a provisioning script to make template setup idempotent across environments: the first run creates, every subsequent run republishes.
Existing renders are never affected. Each render pins its own templateVersionId, so republishing only changes what new renders use — previously rendered PDFs are immutable.

Authorization

Authorization
string
required
Bearer ck_live_… — must own the project that holds (or will hold) the template.

Path

slug
string
required
The canonical kebab-case slug. The URL slug wins — any slug in the body is ignored.

Body

The body is the same shape as create (minus slug, which comes from the URL).
name
string
required
Display name (1–120 chars). Replaces the stored name on republish.
description
string
Optional, up to 280 chars. Replaces the stored description on republish.
manifest
object
required
The variable manifest the render payload binds to.
layout
object
Optional CanvasDocument contentJson override. When omitted, it is regenerated from the manifest.
pageConfig
object
Optional page format (format, orientation, margin, printBackground). Defaults to A4 portrait.

Response

200 (republished) or 201 (created):
id
string
slug
string
The canonical slug (the one in the URL).
currentVersionNumber
number
The newly published version. 1 on create; incremented by one on every republish.
manifest
object
The stored manifest, echoed back.
Each republish creates a new version even when the manifest is unchanged — calling PUT N times leaves N versions in history. This is intentional (it keeps currentVersionNumber advancing) and harmless to existing renders.

Errors

StatuscodeMeaning
400invalid_jsonBody is not valid JSON.
400invalid_requestEnvelope, manifest, or pageConfig failed validation (issues included).
400invalid_loop_keyA loop key contains a dot — use a dot-free top-level key.
401unauthorizedMissing/invalid key.
409slug_conflictThe slug is occupied by another (possibly soft-deleted) template — DELETE it first or pick a new slug.
409version_conflictConcurrent republishes raced for the next version number — retry.
cURL
curl -X PUT https://api.craftkit.dev/v1/templates/charter-handover \
  -H "Authorization: Bearer $CRAFTKIT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Charter Handover",
    "manifest": {
      "variables": [
        { "key": "booking.code", "label": "Booking code", "dataType": "text", "required": true },
        { "key": "handover.signatureImageUrl", "label": "Signature", "dataType": "image" }
      ],
      "loops": [
        { "key": "areas", "label": "Inspection areas", "itemFields": [
          { "key": "areaKey", "label": "Area", "dataType": "text" },
          { "key": "condition", "label": "Condition", "dataType": "text" }
        ] }
      ]
    }
  }'
200
{
  "id": "…",
  "slug": "charter-handover",
  "currentVersionNumber": 2,
  "manifest": { "variables": [ "…" ], "loops": [ "…" ] }
}
Prefer PUT over DELETE + POST when you only need the latest layout: it keeps the same template id and slug, and leaves prior renders intact.