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

# Media uploads

> Upload images, GIFs and video, in one request or in chunks.

## Small files

`POST /media` (write) takes a small image, GIF or video as the whole body, with its `Content-Type`. It returns a `media_id` to pass in `media_ids` when [creating a post](/api/endpoints#creating-a-post).

```bash theme={null}
curl -X POST https://xit.example.org/api/v1/media \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: image/png" \
  --data-binary @picture.png
```

## Chunked uploads

Use chunks for files larger than the server's 16 MiB request limit, or to retry an interrupted upload. Each segment can be up to 5 MiB. The instance's image and video limits still apply.

| Method | Path | Scope | Description |
| - | - | - | - |
| `POST` | `/media/uploads` | write | Start an upload. JSON: `media_type` and `total_bytes`. Returns `media_id`, `max_segment_bytes` and `expires_after_secs`. |
| `POST` | `/media/{id}/segments/{segment_index}` | write | Send one segment as the raw body. Indices start at 0; retrying an index replaces that segment. |
| `POST` | `/media/{id}/finalize` | write | Finish an upload after sending every segment. Returns its processing state. |
| `GET` | `/media/{id}` | read | Check the upload's processing state. Pending uploads also report `total_bytes`, `received_bytes` and `segments`. |

**1. Start**

`POST /media/uploads` with the file's MIME type and exact byte length. Save the returned `media_id`.

**2. Send segments**

Send consecutive segments to `POST /media/{id}/segments/0`, `/1`, and so on, as raw binary bodies. You can send them out of order and retry an index without counting its bytes twice.

**3. Resume if needed**

Read `GET /media/{id}`. While `processing` is `uploading`, `segments` lists each received `segment_index` and its `bytes`.

**4. Finalize**

`POST /media/{id}/finalize`. You can retry it. If processing is still pending, poll `GET /media/{id}` after `check_after_secs`.

**5. Publish**

Use the `media_id` in a post once `processing` is `succeeded`. A `failed` result includes an `error`: fix the file and start a new upload.

## Rules

* Pending uploads expire after an hour.
* Upload state lives in the server process. If the server restarts, start a new upload.
* You can have up to eight pending uploads.
* Only tokens for the account that started an upload can inspect or change it.
* Starting an upload counts toward the upload limit. Sending segments and finalizing use the normal write limit; progress checks use the read limit.


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