PagnovoPagnovodocs

Produtos e Ofertas

Produtos e Ofertas

Product é o catálogo do seu negócio: nome, descrição, imagem. Offer é a variação de preço e ciclo de cobrança desse produto. Um Product tem várias Offers — você pode vender o mesmo curso por R$ 497 à vista (oferta one-time) ou por 12x de R$ 49 (oferta recorrente mensal) sem duplicar o catálogo.

Product "Curso de Marketing"
├── Offer "Pagamento único"   R$ 497,00      one-time
├── Offer "Mensal 12x"        R$ 49,00       MONTHLY × 12 ciclos
└── Offer "Anual"             R$ 397,00      YEARLY × infinito

PaymentLinks, Subscriptions e Invoices ficam vinculados a uma Offer, não diretamente ao Product. Você consulta o Product a partir da Offer.

Editar Offer ativa

Quando seu cliente assina uma Offer, a Pagnovo congela os valores da Offer (amount, billingCycle, trialDays, maxCycles, billingCycleCount) dentro da Subscription. Cada assinatura carrega o preço e o ciclo que existia no momento em que o cliente assinou.

Isso garante que:

  • Aumentar o preço de uma Offer não cobra mais dos assinantes existentes. Eles continuam pagando o valor que assinaram.
  • Mudar o ciclo de MONTHLY pra YEARLY numa Offer ativa não converte as Subscriptions antigas.
  • Histórico de faturamento sempre reflete o preço que o cliente concordou em pagar.

A consequência: editar esses campos de uma Offer com assinantes ou PaymentLinks ativos é confuso — você muda a Offer mas ninguém é afetado, exceto novos clientes. Pra evitar essa pegadinha, a API bloqueia:

CampoEditável sempreBloqueia se há ativos
name, description
deliveryPdfUrl
active (desativar Offer)
externalId, metadata
amount
billingCycle
billingCycleCount
maxCycles
trialDays

Onde "há ativos" significa: Subscriptions em status ACTIVE/TRIAL/PAST_DUE/PAUSED, ou PaymentLinks em status ACTIVE/PAUSED.

Padrão recomendado para mudar preço:

  1. Crie uma Offer nova com o preço novo.
  2. Marque a Offer antiga como active: false (some das listagens de venda, mas Subscriptions existentes continuam funcionando).
  3. Aponte seus novos PaymentLinks pra Offer nova.

stats.canEditSnapshotFields em GET /v2/offers/:id te diz se a Offer está livre pra editar todos os campos.

One-time vs recurring

O que define o tipo é o campo billingCycle na criação:

One-time (billingCycle: null ou omitido):

  • Pagamento único. Cliente paga uma vez e recebe o produto.
  • maxCycles, trialDays e billingCycleCount são ignorados se enviados.
  • Faz sentido pra cursos, e-books, produtos digitais "fechados".

Recurring (billingCycle preenchido com um enum):

  • Cobrança recorrente. Gera nova Invoice a cada ciclo.
  • Valores válidos: DAILY, WEEKLY, MONTHLY, QUARTERLY, SEMIANNUAL, YEARLY.
  • billingCycleCount (default 1): permite intervalos custom. MONTHLY + billingCycleCount: 3 = a cada 3 meses. Em Stripe seria interval: "month", interval_count: 3.
  • maxCycles (default null): número total de cobranças antes da Subscription expirar automaticamente. null = infinito.
  • trialDays (default 0): dias grátis antes da primeira cobrança. Útil pra trial de SaaS.

Combinações úteis:

CenárioConfig
Mensal infinitoMONTHLY, count=1, max=null
Mensal 12x (anual parcelado)MONTHLY, count=1, max=12
BimestralMONTHLY, count=2, max=null
Anual com 14 dias de trialYEARLY, count=1, max=null, trialDays=14
Trimestral por 1 anoQUARTERLY, count=1, max=4

Unidades — centavos

Offers usam centavos no campo amount, igual ao resto da API:

Valor realCentavos
R$ 1,00100
R$ 49,004900
R$ 497,0049700
R$ 1.000,00100000

Range válido para amount: 100 (R$ 1,00) a 5.000.000 (R$ 50.000,00).