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

# Descontos

> Modele regras de desconto e cupons resgatáveis e aplique-os no checkout e em links de pagamento.

Um **desconto** (`discount`) é a **regra econômica** que abate valor de uma cobrança — um percentual ou um valor fixo, com janela de validade, limite de uso e escopo de produtos. Ele habilita campanhas promocionais, cupons digitáveis no checkout e abatimentos automáticos em links de pagamento, sempre com um registro auditável de cada aplicação.

<Info>
  **Discount ≠ Discount code**

  Um **desconto** descreve *quanto* abater (`percentage` ou `fixed`), por *quanto tempo* e *onde* se aplica. Um **código de desconto** (`discount_code`) é a **string que o comprador digita** para resgatar aquele desconto. Um desconto pode existir sem código (aplicado automaticamente via `discount_id`) e pode ter **vários** códigos apontando para ele.
</Info>

## Modelo conceitual

```mermaid theme={}
flowchart LR
  D[Discount<br/>regra econômica] -->|discount_id| AUTO[Aplicação automática]
  D --> C1[Discount code BLACK20]
  D --> C2[Discount code VIP10]
  C1 -. comprador digita .-> CK[Checkout / Link de pagamento]
  AUTO -. embutido no fluxo .-> CK
  CK --> R[Discount redemption<br/>aplicação concreta + snapshot]
```

| Objeto            | Responsabilidade                                          | Campos centrais                                                                                                                                |
| ----------------- | --------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- |
| **Discount**      | A regra: tipo, valor, duração, validade, limite e escopo  | `type`, `amount_off`, `currency`, `percent_off_basis_points`, `duration`, `applies_to`, `max_redemptions`                                      |
| **Discount code** | A string resgatável atrelada a um desconto                | `code`, `discount_id`, `customer`, `first_time_transaction`, `minimum_amount`, `expires_at`, `max_redemptions`, `max_redemptions_per_customer` |
| **Redemption**    | A aplicação concreta numa cobrança, com snapshot imutável | registrada internamente                                                                                                                        |

O schema público completo está em [Objeto discount](/api-reference/discounts) e [Objeto discount\_code](/api-reference/discount-codes). A **redemption** é um registro interno de auditoria — ela guarda um snapshot da regra e do código no momento da cobrança e não é um recurso editável via API.

## Anatomia do desconto

| Campo                      | Tipo              | Descrição                                                                                 |
| -------------------------- | ----------------- | ----------------------------------------------------------------------------------------- |
| `name`                     | `string`          | Nome do desconto. Obrigatório.                                                            |
| `type`                     | `string`          | `percentage` ou `fixed`. Obrigatório.                                                     |
| `percent_off_basis_points` | `integer \| null` | Percentual em basis points (1 a 10000, onde `10000 = 100%`). Presente só em `percentage`. |
| `amount_off`               | `integer \| null` | Valor fixo **em centavos**. Presente só em `fixed`.                                       |
| `currency`                 | `string \| null`  | Código ISO de 3 letras minúsculas. Presente só em `fixed`.                                |
| `duration`                 | `string`          | `once`, `repeating` ou `forever`. Default `once`.                                         |
| `duration_in_months`       | `integer \| null` | Número de meses. Obrigatório quando `duration=repeating`.                                 |
| `applies_to`               | `object`          | `{ "products": [...] }`. Array vazio aplica a **todos** os produtos.                      |
| `starts_at`                | `string \| null`  | A partir de quando passa a valer (ISO 8601).                                              |
| `expires_at`               | `string \| null`  | Quando expira (ISO 8601).                                                                 |
| `max_redemptions`          | `integer \| null` | Limite **total** de aplicações. `null` é ilimitado.                                       |
| `redemptions_count`        | `integer`         | Quantas vezes já foi aplicado.                                                            |
| `is_active`                | `boolean`         | `false` tira de novos fluxos sem apagar histórico.                                        |
| `valid`                    | `boolean`         | Resumo: `true` quando está ativo, dentro da janela e abaixo do limite.                    |
| `metadata`                 | `object`          | Pares chave→valor livres, controlados por você.                                           |

### Tipo: percentual ou valor fixo

São mutuamente exclusivos — a forma define quais campos o objeto carrega.

