> ## 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.

# Create a Product

> Cria um produto.

Cria um recurso `product`. Você pode criar o produto sem preço e definir os
valores depois via [`POST /v1/prices`](/api-reference/prices/create), ou enviar
`prices[]` inline no mesmo request. Quando `prices[]` tem itens, o primeiro preço
do array vira `default_price`, ou use `default_price_index` para escolher outro.

Use `metadata` para correlacionar o produto com IDs do seu sistema. Qualquer
chave funciona (ex.: `sku`, `reference_id`); o objeto inteiro é retornado em
todos os webhooks.

## Autenticação

A API key da própria organização atua diretamente. A API key de plataforma exige o
header `Organization: <organization_id>` apontando para uma organização
conectada ativa.

## Attributes

<ParamField body="default_price_index" type="integer" default="0">
  Índice do preço em `prices[]` que vira `default_price`. Só é aceito quando
  `prices[]` tem pelo menos um item.
</ParamField>

<ParamField body="description" type="string">
  Descrição livre. Envie `null` para deixar vazio.
</ParamField>

<ParamField body="image_url" type="string">
  URL retornada por [`POST /v1/files`](/api-reference/files/create) com
  `purpose=product_image`. Envie `null` para deixar vazio. URLs externas não
  são aceitas.
</ParamField>

<ParamField body="is_tax_applicable" type="boolean" default="true">
  Indica se o produto é tributável.
</ParamField>

<ParamField body="metadata" type="object">
  Objeto livre `string → string` para correlacionar com o seu sistema. Padrão
  `{}`.
</ParamField>

<ParamField body="name" type="string" required>
  Nome do produto exibido em checkout, faturas e webhooks.
</ParamField>

<ParamField body="prices" type="array">
  Lista opcional de preços inline. Cada item segue o mesmo shape de
  [`POST /v1/prices`](/api-reference/prices/create#body) (sem `product_id`).
  Quando omitido ou vazio, o produto nasce com `default_price: null` e
  `prices: []`.

  <Expandable title="price">
    <ParamField body="currency" type="string" required>
      Código ISO 4217 em minúsculas. Ex.: `brl`, `usd`.
    </ParamField>

    <ParamField body="recurring" type="object">
      Obrigatório quando `type` é `recurring`.

      <Expandable title="Campos de recurring">
        <ParamField body="interval" type="string" required>
          Valores: `day`, `week`, `month` ou `year`.
        </ParamField>

        <ParamField body="interval_count" type="integer" default="1">
          Quantidade de intervalos entre cobranças.
        </ParamField>

        <ParamField body="trial_period_days" type="integer">
          Trial padrão em dias para assinaturas criadas a partir deste preço.
        </ParamField>
      </Expandable>
    </ParamField>

    <ParamField body="is_active" type="boolean" default="true">
      Se o preço fica disponível para novas vendas.
    </ParamField>

    <ParamField body="metadata" type="object">
      Metadata livre do preço. Padrão `{}`.
    </ParamField>

    <ParamField body="name" type="string">
      Rótulo interno do preço. Envie `null` para deixar vazio.
    </ParamField>

    <ParamField body="tax_behavior" type="string" default="unspecified">
      `unspecified`, `inclusive` ou `exclusive`.
    </ParamField>

    <ParamField body="type" type="string" default="one_time">
      `one_time` ou `recurring`.
    </ParamField>

    <ParamField body="unit_amount" type="integer" required>
      Valor unitário em minor units (centavos). `0` é válido para `one_time` e
      `recurring`.
    </ParamField>
  </Expandable>
</ParamField>

<RequestExample>
  ```bash Produto sem preço theme={}
  curl -X POST "https://api.chargefy.io/v1/products" \
    -H "Authorization: Bearer {{API_KEY}}" \
    -H "Content-Type: application/json" \
    -d '{
      "name": "Serviço sob consulta"
    }'
  ```

  ```bash Produto com preço inicial theme={}
  curl -X POST "https://api.chargefy.io/v1/products" \
    -H "Authorization: Bearer {{API_KEY}}" \
    -H "Content-Type: application/json" \
    -d '{
      "name": "Plano Pro",
      "prices": [
        {
          "currency": "brl",
          "unit_amount": 9990
        }
      ]
    }'
  ```

  ```bash Produto com assinatura gratuita theme={}
  curl -X POST "https://api.chargefy.io/v1/products" \
    -H "Authorization: Bearer {{API_KEY}}" \
    -H "Content-Type: application/json" \
    -d '{
      "name": "Programa beta",
      "prices": [
        {
          "currency": "brl",
          "name": "Mensal gratuito",
          "recurring": {
            "interval": "month"
          },
          "type": "recurring",
          "unit_amount": 0
        }
      ]
    }'
  ```
</RequestExample>

## Resposta

`200 OK` com o objeto `product` completo. Todo campo declarado pelo DTO público
é sempre retornado; vazio é `null`, `{}` ou `[]`.

| Campo               | Tipo             | Observação                                                                                                     |
| ------------------- | ---------------- | -------------------------------------------------------------------------------------------------------------- |
| `id`                | `string`         | ID do produto (`prod_*`)                                                                                       |
| `object`            | `string`         | Sempre `"product"`                                                                                             |
| `name`              | `string`         | —                                                                                                              |
| `description`       | `string \| null` | —                                                                                                              |
| `image_url`         | `string \| null` | —                                                                                                              |
| `is_tax_applicable` | `boolean`        | —                                                                                                              |
| `default_price`     | `string \| null` | Aponta para um item de `prices[]`, ou `null` quando o produto ainda não tem preço padrão                       |
| `is_active`         | `boolean`        | `false` quando arquivado                                                                                       |
| `livemode`          | `boolean`        | `true` em produção; `false` em ambiente de teste                                                               |
| `metadata`          | `object`         | Eco do `metadata` enviado                                                                                      |
| `created_at`        | `string`         | ISO 8601                                                                                                       |
| `updated_at`        | `string \| null` | ISO 8601                                                                                                       |
| `prices`            | `array`          | Lista de objetos `price` completos (mesmo shape de [`GET /v1/prices/:id`](/api-reference/prices/get#resposta)) |

<ResponseExample>
  ```json 200 theme={}
  {
    "id": "prod_123",
    "object": "product",
    "created_at": "2026-05-16T14:09:27Z",
    "default_price": null,
    "description": null,
    "image_url": null,
    "is_active": true,
    "is_tax_applicable": true,
    "livemode": true,
    "metadata": {
      "reference_id": "sku_custom"
    },
    "name": "Serviço sob consulta",
    "prices": [],
    "updated_at": null
  }
  ```
</ResponseExample>

## Erros comuns

| Status | `code`            | Quando ocorre                                                                                                                                                                                                                                           |
| ------ | ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `400`  | `invalid_request` | `name` ausente; `prices` não-array; `metadata` não-objeto; `default_price_index` sem `prices[]` ou fora do range                                                                                                                                        |
| `400`  | `invalid_request` | `image_url` não aponta para um `file` ativo de `purpose=product_image` da organização                                                                                                                                                                   |
| `400`  | `invalid_request` | Em `prices[N]`: `currency` não é ISO de 3 letras; `unit_amount` negativo ou ausente; `type` inválido; `recurring.interval` ausente para `recurring`; `recurring.interval_count` não-inteiro ou \< 1; `recurring` em `one_time`; `tax_behavior` inválido |

## Webhook

A criação dispara [`product.created`](/api-reference/webhooks/product.created)
com o `product` completo em `data.object`. Cada preço inline também dispara
[`price.created`](/api-reference/webhooks/price.created).
