POST
https://api.craftkit.dev/v1/embed/form-submit/:sessionIddata 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.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
The embed session id. Must match the bearer token’s session.
Body
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.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.
Render id (UUID).
queued initially.Embed-scoped poll URL (
/v1/embed/renders/:id). Poll with the session JWT.null until the render succeeds.Errors
| Status | code | Meaning |
|---|---|---|
| 400 | bad_request | Request origin is not in the allowed origins list. |
| 400 | invalid_json | Body is not valid JSON. |
| 400 | invalid_request | Body did not match { data, datasetSelection? } (issues included). |
| 400 | invalid_input_data | data did not match the manifest (issues included). |
| 401 | unauthorized | Missing/malformed header, or the session token failed verification. |
| 403 | wrong_mode | Session is not scope.mode = "fill". |
| 403 | permission_denied | Session lacks the submitForm permission. |
| 404 | session_not_found | :sessionId does not match the bearer token. |
| 404 | template_not_resolved | Session scope carries no template id, or the external id is not a UUID. |
| 404 | template_not_found | No such template in this project. |
| 404 | unpublished_template | The template has no published version. |
| 503 | queue_unavailable | Render queue temporarily unreachable — retry. |
| 500 | internal | The render could not be written or enqueued. |
cURL
202