---
title: Images Reference
path: reference/images
status: published
---

# Images Reference

Endpoints for the tenant image library. For the guide-level walk-through, see [Attachments and Images](../tutorials/attachments-and-images).

**Base path:** `/v3/images/`
**Public proxy:** `/i/{image_id}` (no auth)

## GET /v3/images

List images.

**Query parameters:**

| Parameter | Notes |
|-----------|-------|
| `folder` | Filter by folder name |
| `search` | Substring match on filename or alt text |
| `page` | 1-indexed (default 1) |
| `page_size` | 1–100 (default 25) |

**Response (200):**

```json
{
  "result": [
    {
      "id": "img_01HXYZ",
      "filename": "logo.png",
      "original_filename": "company-logo.png",
      "content_type": "image/png",
      "size": 42195,
      "width": 600,
      "height": 200,
      "url": "https://scaisend.scailabs.ai/i/img_01HXYZ",
      "thumbnail_url": "https://scaisend.scailabs.ai/i/img_01HXYZ?variant=thumbnail",
      "alt_text": "Acme logo",
      "folder": "brand",
      "created_at": "2026-04-23T10:00:00Z",
      "updated_at": "2026-04-23T10:00:00Z"
    }
  ],
  "total": 42,
  "page": 1,
  "page_size": 25
}
```

## POST /v3/images

Upload an image.

**Content-Type:** `multipart/form-data`.

**Form fields:**

| Field | Type | Required | Notes |
|-------|------|---------|-------|
| `file` | binary | Yes | JPEG, PNG, GIF, or WebP; ≤ 10 MB |
| `alt_text` | string | No | Accessibility alt text |
| `folder` | string | No | Organize images into folders |

**Response (201):** `ImageResponse` (same shape as list items).

**Errors:**

| Status | Cause |
|--------|-------|
| 400 | Unsupported MIME type or malformed image |
| 413 | File exceeds 10 MB |

## GET /v3/images/folders

List distinct folder names in use.

**Response (200):**

```json
{"folders": ["brand", "marketing-q2", "headshots"]}
```

## GET /v3/images/{image_id}

Get image metadata.

**Response (200):** `ImageResponse`.

**Errors:** 404 if not found.

## PATCH /v3/images/{image_id}

Update metadata.

**Request body:**

| Field | Type | Notes |
|-------|------|-------|
| `alt_text` | string | |
| `folder` | string | |

**Response (200):** updated `ImageResponse`.

## DELETE /v3/images/{image_id}

Delete an image. Messages already sent that referenced this image are unaffected — they've either embedded the bytes (CID mode) or the proxy URL will return `410 Gone` going forward.

**Response (204):** no body.

## GET /i/{image_id}

Public image proxy. No authentication.

**Headers on response:**

| Header | Value |
|--------|-------|
| `Content-Type` | Original MIME type (`image/png`, etc.) |
| `Content-Length` | Byte size |
| `Cache-Control` | `public, max-age=31536000, immutable` |
| `ETag` | Content hash for conditional requests |

**Query parameters:**

| Parameter | Notes |
|-----------|-------|
| `variant` | `thumbnail` (returns a smaller version for preview UI) |

### HEAD /i/{image_id}

Same headers, no body. Useful for link-checking and preflight.

## Size limits

| Limit | Value |
|-------|-------|
| Max file size | 10 MB |
| Supported formats | JPEG, PNG, GIF, WebP |

Images exceeding these limits are rejected at upload time with `413`.

## Related

- [Attachments and Images](../tutorials/attachments-and-images)
- [Tracking](../concepts/tracking) — `image_embed_mode: proxy` uses these URLs.
