---
title: 'API Error: 403 Forbidden on POST Requests with form-data'
description: 'Why API calls sent as multipart/form-data get a 403 Forbidden, and how to send them as application/x-www-form-urlencoded instead.'
url: https://www.medialab.co/support/troubleshooting/integration/api-403-forbidden-on-multipart-requests
---

# API Error: 403 Forbidden on POST Requests with form-data

If your integration gets a **403 Forbidden** response on a `POST` or `PUT` request to the MediaLab API, while `GET` requests such as `/api/user/info` work fine, the request body is most likely sent as `multipart/form-data`.

For security reasons, MediaLab only accepts `multipart/form-data` requests on the dedicated upload endpoints. Regular API calls, including `POST /api/upload/id`, must send their parameters as `application/x-www-form-urlencoded`. A multipart request to a regular API endpoint is rejected before it reaches the API, so you get a plain 403 page instead of a JSON error.

### Why this happens

Many HTTP clients use `multipart/form-data` by default when you add body fields:

- **Postman** – the **form-data** body option.
- **curl** – the `-F` / `--form` option.
- **JavaScript** – passing a `FormData` object to `fetch` or `XMLHttpRequest`.
- **PHP / Guzzle** – the `multipart` request option.

None of the regular API endpoints need multipart. Creating an upload with `POST /api/upload/id` only sends parameters such as `folder_id` and `autofinish`. The file itself is uploaded afterwards to the upload URLs returned in the response.

### How to Resolve

Send the same parameters as `application/x-www-form-urlencoded`:

- **Postman** – change the body type from **form-data** to **x-www-form-urlencoded**. You can keep the same keys and values.
- **curl** – use `-d` / `--data` instead of `-F`:

```bash
curl -X POST https://<your-medialab-domain>/api/upload/id \
  -H "Authorization: Bearer <access_token>" \
  -d folder_id=1234 \
  -d autofinish=false
```

- **JavaScript** – use `URLSearchParams` instead of `FormData`:

```js
await fetch('https://<your-medialab-domain>/api/upload/id', {
  method: 'POST',
  headers: { Authorization: 'Bearer <access_token>' },
  body: new URLSearchParams({ folder_id: '1234', autofinish: 'false' }),
})
```

- **PHP / Guzzle** – use the `form_params` request option instead of `multipart`.

After this change, the request reaches the API and you get a normal JSON response. If you still get a 403 after switching to `x-www-form-urlencoded`, please contact MediaLab's service desk and include the endpoint, the time of the request and the response you received.
