Craftkitdocs

POST /v1/embed/catalogs

Publish a named variable catalog version via API.

Publish a new version of a named variable catalog. Each call creates the next version number and marks it as current — the previous version is archived but never deleted.

POST /v1/embed/catalogs

Quick Start

curl

curl -X POST https://api.craftkit.dev/v1/embed/catalogs \
  -H "Authorization: Bearer $CRAFTKIT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "my-catalog",
    "catalog": {
      "allowCustom": false,
      "namespaces": [
        {
          "key": "customer",
          "label": "Customer",
          "fields": [
            { "key": "customer.name",  "label": "Customer name",  "dataType": "text",   "previewData": "Acme Corp" },
            { "key": "customer.email", "label": "Customer email", "dataType": "email",  "previewData": "hello@acme.com" }
          ]
        }
      ],
      "loops": []
    }
  }'

Node.js

const res = await fetch('https://api.craftkit.dev/v1/embed/catalogs', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.CRAFTKIT_API_KEY}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    name: 'my-catalog',
    catalog: {
      allowCustom: false,
      namespaces: [
        {
          key: 'customer',
          label: 'Customer',
          fields: [
            { key: 'customer.name',  label: 'Customer name',  dataType: 'text',  previewData: 'Acme Corp' },
            { key: 'customer.email', label: 'Customer email', dataType: 'email', previewData: 'hello@acme.com' },
          ],
        },
      ],
      loops: [],
    },
  }),
});

const { id, name, version } = await res.json();
// { id: "cat_01jt...", name: "my-catalog", version: 1 }

Python

import os, requests

res = requests.post(
    "https://api.craftkit.dev/v1/embed/catalogs",
    headers={"Authorization": f"Bearer {os.environ['CRAFTKIT_API_KEY']}"},
    json={
        "name": "my-catalog",
        "catalog": {
            "allowCustom": False,
            "namespaces": [
                {
                    "key": "customer",
                    "label": "Customer",
                    "fields": [
                        {"key": "customer.name",  "label": "Customer name",  "dataType": "text",  "previewData": "Acme Corp"},
                        {"key": "customer.email", "label": "Customer email", "dataType": "email", "previewData": "hello@acme.com"},
                    ],
                }
            ],
            "loops": [],
        },
    },
)
result = res.json()
# {"id": "cat_01jt...", "name": "my-catalog", "version": 1}

Request body

{
  "name": "my-catalog",
  "catalog": {
    "allowCustom": false,
    "namespaces": [ ... ],
    "loops": [ ... ]
  }
}
Field Type Required Description
name string Yes Catalog name. Lowercase letters, numbers, and hyphens. Reusing an existing name creates the next version.
catalog object Yes The full catalog payload — see schema below.

Catalog schema

{
  "allowCustom": false,
  "namespaces": [
    {
      "key": "customer",
      "label": "Customer",
      "icon": "user",
      "fields": [
        {
          "key": "customer.name",
          "label": "Customer name",
          "dataType": "text",
          "previewData": "Acme Corp",
          "description": "The company or individual name",
          "format": "optional format string"
        }
      ]
    }
  ],
  "loops": [
    {
      "key": "order.items",
      "label": "Order items",
      "itemFields": [
        { "key": "name",  "label": "Product",    "dataType": "text",     "previewData": "Widget A" },
        { "key": "qty",   "label": "Quantity",   "dataType": "number",   "previewData": 2 },
        { "key": "price", "label": "Unit price", "dataType": "currency", "previewData": 49.99 }
      ],
      "previewData": [
        { "name": "Widget A", "qty": 2, "price": 49.99 },
        { "name": "Widget B", "qty": 1, "price": 99.00 }
      ]
    }
  ]
}

namespaces[].fields object

Field Type Required Description
key string Yes Dot-path key used in templates: customer.name. Pattern: ^[a-zA-Z_][a-zA-Z0-9_.]*$.
label string Yes Display name in the variable picker.
dataType string Yes One of text, longtext, number, currency, date, boolean, image, url, email.
previewData scalar Dummy value shown in the live preview. Doubles as input placeholder in form-fill embeds.
format string Formatting hint: currency:EUR, date:DD/MM/YYYY.
description string Helper text shown beneath the field in the variable picker.

loops object

Field Type Required Description
key string Yes Loop key: order.items. Compiles to {{#each order.items}}...{{/each}}.
label string Yes Display name in the picker.
itemFields array Yes Fields available inside the loop body. Same shape as namespace fields.
previewData array Dummy rows for the live preview (max 10).

Response

201 Created

{
  "id": "cat_01jt9wq...",
  "name": "my-catalog",
  "version": 1
}
Field Type Description
id string Catalog row UUID. Pass this as catalog_ref.id in a session if you want to pin a specific version.
name string The catalog name you passed.
version number Monotonically increasing version number within this name.

Versioning

Calling POST /v1/embed/catalogs with the same name creates the next version:

v1 → archived
v2 → archived
v3 → current ← sessions referencing this name get v3

Sessions minted with catalog_ref: { name: "my-catalog" } always resolve to the current version. To pin a session to a specific version, pass catalog_ref: { name: "my-catalog", version: 2 }.

Referencing the catalog in a session

After publishing, reference the catalog by name when minting a session:

{
  "tenant": { "externalId": "org_123", "displayName": "Acme Corp" },
  "actor":  { "externalId": "usr_456", "displayName": "Jane Smith" },
  "catalog_ref": { "name": "my-catalog" }
}

Or inline a one-off catalog without publishing it first:

{
  "tenant": { ... },
  "actor":  { ... },
  "variable_catalog": { "allowCustom": false, "namespaces": [...], "loops": [] }
}

See Embed sessions for the full session mint reference.

Errors

Status Code Meaning
401 missing_authorization No Authorization header.
401 invalid_credentials API key not found, revoked, or embed not enabled.
400 invalid_json Request body is not valid JSON.
422 invalid_request Body failed validation — check issues array for field-level details.

Last revised: 2026-05-12