(09) Receber pagamentos
Cupões
Descontos em percentagem ou valor fixo, aplicados pela loja ou escritos pelo comprador no checkout, e nas subscrições.
O que é um cupão
Um cupão é um código que dá um desconto: uma percentagem (de 1 a 99) ou um valor fixo numa moeda, que só vale nessa moeda. Cria-se no painel, em Cupões, ou pela API, e é de um modo: um cupão de teste não vale em produção.
- O código é único por comerciante e por modo, com letras, números,
-e_, e guarda-se em maiúsculas. - Tem, se quiseres, um limite de usos (
max_redemptions) e uma data de fim (expires_at). - O desconto não muda depois de criado. Mudam o nome, o limite, a data de fim e o ativo; um desconto novo é um cupão novo. Um cupão não se apaga: desativa-se, e quem já o tem fica com ele.
- Em kwanzas, o desconto de uma percentagem arredonda para baixo, ao kwanza inteiro. Um desconto que dê zero, ou que leve o valor todo, é recusado.
curl -s "$VIBRA_API_URL/v1/coupons" \
-H "Authorization: Bearer $VIBRA_SECRET_KEY" \
-H "Idempotency-Key: cupao-bemvindo10" \
-H "Content-Type: application/json" \
-d '{"code": "BEMVINDO10", "name": "Boas-vindas", "percent_off": 10, "duration": "repeating", "duration_cycles": 3, "max_redemptions": 100}'{
"id": "cpn_test_8Kq2Lm4Rt8Vx1Zb6Nc3Kd0Ab",
"object": "coupon",
"mode": "test",
"code": "BEMVINDO10",
"name": "Boas-vindas",
"percent_off": 10,
"amount_off": null,
"duration": "repeating",
"duration_cycles": 3,
"max_redemptions": 100,
"times_redeemed": 0,
"expires_at": null,
"active": true,
"valid": true,
"metadata": {},
"created_at": "2026-11-29T08:55:00Z",
"updated_at": "2026-11-29T08:55:00Z"
}GET /v1/coupons lista-os (com ?code= para procurar um), GET /v1/coupons/cpn_... lê um, e PATCH /v1/coupons/cpn_... muda o que se pode mudar. Um código repetido dá 409 codigo_repetido.
Aplicar um cupão
| Como | O que se faz |
|---|---|
| A tua loja aplica-o | coupon na sessão, com o código (ou o cpn_...). Um cupão que não serve (não existe, desativado, expirado, esgotado, noutra moeda, ou que não desconta neste valor) dá 422 cupao_invalido. |
| O comprador escreve-o | allow_promotion_codes: true na sessão, ou a caixa Aceitar códigos de desconto num link de cobrança. O checkout mostra o campo do código, com o preço riscado e o total novo. |
curl -s "$VIBRA_API_URL/v1/checkout/sessions" \
-H "Authorization: Bearer $VIBRA_SECRET_KEY" \
-H "Idempotency-Key: pedido-1042" \
-H "Content-Type: application/json" \
-d '{"amount": 1500000, "currency": "AOA", "description": "Vestido de capulana", "coupon": "BEMVINDO10"}'"amount": {"amount": 1500000, "currency": "AOA"},
"discount": {
"coupon": {"id": "cpn_test_8Kq2...", "code": "BEMVINDO10", "name": "Boas-vindas", "percent_off": 10,
"amount_off": null, "duration": "repeating", "duration_cycles": 3},
"amount": {"amount": 150000, "currency": "AOA"}
},
"allow_promotion_codes": falseO amount da sessão continua a ser o preço; o comprador paga amount menos discount.amount. Um pagamento leva um cupão só, e os dois modos não vão juntos.
// Go
cupao, err := cliente.CreateCoupon(ctx, &vibra.CouponParams{
Code: "BEMVINDO10", PercentOff: 10, Duration: vibra.CouponRepeating, DurationCycles: 3,
})
sessao, err := cliente.CreateCheckoutSession(ctx, &vibra.CheckoutSessionParams{
Amount: 1500000, Currency: vibra.AOA, Description: "Vestido", AllowPromotionCodes: true,
})
// JavaScript
const cupao = await vibra.createCoupon({ code: "BEMVINDO10", percent_off: 10, duration: "repeating", duration_cycles: 3 });
const sessao = await vibra.createCheckoutSession({ amount: 1500000n, currency: "AOA", description: "Vestido", allow_promotion_codes: true });O dinheiro, a taxa e o limite
- O pagamento nasce com o valor descontado. O
payment.succeededtraz esse valor emamount, odiscountcom o cupão, e afee, que é sobre o valor pago, depois do desconto. - O recibo mostra o preço, a linha do desconto e o código.
- O limite conta as sessões pagas com o cupão e as abertas que ainda se podem pagar: dois compradores com o último uso, um fica com ele e o outro é recusado. Uma sessão que expira devolve o uso.
times_redeemedsão as pagas.
Numa subscrição
| duration | O desconto vale |
|---|---|
once | No primeiro ciclo. As renovações cobram o preço cheio. |
repeating | Nos primeiros duration_cycles ciclos (de 2 a 1000), contando com o primeiro, e a seguir o preço cheio. |
forever | Em todos os ciclos. |
A subscrição guarda o cupão em discount (coupon, amount e cycles, nulo quando são todos), e vale o que o comprador aceitou mesmo que depois desatives o cupão. Num pagamento único, qualquer cupão vale uma vez. Um cupão não vai com o first_cycle_amount de um plano.
Subscrições semanais com cartão
O cartão renova-se sozinho no gateway, que conta os descontos repetidos em meses. Por isso, uma subscrição semanal que se pode pagar com cartão recusa um cupão repeating; o once e o forever servem.