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

# Produtos

> Defina o que você vende e atrele diferentes ofertas e condições de preço.

Um **produto** é o item de catálogo que descreve **o que você vende** — um plano, um serviço, um item físico. Ele não carrega valor: quem define **quanto** e **como** cobrar é o **preço** (`price`). Essa separação é o que deixa o mesmo produto ter várias formas de cobrança (mensal, anual, promocional) sem duplicar o cadastro da oferta.

<Info>
  **Product ≠ Price**

  Um **produto** descreve a oferta (nome, descrição, imagem). Um **preço** descreve a cobrança (valor, moeda, recorrência). Um produto pode existir sem preço enquanto a cobrança ainda está indefinida; quando há preços, `default_price` aponta qual deles é o padrão para fluxos que partem do produto.
</Info>

## Modelo conceitual

```mermaid theme={}
flowchart LR
  P[Product] -- default_price --> DP[Price mensal]
  P --> Py[Price anual]
  P --> Po[Price promocional]
  DP -. usado em .-> CK[Checkout / Assinatura]
```

| Objeto      | Responsabilidade                           | Campos centrais                                                                      |
| ----------- | ------------------------------------------ | ------------------------------------------------------------------------------------ |
| **Product** | Identidade da oferta no catálogo           | `name`, `description`, `image_url`, `is_tax_applicable`, `default_price`, `metadata` |
| **Price**   | Termos de cobrança vinculados a um produto | `unit_amount`, `currency`, `type`, `recurring`, `tax_behavior`, `is_active`          |

O objeto `price` é detalhado em [Preços](/features/prices). O schema público completo do produto está em [Objeto product](/api-reference/products).

## Anatomia do produto

