# Mídia

A **Mídia** é o utilitário de upload de imagens **compartilhado** da API. Em vez de cada recurso ter seu próprio upload, você sobe a imagem **uma vez** aqui, recebe um identificador e depois **vincula** esse identificador ao recurso final. Como ela serve a vários domínios ao mesmo tempo (produtos, anúncios e o que vier), faz mais sentido documentá-la num lugar só do que repetir o mesmo fluxo dentro de cada guia.

> Pré-requisitos: você precisa de um token válido. Veja [Autenticação](/guia/autenticacao).

Hoje quem consome a Mídia é:

- **Produtos** — a galeria do produto ([Produtos › Galeria](/guia/produtos#galeria)).
- **Anúncios** — as imagens da publicação ([Anúncios](/guia/anuncios)).

---

## Como funciona

O upload é **síncrono e em uma única chamada** (`multipart/form-data`): você manda o arquivo e, na mesma resposta, recebe a imagem já processada. O servidor converte tudo para **WebP**, gera automaticamente as **variações de tamanho** (`thumbnail`, `sm`, `md`, `lg`, `xl`) e devolve as URLs públicas de cada uma — você não precisa redimensionar nada do seu lado.

O identificador da imagem é o campo `id` (um **ULID**). É esse valor que você usa como `image_id` ao vincular a um produto ou anúncio, e como `{file_hash}` nas rotas de detalhe e exclusão.

---

## Ciclo de vida

A imagem nasce **solta** (`in_use: false`, sem `reference_id`). Ela só passa a contar como "em uso" quando você a vincula a um recurso — por exemplo, ao adicioná-la à galeria com `POST /api/products/{id}/gallery` passando o `id` como `image_id`.

- **Solta:** imagens sem vínculo são removidas por uma rotina de limpeza da plataforma (janela de ~72h). Suba a imagem só quando for usá-la em seguida.
- **Em uso:** uma imagem `in_use: true` fica protegida — qualquer tentativa de excluir ou alterar retorna **409**. Não é pra te atrapalhar: é uma trava de segurança pra você não derrubar, sem querer, uma foto que está aparecendo num produto ou anúncio publicado. Quando quiser mesmo remover, tire o vínculo no recurso primeiro (ex.: remova da galeria do produto) e aí a exclusão libera.

---

## Subir uma imagem

<a class="api-route" href="/reference/primeiros-passos#tag/media/POST/api/media/upload"><span class="api-method api-method-post">POST</span><span class="api-path">/api/media/upload</span></a>

Envie como `multipart/form-data` no campo `image`:

| Regra | Valor |
|-------|-------|
| Campo | `image` (arquivo) |
| Formatos aceitos | `image/jpeg`, `image/png`, `image/webp` |
| Tamanho máximo | 2 MB |

```bash
curl -X POST https://api.sandbox.samdevel.com.br/api/media/upload \
  -H "Authorization: Bearer sk_live_a1b2c3d4e5f6..." \
  -F "image=@/caminho/para/foto.jpg"
```

Resposta **201**. O arquivo já vem convertido para WebP, com uma URL por tamanho:

```json
{
  "success": true,
  "data": {
    "id": "01K8PBIMG00001VWXYZ12345678",
    "original_source": "https://cdn.unisupri.com/products/2026/05/28/original_01K8PBIMG00001VWXYZ12345678.webp",
    "urls": [
      { "name": "thumbnail", "size": "135x135", "url": "https://cdn.unisupri.com/.../thumbnail_01K8PBIMG....webp" },
      { "name": "sm", "size": "200x200", "url": "https://cdn.unisupri.com/.../sm_01K8PBIMG....webp" },
      { "name": "md", "size": "400x400", "url": "https://cdn.unisupri.com/.../md_01K8PBIMG....webp" },
      { "name": "lg", "size": "800x800", "url": "https://cdn.unisupri.com/.../lg_01K8PBIMG....webp" },
      { "name": "xl", "size": "1600x1600", "url": "https://cdn.unisupri.com/.../xl_01K8PBIMG....webp" }
    ],
    "in_use": false,
    "reference_id": null,
    "reference_model": null,
    "created_at": "2026-05-28T10:00:00-03:00",
    "updated_at": "2026-05-28T10:00:00-03:00"
  }
}
```

---

## Listar imagens

<a class="api-route" href="/reference/primeiros-passos#tag/media/GET/api/media"><span class="api-method api-method-get">GET</span><span class="api-path">/api/media</span></a>

Lista paginada das imagens da sua loja. Filtros:

| Parâmetro | Para quê |
|-----------|----------|
| `filter[reference_id]` | Imagens vinculadas a um recurso específico (ID do produto/anúncio). |
| `filter[reference_model]` | Tipo do recurso vinculado: `product` (produto), `publication` (anúncio) ou `store` (loja). |
| `filter[in_use]` | `true` (já vinculadas) ou `false` (soltas). |
| `sort` | `created_at` ou `updated_at` (prefixe com `-` para descendente). |
| `per_page` | Itens por página (1–100, default 15). |

---

## Detalhes de uma imagem

<a class="api-route" href="/reference/primeiros-passos#tag/media/GET/api/media/{file_hash}"><span class="api-method api-method-get">GET</span><span class="api-path">/api/media/{file_hash}</span></a>

Retorna os mesmos dados do upload para a imagem cujo `id` você informar. **404** se ela não existir ou não pertencer à sua loja.

---

## Excluir uma imagem

<a class="api-route" href="/reference/primeiros-passos#tag/media/DELETE/api/media/{file_hash}"><span class="api-method api-method-delete">DELETE</span><span class="api-path">/api/media/{file_hash}</span></a>

Remove o registro e os arquivos no storage. Retorna **204**. Se a imagem estiver em uso por um produto ou anúncio (`in_use: true`), retorna **409** — desvincule antes.
