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

# Image uploads

> GIF, JPEG, PNG, and WebP via POST commentify/api/v1/media. Per-role size and rate limits, optional S3 bucket and thumbnails.

```env theme={null}
COMMENTIFY_MEDIA_ENABLED=true
COMMENTIFY_MEDIA_DISK=s3
COMMENTIFY_MEDIA_BUCKET=your-comment-media-bucket
```

When `enabled` is false, `POST media` 404s and `GET ui` reports `features.media: false` so the composer hides the control.

## Request

`multipart/form-data` field `file`. Authenticated users need `create` on `Comment`. Guests need `allow_guests` and `media.guests` not `deny`.

Response `201`:

```json theme={null}
{ "url": "https://…/commentify/….png", "thumbnail_url": "https://…/….png" }
```

Insert markdown: `![image](url)`. The bundled composer does this for you when media is on.

Allowed MIME types (config): `image/gif`, `image/jpeg`, `image/png`, `image/webp`.

## Limits by role

`ModeratorGate::role()` → `guest` | `user` | `moderator`:

| Role      | Default max | Default per minute |
| --------- | ----------- | ------------------ |
| Guest     | 512 KB      | 2                  |
| User      | 2048 KB     | 6                  |
| Moderator | 5120 KB     | 20                 |

Oversized files → `413`. Too many uploads → `429` (`commentify-media:{id|ip}`).

`media.guests`: `allow` (default) or `deny` (403). The config also accepts `review`; uploads still store like `allow` — hold the *comment* with `require_approval` if you need a queue.

## Disk

* If `COMMENTIFY_MEDIA_BUCKET` is set, Pro registers a `commentify-media` disk cloned from `filesystems.disks.{COMMENTIFY_MEDIA_DISK}` with that bucket.
* Otherwise it stores on `media.disk` (default `s3` in config — use `public` for local).

Path prefix: `commentify`. Visibility: `public` by default. Thumbnails: max edge `thumbnail_max` (320px); if generation fails, `thumbnail_url` equals `url`.

Use a dedicated bucket when comment images should not share your private app disk.

## Livewire

The API is the upload path. Livewire threads that need images should use the same `POST media` endpoint (or enable the React/Vue composer, which already calls `uploadMedia()`).
