# Upload a file

`POST /v1/media`

Uploads a file to send in a message. Send it as `multipart/form-data`, with the file in a field called `file`.

Needs `messages:send`. Counts against the heavy request limit (10 a minute).

> Soosh reads the file type from the file itself, not from its name or the `Content-Type` of the part.

## Body

- `file` (file, required): The file to upload.

## Headers

- `Idempotency-Key` (string): Makes this request safe to retry. See [Retrying safely](/reference/api/#retrying-safely). 1 to 255 characters.

## Accepted files

| Kind | Types | Largest |
|---|---|---|
| Image | JPEG, PNG | 5 MB |
| Video | MP4, 3GPP | 14 MB |
| Audio | AAC, MP4, MPEG (MP3), AMR, OGG | 14 MB |
| Document | PDF, DOC, DOCX, XLS, XLSX, PPT, PPTX, TXT, CSV | 14 MB |

## How long it's kept

An upload is kept for 30 days: `expires_at` is the day it goes. A message, or a scheduled or running broadcast, that uses it keeps it longer.

## Next: send it

Send the file with `POST /v1/messages`, using the returned `id` as `media.media_id`. A template with a file in its header takes it as `template.header.media_id`, in `POST /v1/messages` and in `POST /v1/broadcasts`.

## Example

```sh
curl -X POST https://app.soosh.io/v1/media \
  -H "Authorization: Bearer $SOOSH_API_KEY" \
  -H "Idempotency-Key: upload-media-upload-parcel-jpg-1" \
  -F "file=@parcel.jpg"
```

Response 201:

```json
{
  "id": "5a9c3e7b-2d4f-4b61-8c0e-7f1a3d5b9e24",
  "mime_type": "image/jpeg",
  "size": 186472,
  "filename": "parcel.jpg",
  "expires_at": "2026-11-13T09:28:41.207Z"
}
```

## Returns

201. The stored file, with its `id`.

## Errors

Besides the ones every request can get (https://docs.soosh.io/reference/api/errors/):

- 400 `invalid_request`: The body isn't `multipart/form-data`, has a field other than `file`, or has more than one file.
- 422 `invalid_field`: The `file` is missing, empty, or sent as a text field instead of a file.
- 413 `too_large`: The file is over the size for its type, or the request is over the endpoint's size limit.
- 415 `unsupported_media_type`: The file's type isn't one of those listed.
- 409 `idempotency_in_progress`: A request with the same `Idempotency-Key` is still running.
- 422 `idempotency_mismatch`: The `Idempotency-Key` was used before for a different file, or by another of your API keys.