Skip to main content
POST https://api.craftkit.dev/v1/embed/form-submit/:sessionId
Validates the submitted data against the template version’s manifest, merges JWT-claimed prefill under the user-supplied data (user wins), and enqueues a render with source = "form". Returns 202 with a poll URL. Rendering is asynchronous.

Authorization

Embed session JWT only — never a project API key.
Authorization
string
required
Bearer <session_token> — a fill-mode session JWT with permissions.submitForm = true. The request origin must be allow-listed (used as the token audience), and :sessionId must match the token’s session.

Path parameters

sessionId
string
required
The embed session id. Must match the bearer token’s session.

Body

data
object
required
Variable values to render. May use flat dot-keys ("customer.name") — they are expanded to nested objects before manifest validation. Validated against the template version’s manifest. Reserved property names (__proto__, constructor, prototype) in keys are stripped.
datasetSelection
object
Optional string→string map persisted on the render row (for example, which source records the form was filled from).

Response

202 when the render is queued.
id
string
Render id (UUID).
status
string
queued initially.
pollUrl
string
Embed-scoped poll URL (/v1/embed/renders/:id). Poll with the session JWT.
downloadUrl
string | null
null until the render succeeds.
errorMessage
string | null
createdAt
string

Errors

StatuscodeMeaning
400bad_requestRequest origin is not in the allowed origins list.
400invalid_jsonBody is not valid JSON.
400invalid_requestBody did not match { data, datasetSelection? } (issues included).
400invalid_input_datadata did not match the manifest (issues included).
401unauthorizedMissing/malformed header, or the session token failed verification.
403wrong_modeSession is not scope.mode = "fill".
403permission_deniedSession lacks the submitForm permission.
404session_not_found:sessionId does not match the bearer token.
404template_not_resolvedSession scope carries no template id, or the external id is not a UUID.
404template_not_foundNo such template in this project.
404unpublished_templateThe template has no published version.
503queue_unavailableRender queue temporarily unreachable — retry.
500internalThe render could not be written or enqueued.
cURL
curl -X POST https://api.craftkit.dev/v1/embed/form-submit/$SESSION_ID \
  -H "Authorization: Bearer $SESSION_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "data": {
      "customer.name": "Acme Corp",
      "customer.email": "hello@acme.com"
    }
  }'
202
{
  "id": "0193c2c3-...",
  "status": "queued",
  "pollUrl": "https://api.craftkit.dev/v1/embed/renders/0193c2c3-...",
  "downloadUrl": null,
  "errorMessage": null,
  "createdAt": "2026-06-05T10:00:00.000Z"
}