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.
Discount ≠ Discount codeUm 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.Modelo conceitual
| 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 |
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. |
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.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. |
Cada cobrança (checkout, link, assinatura) recebe no máximo um desconto —
a mesma cobrança não acumula dois.
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. |
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.
Criar um desconto
POST /v1/discounts cria a regra. Para um cupom digitável, crie em seguida um discount_code apontando para o disc_*.
Criar um código de desconto
Com o desconto criado, gere a string que o comprador vai digitar. Ocode é opcional — quando omitido, a Chargefy gera um.
Como o desconto é aplicado
Há dois caminhos, e eles podem coexistir no mesmo fluxo de cobrança. Ambos valem para Checkout Sessions e Links de pagamento.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.| 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. |
Casos de uso
Cupom promocional público
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.Primeiros meses com desconto na assinatura
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.Abatimento fixo de campanha
Abatimento fixo de campanha
Um desconto
fixed (ex.: amount_off: 5000, currency: "brl" = R 50 OFF acima de R$ 100” combinando o código com
minimum_amount: 10000 e minimum_amount_currency: "brl".Link de pagamento com cupom automático
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.Cupom restrito a um produto
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.Atualizar
O update é merge — você envia só os campos que mudam. 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:
Nunca aplicado
Nunca aplicado
É removido de fato. A resposta é
{ "id": "disc_123", "object": "discount", "deleted": true }.Já aplicado em alguma cobrança
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.POST /v1/discounts/{id} enviando is_active: false.
Próximos passos
Objeto discount
Schema público completo e campos retornados.
Checkout Sessions
Como cupom digitável e desconto automático entram numa cobrança.
Links de pagamento
Atrelar um desconto ou habilitar cupons num link.
Assinaturas
Como
duration rege o abatimento ao longo dos ciclos.Preços
O valor que o desconto abate vem do preço.
Criar desconto (API)
Contrato do
POST /v1/discounts.