| Campo               | Tipo             | Descrição                                                                                                |
| ------------------- | ---------------- | -------------------------------------------------------------------------------------------------------- |
| `name`              | `string`         | Nome do produto. Obrigatório.                                                                            |
| `description`       | `string \| null` | Texto livre da oferta.                                                                                   |
| `image_url`         | `string \| null` | Imagem do produto. Sempre uma URL de arquivo Chargefy (veja [Imagem do produto](#imagem-do-produto)).    |
| `is_tax_applicable` | `boolean`        | Indica se o produto é tributável. Default `true`.                                                        |
| `default_price`     | `string \| null` | Preço padrão quando o fluxo parte do produto. No update, esse vínculo é enviado como `default_price_id`. |
| `prices`            | `price[]`        | Preços vinculados ao produto.                                                                            |
| `is_active`         | `boolean`        | `false` tira o produto de novos fluxos sem apagar histórico.                                             |
| `metadata`          | `object`         | Pares chave→valor livres, controlados por você.                                                          |

## Criar um produto

Um produto pode nascer sem preço. Use isso quando o valor ainda será definido por
outro fluxo ou quando o parceiro só precisa cadastrar a oferta no catálogo. Se
você já sabe o valor, envie `prices[]` inline no create ou crie um preço depois.

<Steps>
  <Step title="No Dashboard">
    A criação no painel começa com um **preço base**. Variações adicionais (anual, promocional) são adicionadas depois, na gestão de preços do produto.
  </Step>

  <Step title="Via API">
    O `POST /v1/products` aceita produto puro ou `prices[]` inline. Quando
    `prices[]` tem itens, por padrão o **primeiro** preço da lista vira o
    `default_price`; use `default_price_index` para escolher outro.
  </Step>
</Steps>

<CodeGroup>
  ```bash Sem preço definido theme={}
  curl https://api.chargefy.io/v1/products \
    -H "Authorization: Bearer {{API_KEY}}" \
    -H "Content-Type: application/json" \
    -d '{
      "metadata": {
        "reference_id": "sku_custom"
      },
      "name": "Serviço sob consulta"
    }'
  ```

  ```bash Um preço theme={}
  curl https://api.chargefy.io/v1/products \
    -H "Authorization: Bearer {{API_KEY}}" \
    -H "Content-Type: application/json" \
    -d '{
      "name": "Plano Pro",
      "description": "Acesso completo à plataforma",
      "prices": [
        { "currency": "brl", "unit_amount": 9900, "type": "recurring", "recurring": { "interval": "month" } }
      ]
    }'
  ```

  ```bash Mensal + anual (escolhendo o padrão) theme={}
  curl https://api.chargefy.io/v1/products \
    -H "Authorization: Bearer {{API_KEY}}" \
    -H "Content-Type: application/json" \
    -d '{
      "name": "Plano Pro",
      "prices": [
        { "name": "Mensal", "currency": "brl", "unit_amount": 9900,  "type": "recurring", "recurring": { "interval": "month" } },
        { "name": "Anual",  "currency": "brl", "unit_amount": 99000, "type": "recurring", "recurring": { "interval": "year" } }
      ],
      "default_price_index": 1
    }'
  ```

  ```bash Compra única theme={}
  curl https://api.chargefy.io/v1/products \
    -H "Authorization: Bearer {{API_KEY}}" \
    -H "Content-Type: application/json" \
    -d '{
      "name": "E-book",
      "prices": [
        { "currency": "brl", "unit_amount": 4990, "type": "one_time" }
      ]
    }'
  ```
</CodeGroup>

### Shape do preço inicial

Quando enviado, cada item de `prices[]` segue este contrato:

| Campo          | Regra                                                                                                                                     |
| -------------- | ----------------------------------------------------------------------------------------------------------------------------------------- |
| `currency`     | Código ISO de 3 letras (`brl`). Obrigatório.                                                                                              |
| `unit_amount`  | Valor **em centavos**, inteiro ≥ 0. `0` é permitido em `one_time` e `recurring`.                                                          |
| `type`         | `one_time` (compra única) ou `recurring` (cobrança recorrente). Default `one_time`.                                                       |
| `recurring`    | Obrigatório quando `type = recurring`; proibido em `one_time`. Contém `interval`, `interval_count` e, opcionalmente, `trial_period_days`. |
| `tax_behavior` | `unspecified`, `inclusive` ou `exclusive`. Default `unspecified`.                                                                         |
| `name`         | Rótulo interno opcional do preço (`Mensal`, `Anual Early Bird`).                                                                          |

<Info>
  Preço recorrente com `unit_amount: 0` representa uma assinatura gratuita
  naquela cadência. Assinaturas compostas só por preços zero geram invoices pagas,
  sem tentativa de cobrança.
</Info>

## Imagem do produto

`image_url` nunca aponta para uma URL arbitrária — ela sempre referencia um **arquivo Chargefy** enviado com a finalidade `product_image`. Isso garante que a imagem fica hospedada no CDN da Chargefy e some junto com o histórico se o arquivo for removido.

<Steps>
  <Step title="Envie o arquivo">
    `POST /v1/files` com `purpose=product_image`. A resposta traz a `url` pública do arquivo.
  </Step>

  <Step title="Atrele ao produto">
    Passe essa `url` em `image_url` no create ou update do produto.
  </Step>
</Steps>

<Note>
  Passar uma URL externa em `image_url` retorna `400`. O arquivo precisa ser público, pertencer à sua organização e ter `purpose=product_image`. Veja [Files](/api-reference/files).
</Note>

## Múltiplos preços no mesmo produto

O padrão recomendado para variações de cobrança é **um produto com vários preços**, em vez de produtos duplicados.

Casos comuns:

* mensal + anual no mesmo plano
* compra única + versão recorrente do mesmo item
* preço padrão + preço promocional arquivado depois
* preços com `name` interno como `Mensal`, `Anual Early Bird` ou `Equipe 10+`

### Definir o preço padrão

O `default_price` é o preço que os fluxos usam quando partem do produto. Há três formas de defini-lo:

| Quando                     | Como                                                                                                                                 |
| -------------------------- | ------------------------------------------------------------------------------------------------------------------------------------ |
| Na criação do produto      | `default_price_index` aponta o índice do preço em `prices[]` (default `0`) quando `prices[]` tem itens.                              |
| Ao adicionar um preço novo | `POST /v1/prices` com `product_id` e `set_as_default: true`.                                                                         |
| A qualquer momento         | `POST /v1/products/{id}` com `default_price_id` apontando um preço **daquele** produto. A resposta pública vem como `default_price`. |

Para adicionar um preço a um produto existente, use [Criar preço](/api-reference/prices/create) com `product_id`.

## Atualizar um produto

O update de produto é **merge**: você envia só os campos que mudam. Editáveis com segurança:

| Campo               | Observação                                                                                                    |
| ------------------- | ------------------------------------------------------------------------------------------------------------- |
| `name`              | Não pode ficar vazio.                                                                                         |
| `description`       | Envie `null` para limpar.                                                                                     |
| `image_url`         | Aceita uma URL de arquivo `product_image` ou `null`.                                                          |
| `is_tax_applicable` | Boolean.                                                                                                      |
| `is_active`         | `false` arquiva (veja abaixo).                                                                                |
| `default_price_id`  | Campo de input para trocar o preço padrão; deve pertencer ao próprio produto. A resposta usa `default_price`. |
| `metadata`          | Substitui o objeto inteiro.                                                                                   |

<Tip>
  Valor, moeda e cadência de um preço **não** se editam pelo produto — nem pelo próprio preço. Eles são imutáveis. Para mudar a cobrança, crie um preço novo e arquive o antigo.
</Tip>

## Arquivar e remover

`DELETE /v1/products/{id}` expressa "tirar de circulação". O efeito depende do uso:

<AccordionGroup>
  <Accordion title="Produto nunca usado">
    É removido de fato. A resposta é `{ "id": "prod_123", "object": "product", "deleted": true }`.
  </Accordion>

  <Accordion title="Produto já referenciado por vendas/assinaturas">
    Não pode sumir sem quebrar histórico, então é **desativado** (`is_active = false`) e a resposta é o produto completo atualizado. Ele sai de novos fluxos de compra, mas vendas, assinaturas e auditoria permanecem íntegras.
  </Accordion>
</AccordionGroup>

Você também pode arquivar diretamente com `POST /v1/products/{id}` enviando `is_active: false`, sem tentar a remoção.

## Impostos

A modelagem separa o tema em dois níveis:

* `products.is_tax_applicable` — o produto é tributável?
* `prices.tax_behavior` — como o imposto se relaciona com o valor do preço?

| `tax_behavior` | Significado                                   |
| -------------- | --------------------------------------------- |
| `unspecified`  | Sem comportamento fiscal declarado (default). |
| `inclusive`    | O imposto já está embutido em `unit_amount`.  |
| `exclusive`    | O imposto é somado por cima de `unit_amount`. |

<Note>
  Hoje `tax_behavior` é **declarativo**: faz parte do contrato público do preço, mas não altera sozinho o valor final cobrado.
</Note>

## Quantidade

Um `price` é sempre **unitário**. A multiplicação acontece no checkout, pela quantidade:

```text theme={}
Total da linha = price.unit_amount × quantidade
```

Se você vende por assento, licença ou unidade, o caminho é esse: preço unitário no catálogo + quantidade no checkout.

## Próximos passos

<CardGroup cols={2}>
  <Card title="Objeto product" icon="cube" href="/api-reference/products">
    Schema público completo e campos retornados.
  </Card>

  <Card title="Preços" icon="tag" href="/features/prices">
    Como modelar valor, moeda e recorrência.
  </Card>

  <Card title="Criar produto (API)" icon="code" href="/api-reference/products/create">
    Contrato do `POST /v1/products` com preços opcionais.
  </Card>

  <Card title="Checkout Sessions" icon="cart-shopping" href="/api-reference/checkout-sessions">
    Como o produto vira uma cobrança.
  </Card>
</CardGroup>