| Tipo         | Campos obrigatórios        | Significado                                                                  |
| ------------ | -------------------------- | ---------------------------------------------------------------------------- |
| `percentage` | `percent_off_basis_points` | Abate uma porcentagem do subtotal. `2000` = 20%, `500` = 5%, `10000` = 100%. |
| `fixed`      | `amount_off` + `currency`  | Abate um valor fixo em centavos. `5000` = R\$ 50,00 em `brl`.                |

<Note>
  O abatimento de um desconto `fixed` nunca passa do subtotal — um `amount_off`
  de `5000` aplicado a um subtotal de `3000` abate apenas `3000`, e o total não
  fica negativo.
</Note>

### Duração

A duração descreve por quanto tempo o desconto acompanha uma cobrança recorrente (assinatura). Em cobrança avulsa, só a primeira aplicação importa.

| `duration`  | Significado                                                                     |
| ----------- | ------------------------------------------------------------------------------- |
| `once`      | Aplica uma única vez (default).                                                 |
| `repeating` | Aplica por `duration_in_months` meses seguidos. Exige `duration_in_months > 0`. |
| `forever`   | Aplica em todas as cobranças enquanto a assinatura existir.                     |

### Limites e validade

| Mecanismo         | Onde                                   | Efeito                                                                               |
| ----------------- | -------------------------------------- | ------------------------------------------------------------------------------------ |
| Janela            | `starts_at` / `expires_at` no desconto | Fora da janela, o desconto é recusado. `starts_at` deve ser anterior a `expires_at`. |
| Limite total      | `max_redemptions` no desconto          | Quando `redemptions_count` atinge o limite, novas aplicações são recusadas.          |
| Escopo de produto | `applies_to.products`                  | Só abate o subtotal das linhas dos produtos listados. Vazio = todos.                 |

<Note>
  Cada cobrança (checkout, link, assinatura) recebe **no máximo um** desconto —
  a mesma cobrança não acumula dois.
</Note>

## Anatomia do código de desconto

O código herda a regra econômica do desconto pai (`discount_id`) e adiciona suas próprias condições de resgate.

| Campo                          | Tipo              | Descrição                                                                                                                   |
| ------------------------------ | ----------------- | --------------------------------------------------------------------------------------------------------------------------- |
| `discount_id`                  | `string`          | Desconto pai (`disc_*`). Obrigatório.                                                                                       |
| `code`                         | `string`          | A string digitável. Letras, números e hífens; normalizada para maiúsculas. Se omitida na criação, é gerada automaticamente. |
| `customer`                     | `string \| null`  | Cliente específico que pode resgatar o código. `null` permite qualquer cliente.                                             |
| `first_time_transaction`       | `boolean`         | Quando `true`, o código só vale para clientes sem atividade de cobrança anterior.                                           |
| `minimum_amount`               | `integer \| null` | Valor mínimo da compra **em centavos** para o código valer.                                                                 |
| `minimum_amount_currency`      | `string \| null`  | Moeda do valor mínimo. Obrigatória quando `minimum_amount` é enviado.                                                       |
| `expires_at`                   | `string \| null`  | Expiração própria do código (não pode ser posterior à do desconto).                                                         |
| `max_redemptions`              | `integer \| null` | Limite próprio do código (não pode exceder o do desconto).                                                                  |
| `max_redemptions_per_customer` | `integer \| null` | Limite de resgates por cliente para este código.                                                                            |
| `redemptions_count`            | `integer`         | Quantas vezes este código foi resgatado.                                                                                    |
| `is_active`                    | `boolean`         | `false` desativa o código sem mexer no desconto.                                                                            |
| `valid`                        | `boolean`         | `true` quando o código **e** o desconto pai estão válidos.                                                                  |
| `metadata`                     | `object`          | Pares chave→valor livres.                                                                                                   |

<Note>
  Um código público ativo é único por organização. Códigos restritos a clientes
  podem repetir a mesma string para clientes diferentes; um código público ativo
  bloqueia reutilizar essa string para qualquer cliente.
</Note>

## Criar um desconto

`POST /v1/discounts` cria a regra. Para um cupom digitável, crie em seguida um `discount_code` apontando para o `disc_*`.

