> ## Documentation Index
> Fetch the complete documentation index at: https://docs.olonjs.com/llms.txt
> Use this file to discover all available pages before exploring further.

# POST /api/upload-asset — upload a media file via JSON body

> POST /api/upload-asset accepts a JSON body with a base64-encoded file and saves it to the project's public assets directory for use in image fields.

The `POST /api/upload-asset` endpoint lets you upload images and other media files directly through Studio or custom tooling. The endpoint accepts a **JSON body** carrying the file's name, MIME type, and base64-encoded content. Uploaded files are saved to the project's public assets images directory and are immediately available as image URLs you can reference in any image field.

Studio calls this endpoint when you drag-and-drop or select a file in the image picker. You can also call it from scripts to seed your project with images.

## Request

* **Method:** `POST`
* **Path:** `/api/upload-asset`
* **Content-Type:** `application/json`

<ParamField body="filename" type="string" required>
  The target filename including extension (e.g., `"readme-first.jpg"`). The file will be saved under this name in the assets images directory.
</ParamField>

<ParamField body="data" type="string" required>
  The file content as a **base64-encoded string** (without a data-URL prefix). The endpoint decodes this string and writes the binary file to disk.
</ParamField>

<ParamField body="mimeType" type="string">
  Optional MIME type of the file (e.g., `"image/jpeg"`, `"image/png"`). Used for validation and metadata. If omitted, the type is inferred from the filename extension.
</ParamField>

```bash theme={null}
# Encode the file and send it as a JSON payload
FILE_B64=$(base64 -i ./readme-first.jpg)

curl -X POST https://localhost:3000/api/upload-asset \
  -H "Content-Type: application/json" \
  -d "{
    \"filename\": \"readme-first.jpg\",
    \"mimeType\": \"image/jpeg\",
    \"data\": \"${FILE_B64}\"
  }"
```

## Response

**200 OK** — The file was saved successfully. The response contains the public URL you can use in image fields.

<ResponseField name="url" type="string">
  The public path to the uploaded file (e.g., `"/assets/images/readme-first.jpg"`). Use this value as the `url` in any `ImageSelectionSchema` field — for example in a `hero` or `content-block` section's `image.url`.
</ResponseField>

```json theme={null}
{ "url": "/assets/images/readme-first.jpg" }
```

## Supported formats

The endpoint accepts common image formats. Examples include:

| Format | MIME type |
| - | - |
| JPEG | `image/jpeg` |
| PNG | `image/png` |
| WebP | `image/webp` |
| SVG | `image/svg+xml` |
| GIF | `image/gif` |

## Error responses

| Status | Meaning |
| - | - |
| `400` | `filename` is missing or `data` is not a string. Also returned when the file type is invalid (e.g., an executable disguised as an image). |
| `413` | The uploaded file exceeds the maximum allowed size. |
| `500` | An unexpected filesystem error occurred. The response body contains an `error` string. |

```json theme={null}
{ "error": "Invalid file type" }
```


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.