# Large files

Files over 95 MB are uploaded to a reserved upload URL instead of the request body.

Request bodies are limited to 95 MB. Files up to 2 GB and 60 minutes use a reserved upload, in two steps: create the separation with the file's size, then upload the file to the returned URL. Reserved uploads require bought credits.

## Reserve

Send `POST /separations` with the file's size in bytes as `bytes` and no body. The request is checked like any other create, so a missing balance or too many running separations return an error before the upload.

```bash
curl -X POST "https://api.disband.io/v1/separations" \
  --url-query stems=vocals \
  --url-query stems=instrumental \
  --url-query bytes=734003200 \
  -H "Authorization: Bearer $DISBAND_KEY"
```

```json
{
  "id": "sep_5aTuE8",
  "created_at": "2026-11-12T14:04:05.000Z",
  "expires_at": "2026-11-12T16:04:05.000Z",
  "status": "uploading",
  "upload": {
    "url": "https://…",
    "expires_at": "2026-11-12T14:34:05.000Z"
  }
}
```

## Upload

`PUT` the file to `upload.url` in a single request of exactly `bytes` bytes, without an `Authorization` header. The URL is signed. The upload must start before `upload.expires_at` and has another 30 minutes to finish.

```bash
curl -X PUT "$upload_url" --upload-file recording.wav
```

The separation starts when the file has arrived and continues like any other: `uploading`, then `queued`, `separating` and `ready`. See [Status](https://disband.io/docs/separations#status).

## Errors

The file is checked after the upload. Errors that a direct create returns end the separation with `status: "failed"` and the `problem` instead. Nothing is charged.

| Cause                                                        | Problem                                                                 |
| ------------------------------------------------------------ | ----------------------------------------------------------------------- |
| The file's size differs from `bytes`, or it can't be decoded | [`bad-audio`](https://disband.io/docs/errors#bad-audio)                 |
| The format isn't supported                                   | [`unsupported-audio`](https://disband.io/docs/errors#unsupported-audio) |
| The balance was spent before the upload finished             | [`out-of-credits`](https://disband.io/docs/errors#out-of-credits)       |
| No upload within the window                                  | [`upload-timeout`](https://disband.io/docs/errors#upload-timeout)       |

A reservation counts as a running separation until it ends. Delete unused reservations to free their place.