<CodeGroup>
  ```bash Percentual theme={}
  curl https://api.chargefy.io/v1/discounts \
    -H "Authorization: Bearer {{API_KEY}}" \
    -H "Content-Type: application/json" \
    -d '{
      "name": "Promo 20%",
      "type": "percentage",
      "percent_off_basis_points": 2000,
      "duration": "once",
      "max_redemptions": 500
    }'
  ```

  ```bash Valor fixo theme={}
  curl https://api.chargefy.io/v1/discounts \
    -H "Authorization: Bearer {{API_KEY}}" \
    -H "Content-Type: application/json" \
    -d '{
      "name": "R$ 50 OFF",
      "type": "fixed",
      "amount_off": 5000,
      "currency": "brl"
    }'
  ```

  ```bash Recorrente por 3 meses theme={}
  curl https://api.chargefy.io/v1/discounts \
    -H "Authorization: Bearer {{API_KEY}}" \
    -H "Content-Type: application/json" \
    -d '{
      "name": "3 meses com 10%",
      "type": "percentage",
      "percent_off_basis_points": 1000,
      "duration": "repeating",
      "duration_in_months": 3
    }'
  ```

  ```bash Escopo por produto theme={}
  curl https://api.chargefy.io/v1/discounts \
    -H "Authorization: Bearer {{API_KEY}}" \
    -H "Content-Type: application/json" \
    -d '{
      "name": "Só no Plano Pro",
      "type": "percentage",
      "percent_off_basis_points": 1500,
      "applies_to": { "products": ["prod_123"] }
    }'
  ```
</CodeGroup>

O contrato completo do body, com erros e variantes, está em [Criar desconto](/api-reference/discounts/create).

## Criar um código de desconto

Com o desconto criado, gere a string que o comprador vai digitar. O `code` é opcional — quando omitido, a Chargefy gera um.

<CodeGroup>
  ```bash Código fixo theme={}
  curl https://api.chargefy.io/v1/discount-codes \
    -H "Authorization: Bearer {{API_KEY}}" \
    -H "Content-Type: application/json" \
    -d '{
      "discount_id": "disc_123",
      "code": "PROMO20",
      "max_redemptions": 500
    }'
  ```

  ```bash Com valor mínimo de compra theme={}
  curl https://api.chargefy.io/v1/discount-codes \
    -H "Authorization: Bearer {{API_KEY}}" \
    -H "Content-Type: application/json" \
    -d '{
      "discount_id": "disc_123",
      "code": "FRETE100",
      "minimum_amount": 10000,
      "minimum_amount_currency": "brl"
    }'
  ```

  ```bash Restrito a um cliente e primeira compra theme={}
  curl https://api.chargefy.io/v1/discount-codes \
    -H "Authorization: Bearer {{API_KEY}}" \
    -H "Content-Type: application/json" \
    -d '{
      "discount_id": "disc_123",
      "code": "BEMVINDO",
      "customer": "cus_123",
      "first_time_transaction": true,
      "max_redemptions_per_customer": 1
    }'
  ```

  ```bash Código gerado automaticamente theme={}
  curl https://api.chargefy.io/v1/discount-codes \
    -H "Authorization: Bearer {{API_KEY}}" \
    -H "Content-Type: application/json" \
    -d '{ "discount_id": "disc_123" }'
  ```
</CodeGroup>

O contrato completo está em [Criar código de desconto](/api-reference/discount-codes/create).

## Como o desconto é aplicado

Há dois caminhos, e eles podem coexistir no mesmo fluxo de cobrança. Ambos valem para [Checkout Sessions](/features/checkout-sessions) e [Links de pagamento](/features/payment-links).

<Steps>
  <Step title="Cupom digitável (discount_code)">
    O comprador digita o código no checkout. A Chargefy valida janela, limite,
    restrições de cliente, valor mínimo e escopo de produto e calcula o
    abatimento. Controle isso por `allow_discount_codes` no checkout/link
    (default `true`); `false` esconde o campo de cupom.
  </Step>

  <Step title="Desconto automático (discount_id)">
    Você atrela um `discount_id` direto ao checkout ou link de pagamento. O
    abatimento é aplicado sem o comprador digitar nada — útil para campanhas
    dirigidas e links promocionais.
  </Step>
</Steps>

| Campo no checkout/link | Tipo             | Efeito                                                      |
| ---------------------- | ---------------- | ----------------------------------------------------------- |
| `allow_discount_codes` | `boolean`        | Habilita o campo de cupom para o comprador. Default `true`. |
| `discount_id`          | `string \| null` | Desconto aplicado automaticamente, sem código digitado.     |

