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

# Produtos e variações

> Modelo de produto, imagens por URL, estoque, licenças e como editar variações pela API

A API de produtos cobre **criação, leitura, atualização e exclusão** de produtos simples, combos (bundles) e variações. Não existe um recurso separado de “variante”: uma variação **é um produto** com `parent_id` apontando para o combo. Criar, editar estoque, preço, imagens, categoria, visibilidade e o restante usa as mesmas rotas.

Base: `https://api.selltrust.com.br/api/v1` — header `Authorization: Bearer <token>`.

## Tipos

| Tipo | `is_bundle` | `parent_id` | Preço / estoque |
| - | - | - | - |
| Produto simples | `false` | `null` | Tem `pricing`, `inventory_amount`, `license_keys` |
| Combo (bundle) | `true` | `null` | Sem preço e sem estoque. Serve de agrupador das variações |
| Variação | `false` | UUID do combo | Igual ao produto simples: preço, estoque, imagens, etc. |

`GET /api/v1/product` lista só a **raiz** (`parent_id = null`). Variações não aparecem soltas nessa lista. Use [`GET /api/v1/product/{id}/variants`](/api-reference/products/variants) ou `GET /api/v1/product/{id}` na própria variação.

## Imagens

Cada produto aceita até **5** imagens. Cada item do array `images` pode ser:

1. **Arquivo da plataforma** no formato `uuid.extensão` (o mesmo que o painel grava depois do upload).
2. **URL absoluta** `http://` ou `https://` (CDN próprio, Imgur, S3, etc.), até 2048 caracteres.

Quando você envia uma URL, a SellTrust **não reescreve** o caminho com o CDN da plataforma. Na loja, no pedido e nas respostas da API a imagem é exatamente o link que você mandou.

```json theme={null}
{
  "images": [
    "https://cdn.seudominio.com/capas/elden-ring.jpg",
    "https://cdn.seudominio.com/capas/elden-ring-2.jpg"
  ]
}
```

> [!NOTE]
>
> A primeira posição do array é a **capa**. Para trocar a capa, reenvie o array completo com a URL (ou arquivo) desejada no índice `0`. `images` no PATCH **substitui** a lista atual — não é um merge.

Arquivos enviados pelo upload da plataforma continuam sendo resolvidos para `https://cdn…/store/{loja}/product/{arquivo}`. URLs externas passam direto.

## Estoque e licenças (produto simples e variação)

Dois jeitos de controlar estoque. Os dois valem na **criação** e no **PATCH** (incluindo variação).

**Estoque numérico** — envie `inventory_amount` (inteiro ≥ 0). Use `null` se o produto não deve controlar quantidade.

**Chaves / contas (entrega automática)** — envie `license_keys` (array de strings, até 5.000 por request, cada uma até 255 caracteres).

* Se `license_keys` tiver itens, o estoque passa a ser **o tamanho do array** (`inventory_amount` é ignorado nesse request).
* No **PATCH**, enviar `license_keys` **substitui** todas as chaves atuais. Envie a lista completa, não um diff.
* `license_keys: []` apaga as chaves. O estoque só muda se você mandar `inventory_amount` no mesmo request.
* Se você **não** enviar `inventory_amount` nem `license_keys`, o estoque permanece como está.

```json theme={null}
{
  "is_bundle": false,
  "inventory_amount": 40
}
```

```json theme={null}
{
  "is_bundle": false,
  "license_keys": ["AAAA-1111", "BBBB-2222", "CCCC-3333"]
}
```

As chaves completas vêm em `GET /api/v1/product/{id}`. A listagem de variações traz só `_count.license_keys` (quantidade), para não devolver milhares de keys de uma vez.

## Como editar uma variação

É o **mesmo** `PATCH /api/v1/product/{id}` do produto simples. Use o UUID da **variação** (não o do combo).

O body precisa de `is_bundle: false` (o valor tem que bater com o tipo atual). O restante é parcial: mande só o que mudou.

| O que mudar | Body (além de `is_bundle: false`) |
| - | - |
| Estoque numérico | `{ "inventory_amount": 80 }` |
| Reposição de keys | `{ "license_keys": ["KEY-1", "KEY-2"] }` |
| Preço | `{ "pricing": { "price": 29.9, "comparison": 39.9 } }` |
| Capa / galeria | `{ "images": ["https://cdn.seudominio.com/nova.jpg"] }` |
| Título | `{ "title": "90 dias (promo)" }` — o `slug` é regenerado |
| Categoria | `{ "category_id": "uuid-folha" }` |
| Ocultar na vitrine | `{ "hide_product": true }` |
| Chat | `{ "chat_enabled": true, "chat_welcome_message": "Olá" }` |
| Instruções / qtd. mín. | `{ "instructions": "...", "min_quantity": 1 }` |
| Mover de combo | `{ "parent_id": "uuid-outro-combo" }` ou `null` para virar produto raiz |

Fluxo típico:

1. Crie o combo: `POST /api/v1/product` com `is_bundle: true`.
2. Crie cada variação: `POST /api/v1/product` com `is_bundle: false` e `parent_id` = id do combo.
3. Liste: `GET /api/v1/product/{idDoCombo}/variants`.
4. Edite estoque, preço ou imagem: `PATCH /api/v1/product/{idDaVariacao}`.
5. Remova: `DELETE /api/v1/product/{idDaVariacao}`. Excluir o combo apaga as variações em cascata.

Detalhes e exemplos em [Criar](/api-reference/products/create), [Atualizar](/api-reference/products/update) e [Variações](/api-reference/products/variants).

## Combo (`is_bundle: true`)

O PATCH do combo também exige `is_bundle: true`. Dá para mudar título, descrição, imagens (URL ou arquivo), categoria, visibilidade e chat. **Não** envie `pricing`, `inventory_amount`, `license_keys`, `parent_id`, `min_quantity` nem `instructions` — esses campos não existem no combo.

## Categoria

`category_id` é obrigatório na criação e, no PATCH, precisa ser uma categoria **folha** da **mesma loja** (sem subcategorias). Caso contrário a API responde 400/404.

## Slug e posição

* `slug` é gerado a partir do `title`. No PATCH, se o título mudar, um slug novo é gerado (com sufixo se já existir na loja). Não há campo `slug` no body de produto.
* `position` entra nas respostas. Reordenar produtos é só pelo painel, não pela API pública.

## Limites

* Até **1000** produtos raiz por loja (variações não entram nesse teto).
* `title` 2–255 caracteres.
* `description` até 50.000; `instructions` até 30.000; `chat_welcome_message` até 1.000.
* `price` / `comparison` entre 0 e 100.000. O preço comparativo, se enviado, não pode ser menor que o preço.

## Erros comuns

| Situação | HTTP |
| - | - |
| Token ausente / inválido | 401 |
| Categoria com subcategorias, pai que não é combo, `is_bundle` invertido | 400 |
| Produto, categoria ou combo pai inexistente nesta loja | 404 |
| Rate limit (120 req/min) | 429 |


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