Descontos e cupons
Aplicar cupom
Aplica um cupom a uma assinatura que já está ativa. Serve para desconto recorrente (percentual ou em reais por algumas cobranças) e para período grátis — por exemplo, "indicou um amigo, ganhou um mês".
/v1/subscriptions/:subscriptionId/couponshttps://api.validapay.com.brhttps://sandbox.validapay.com.brComo usar para indicação ou cortesia: crie uma vez um cupom do tipo EXTRA_PERIOD (em Cupons), por exemplo INDICACAO com 1 mês. Quando o cliente ganhar o benefício, aplique esse código na assinatura dele.
A partir de quando vale (applyTo):
NEXT_CYCLE(padrão): a cobrança atual não muda; o cupom vale a partir da próxima. No período grátis, a próxima cobrança é adiada.CURRENT_CYCLE: vale já para a cobrança atual.- Se ela ainda não foi gerada, o cupom entra quando for gerada.
- Se já foi gerada por Pix ou boleto e está em aberto, ela é reemitida. No desconto, com o valor novo; no período grátis, com o mesmo valor e o vencimento adiado pelo período.
- Se ela está vencida: no desconto, envie um
dueDateposterior a hoje, que vira o vencimento da nova cobrança. No período grátis, não enviedueDate: a nova cobrança vence hoje mais o período do cupom.
Regras:
- Uma assinatura tem um cupom por vez. Se já houver cupom em vigor, a resposta é
COUPON_ALREADY_ACTIVE; aplique o próximo quando ele terminar. - Cupom e desconto recorrente (Aplicar desconto em uma cobrança com
cycles) não valem juntos. Com desconto recorrente em vigor, encerre-o antes de aplicar o cupom. - Valem as mesmas regras do checkout: validade, limite de usos, produtos permitidos e primeiro uso.
CURRENT_CYCLEsó reemite cobrança de Pix ou boleto. Se a cobrança atual é de cartão e já foi gerada, ou se já foi paga, useNEXT_CYCLE.- Um desconto manual já lançado na cobrança atual impede o cupom de desconto com
CURRENT_CYCLE. Remova o desconto ou useNEXT_CYCLE. dueDatesó vale quando a cobrança atual é reemitida com desconto. Com cupom de período grátis, ou com a cobrança atual ainda não emitida, a resposta éDUE_DATE_NOT_APPLICABLE.- No boleto, o boleto antigo não é cancelado ao reemitir, a menos que você envie
cancelOpenBoleto: true. - No Pix Automático, o valor de um débito não muda depois que a instrução foi enviada ao banco do pagador. Se a instrução do ciclo onde o cupom começaria já foi enviada, a resposta é
PIX_AUTOMATICO_INSTRUCTED. Isso vale também paraNEXT_CYCLE, quando o débito da próxima cobrança já foi instruído.
Erros:
COUPON_ALREADY_ACTIVE: já há um cupom em vigor na assinatura.COUPON_NOT_FOUND,COUPON_INACTIVE,COUPON_NOT_STARTED,COUPON_EXPIRED,COUPON_EXHAUSTED,PRODUCT_NOT_ELIGIBLE,COUPON_FIRST_TIME_ONLY: o cupom não vale para esta assinatura.COUPON_NOT_APPLICABLE: a assinatura é uma venda avulsa (ONE_TIME), ou o cupom é só para cobranças avulsas.SUBSCRIPTION_NOT_CHANGEABLE: a assinatura está encerrada.CYCLE_ALREADY_SETTLED: a cobrança onde o cupom começaria já foi paga.NO_OPEN_DOCUMENT: comCURRENT_CYCLE, a cobrança atual já foi gerada e não tem Pix ou boleto em aberto para reemitir.COUPON_CONFLICTS_WITH_DISCOUNT: comCURRENT_CYCLE, a cobrança atual já tem desconto manual.COUPON_CONFLICTS_WITH_DISCOUNT_SCHEDULE: a assinatura tem desconto recorrente em vigor.DUE_DATE_REQUIRED: cupom de desconto comCURRENT_CYCLE, a cobrança atual está vencida e odueDatenão foi enviado.DUE_DATE_NOT_APPLICABLE:dueDateenviado com cupom de período grátis, ou com a cobrança atual ainda não emitida.PIX_AUTOMATICO_INSTRUCTED: a instrução de débito do ciclo já foi enviada ao banco.CYCLE_BEING_PROCESSED: a cobrança está sendo processada agora; tente de novo em alguns minutos.
Para um abatimento pontual em uma cobrança, sem cupom, use Aplicar desconto em uma cobrança.
Envie
dryRun: truepara ver o efeito sem aplicar.
Authorizations
Authorization
string obrigatório
Cabeçalho de autenticação Bearer no formato Bearer {{token}} onde {{token}} é o seu token OAuth2.
Escopos requeridos
Path Parameters
subscriptionIdstringobrigatórioBody
application/json
{
"code": "INDICACAO",
"applyTo": "NEXT_CYCLE",
"dueDate": "2026-10-05",
"cancelOpenBoleto": false,
"dryRun": false
}Schema
codestringobrigatórioapplyTostringopcionalNEXT_CYCLECURRENT_CYCLEdueDatestringopcional^\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01])$cancelOpenBoletobooleanopcionaldryRunbooleanopcionalconst url = 'https://sandbox.validapay.com.br/v1/subscriptions/:subscriptionId/coupons';
const options = {
method: 'POST',
headers: {
'Authorization': 'Bearer {{token}}',
'Content-Type': 'application/json'
},
body: JSON.stringify({
"code": "INDICACAO",
"applyTo": "NEXT_CYCLE",
"dueDate": "2026-10-05",
"cancelOpenBoleto": false,
"dryRun": false
})
};
fetch(url, options)
.then(res => res.json())
.then(json => console.log(json))
.catch(err => console.error(err));Response Examples
200cupom aplicado▾
{
"success": true,
"type": "COUPON_APPLIED",
"subscriptionId": "sub_xxx",
"coupon": {
"code": "INDICACAO",
"discountType": "EXTRA_PERIOD",
"discountValue": 1,
"extraPeriodUnit": "MONTHS",
"maxCycles": 1
},
"applyTo": "NEXT_CYCLE",
"firstCycleNumber": 4,
"action": "SHIFT_UNBILLED_CYCLES",
"currentDueDate": null,
"newDueDate": null,
"reissuesOpenCharge": false,
"redemptionId": "red_xxx",
"reissued": null,
"shiftedCycles": [
{
"cycleNumber": 4,
"previousChargeDate": "2026-11-10",
"chargeDate": "2026-12-10"
}
],
"repricedCycles": [],
"restoredStatus": null
}Campos da resposta
successbooleantypestringCOUPON_APPLIEDPREVIEWsubscriptionIdstringcouponobjectapplyTostringCURRENT_CYCLENEXT_CYCLEfirstCycleNumbernumberactionstringAPPLIED_ON_BILLINGSHIFT_UNBILLED_CYCLESREISSUE_WITH_DISCOUNTREISSUE_WITH_NEW_DUE_DATEcurrentDueDateobjectdatenewDueDateobjectdatereissuesOpenChargebooleanredemptionIdstringreissuedobjectshiftedCyclesarray[1]repricedCyclesarray[0]restoredStatusobject200cupom na cobrança atual▾
{
"success": true,
"type": "COUPON_APPLIED",
"subscriptionId": "sub_xxx",
"coupon": {
"code": "VOLTA10",
"discountType": "PERCENTAGE",
"discountValue": 10,
"extraPeriodUnit": null,
"maxCycles": 3
},
"applyTo": "CURRENT_CYCLE",
"firstCycleNumber": 3,
"action": "REISSUE_WITH_DISCOUNT",
"currentDueDate": "2026-11-10",
"newDueDate": "2026-11-10",
"reissuesOpenCharge": true,
"redemptionId": "red_xxx",
"reissued": {
"chargeId": "cha_xxx",
"paymentType": "BOLETO",
"dueDate": "2026-11-10",
"amount": 90,
"replacedChargeId": null,
"keptOpenChargeId": "cha_yyy",
"warning": "O boleto anterior continua pagável; oriente o cliente a usar apenas a nova cobrança",
"payment": {
"transactionId": "9b22cd56-ca19-47f6-b19e-08908158ae9c",
"dueDate": "2026-11-10",
"boletoUrl": "34191090081225054789529988600002216220000001000"
}
},
"shiftedCycles": [],
"repricedCycles": [
{
"cycleNumber": 4,
"previousAmount": 100,
"amount": 90
}
],
"restoredStatus": null
}Campos da resposta
successbooleantypestringsubscriptionIdstringcouponobjectapplyTostringfirstCycleNumbernumberactionstringcurrentDueDatestringnewDueDatestringreissuesOpenChargebooleanredemptionIdstringreissuedobjectshiftedCyclesarray[0]repricedCyclesarray[1]restoredStatusobject200prévia (dryRun)▾
{
"success": true,
"type": "PREVIEW",
"subscriptionId": "sub_xxx",
"coupon": {
"code": "INDICACAO",
"discountType": "EXTRA_PERIOD",
"discountValue": 1,
"extraPeriodUnit": "MONTHS",
"maxCycles": 1
},
"applyTo": "NEXT_CYCLE",
"firstCycleNumber": 4,
"action": "SHIFT_UNBILLED_CYCLES",
"currentDueDate": null,
"newDueDate": null,
"reissuesOpenCharge": false
}Campos da resposta
successbooleantypestringsubscriptionIdstringcouponobjectapplyTostringCURRENT_CYCLENEXT_CYCLEfirstCycleNumbernumberactionstringAPPLIED_ON_BILLINGSHIFT_UNBILLED_CYCLESREISSUE_WITH_DISCOUNTREISSUE_WITH_NEW_DUE_DATEcurrentDueDateobjectdatenewDueDateobjectdatereissuesOpenChargeboolean400cupom em vigor▾
{
"error": {
"message": "A assinatura já tem o cupom BEMVINDO em vigor; aplique outro quando ele terminar",
"code": "COUPON_ALREADY_ACTIVE",
"details": null,
"timestamp": "2026-09-24T12:00:00.000Z"
}
}400cobrança atual vencida▾
{
"error": {
"message": "A cobrança atual está vencida; informe um dueDate posterior a hoje para emitir a nova cobrança",
"code": "DUE_DATE_REQUIRED",
"details": null,
"timestamp": "2026-09-24T12:00:00.000Z"
}
}400cupom inválido▾
{
"error": {
"message": "Cupom expirado",
"code": "COUPON_EXPIRED",
"details": null,
"timestamp": "2026-09-24T12:00:00.000Z"
}
}400cobrança já paga▾
{
"error": {
"message": "A cobrança atual já foi paga; aplique o cupom a partir da próxima (NEXT_CYCLE)",
"code": "CYCLE_ALREADY_SETTLED",
"details": null,
"timestamp": "2026-09-24T12:00:00.000Z"
}
}