<Tip>
  O cálculo é sobre o **subtotal**: `amount_total = amount_subtotal −
      amount_discount`, com `amount_discount` nunca maior que o subtotal. O
  comprador pode pré-visualizar o abatimento de um cupom antes de confirmar — a
  sessão expõe o desconto calculado.
</Tip>

## Casos de uso

<AccordionGroup>
  <Accordion title="Cupom promocional público">
    Um desconto `percentage` (ex.: 20%) com um `discount_code` divulgado em
    campanha (`PROMO20`). Limite o alcance com `max_redemptions` e a janela com
    `starts_at`/`expires_at`. Quem digitar o cupom no checkout recebe o
    abatimento.
  </Accordion>

  <Accordion title="Primeiros meses com desconto na assinatura">
    Um desconto `percentage` com `duration=once` (só a próxima cobrança),
    `duration=repeating` + `duration_in_months` para abater as invoices dentro
    desse período, ou `duration=forever` para acompanhar a assinatura por toda a
    vida dela.
  </Accordion>

  <Accordion title="Abatimento fixo de campanha">
    Um desconto `fixed` (ex.: `amount_off: 5000`, `currency: "brl"` = R$ 50).
            Bom para "R$ 50 OFF acima de R\$ 100" combinando o código com
    `minimum_amount: 10000` e `minimum_amount_currency: "brl"`.
  </Accordion>

  <Accordion title="Link de pagamento com cupom automático">
    Crie o desconto e atrele o `disc_*` ao link via `discount_id`. Todo mundo
    que abrir o link já recebe o abatimento, sem digitar código. Para deixar o
    comprador também aplicar cupons próprios, mantenha `allow_discount_codes:
            true`.
  </Accordion>

  <Accordion title="Cupom restrito a um produto">
    Use `applies_to.products` com os `prod_*` elegíveis. O desconto só vale
    quando o checkout contém pelo menos um produto da lista; caso contrário é
    recusado.
  </Accordion>
</AccordionGroup>

## Atualizar

O update é **merge** — você envia só os campos que mudam.

<Warning>
  Depois que um desconto tem ao menos uma aplicação (`redemptions_count > 0`), os **campos econômicos** ficam congelados: `type`, `amount_off`, `currency`, `percent_off_basis_points`, `duration` e `duration_in_months` não podem mais mudar (retorna `409`). Para mudar o valor, crie um desconto novo e desative o antigo. O mesmo vale para os campos de valor de um código (`code`, `discount_id`, `minimum_amount`, `minimum_amount_currency`).
</Warning>

Continuam editáveis a qualquer momento: `name`, `applies_to`, `starts_at`, `expires_at`, `max_redemptions` (nunca abaixo de `redemptions_count`), `is_active` e `metadata`.

## Desativar e remover

`DELETE /v1/discounts/{id}` e `DELETE /v1/discount-codes/{id}` expressam "tirar de circulação". O efeito depende do uso:

<AccordionGroup>
  <Accordion title="Nunca aplicado">
    É removido de fato. A resposta é `{ "id": "disc_123", "object": "discount", "deleted": true }`.
  </Accordion>

  <Accordion title="Já aplicado em alguma cobrança">
    Não pode sumir sem quebrar a auditoria, então é **desativado** (`is_active = false`) e a resposta é o objeto completo atualizado. Ele sai de novos fluxos, mas as aplicações passadas e seus snapshots permanecem íntegros.
  </Accordion>
</AccordionGroup>

Você também pode desativar diretamente com `POST /v1/discounts/{id}` enviando `is_active: false`.

## Próximos passos

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

  <Card title="Checkout Sessions" icon="cart-shopping" href="/features/checkout-sessions">
    Como cupom digitável e desconto automático entram numa cobrança.
  </Card>

  <Card title="Links de pagamento" icon="link" href="/features/payment-links">
    Atrelar um desconto ou habilitar cupons num link.
  </Card>

  <Card title="Assinaturas" icon="rotate" href="/features/subscriptions">
    Como `duration` rege o abatimento ao longo dos ciclos.
  </Card>

  <Card title="Preços" icon="tag" href="/features/prices">
    O valor que o desconto abate vem do preço.
  </Card>

  <Card title="Criar desconto (API)" icon="code" href="/api-reference/discounts/create">
    Contrato do `POST /v1/discounts`.
  </Card>
</CardGroup>
