> ## 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.

# Upload a form image

> POST /v1/embed/form-submit/:sessionId/upload-image — upload an image and get back a public URL. Embed session JWT only.

<Info>**POST** `https://api.craftkit.dev/v1/embed/form-submit/:sessionId/upload-image`</Info>

Accepts a `multipart/form-data` upload with a single `file` field (an image), stores it under the
session's namespace, and returns the public URL — so the form submit payload can carry a URL
instead of a raw file. Call this before posting the JSON form data.

## Authorization

Embed session JWT **only** — never a project API key.

<ParamField header="Authorization" type="string" required>
  `Bearer <session_token>` — a **fill**-mode session JWT. The request origin must be allow-listed,
  and `:sessionId` must match the token's session. The `submitForm` permission is **not** required
  for upload — only fill mode.
</ParamField>

## Path parameters

<ParamField path="sessionId" type="string" required>
  The embed session id. Must match the bearer token's session.
</ParamField>

## Body

Send as `multipart/form-data`.

<ParamField body="file" type="file" required>
  The image to upload. MIME type must start with `image/`. Max size 10 MB. The stored key is
  `embed-uploads/{projectId}/{sessionId}/{uuid}.{ext}`; the extension comes from the filename,
  falling back to a MIME-type mapping (jpg, png, gif, webp, svg) or `.bin`.
</ParamField>

## Response

`200` with the public URL of the uploaded image.

<ResponseField name="url" type="string">
  Public URL of the uploaded image. Pass it back as the value of the matching image variable in
  the `data` of your form submit.
</ResponseField>

## Errors

| Status | code                | Meaning                                                             |
| ------ | ------------------- | ------------------------------------------------------------------- |
| 400    | `bad_request`       | Request origin is not in the allowed origins list.                  |
| 400    | `invalid_multipart` | Body is not valid `multipart/form-data`.                            |
| 400    | `missing_file`      | No `file` field in the form data.                                   |
| 401    | `unauthorized`      | Missing/malformed header, or the session token failed verification. |
| 403    | `wrong_mode`        | Session is not `scope.mode = "fill"`.                               |
| 404    | `session_not_found` | `:sessionId` does not match the bearer token.                       |
| 413    | `file_too_large`    | File exceeds the 10 MB limit.                                       |
| 415    | `invalid_type`      | The file's MIME type is not `image/*`.                              |

```bash cURL theme={null}
curl -X POST https://api.craftkit.dev/v1/embed/form-submit/$SESSION_ID/upload-image \
  -H "Authorization: Bearer $SESSION_TOKEN" \
  -F "file=@logo.png"
```

```json 200 theme={null}
{
  "url": "https://cdn.craftkit.dev/embed-uploads/proj_01j.../sess_01j.../9f1c....png"
}
```
