Skip to main content

Overview

On-demand subscriptions let you authorize a customer’s payment method once and then charge variable amounts whenever you need, instead of on a fixed schedule. This feature is available for all accounts—no approval required. Use this guide to:
  • Create an on-demand subscription (authorize a mandate with optional initial price)
  • Trigger subsequent charges with custom amounts
  • Track outcomes using webhooks
For a general subscription setup, see the Subscription Integration Guide.

Prerequisites

  • Dodo Payments merchant account and API key
  • Webhook secret configured and an endpoint to receive events
  • A subscription product in your catalog
Este guia cria a assinatura sob demanda através de uma sessão de checkout (POST /checkouts), que sempre retorna um checkout_url hospedado. Redirecione o cliente para lá para aprovar o mandato e defina return_url para onde devem ir em seguida.

How on-demand works

  1. You create a subscription with the on_demand object to authorize a payment method and optionally collect an initial charge.
  2. Later, you create charges against that subscription with custom amounts using the dedicated charge endpoint.
  3. You listen to webhooks (e.g., payment.succeeded, payment.failed) to update your system.

Create an on-demand subscription

Endpoint: POST /checkouts Key request fields (body):
Please find them in Create Checkout Session

Create an on-demand subscription

Success

Charge an on-demand subscription

After the mandate is authorized, create charges as needed. Endpoint: POST /subscriptions/{subscription_id}/charge Key request fields (body):
integer
obrigatório
Amount to charge (in the smallest currency unit). Example: to charge $25.00, pass 2500.
string
Optional currency override for the charge.
string
Optional description override for this charge.
boolean
If true, includes adaptive currency fees within product_price. If false, fees are added on top.
object
Especifique como o saldo da carteira do cliente é usado para liquidar esta cobrança.
object
Metadados adicionais para o pagamento. Se omitidos, os metadados da assinatura serão usados.
Success
A cobrança de uma assinatura que não seja sob demanda pode falhar. Verifique se a assinatura tem on_demand: true em seus detalhes antes de realizar a cobrança.

Como lidar com cobranças que falharam

Quando uma cobrança de uma assinatura sob demanda falha, você decide o que acontece em seguida. Diferentemente das assinaturas agendadas — nas quais uma renovação malsucedida interrompe as cobranças automáticas futuras — as assinaturas sob demanda continuam podendo ser cobradas após uma falha. Você pode chamar o endpoint de cobrança novamente como parte da sua própria lógica de novas tentativas.

O que acontece em caso de falha

1

Charge attempt fails

A solicitação POST /subscriptions/{subscription_id}/charge retorna uma resposta de erro ou é concluída de forma assíncrona e emite um webhook payment.failed com o motivo da recusa.
2

Subscription may transition to on_hold

A assinatura pode passar para o estado on_hold e emitir um webhook subscription.on_hold (consulte Estados da assinatura → Em espera). Isso é um sinal — não um bloqueio. Para assinaturas sob demanda, on_hold não impede que você faça uma nova cobrança.
3

Retry the charge (your call)

Nos fluxos sob demanda, Dodo não faz novas tentativas automaticamente. Você pode chamar POST /subscriptions/{subscription_id}/charge novamente a qualquer momento para tentar outra vez. Aplique a política de novas tentativas seguras abaixo — use espera exponencial, ignore recusas definitivas e evite padrões de rajada — para que as novas tentativas não sejam sinalizadas pelos nossos sistemas de fraude e risco.
4

Optionally, ask the customer for a new payment method

Se as novas tentativas continuarem falhando porque o próprio método de pagamento apresenta problemas (cartão expirado, conta encerrada etc.), use POST /subscriptions/{subscription_id}/update-payment-method para coletar um novo método do cliente. Em caso de sucesso, a assinatura retorna a active e os webhooks payment.succeeded seguidos de subscription.active são emitidos.
Sob demanda vs. agendada: para assinaturas agendadas, Dodo executa suas próprias novas tentativas de renovação e dunning. Para assinaturas sob demanda, você é responsável pela política de novas tentativas, pois somente você sabe quando a próxima cobrança deve ocorrer (ela é orientada pelos seus eventos de uso, não por um calendário).

Sequência de webhooks após uma cobrança sob demanda malsucedida

Os eventos 3 e 4 só são disparados depois que uma cobrança subsequente é bem-sucedida.

Responsabilidade pelas novas tentativas

Dodo Payments não faz novas tentativas automáticas de cobranças sob demanda malsucedidas. Você é responsável pela política de novas tentativas. Siga as diretrizes de novas tentativas seguras abaixo para evitar ser sinalizado pelos nossos sistemas de detecção de fraude como teste de cartão.
Dunning de assinaturas — a sequência integrada de recuperação por e-mail — é destinada a pagamentos de renovação malsucedidos em assinaturas agendadas e a cancelamentos iniciados pelo cliente. Ela não foi projetada para falhas de cobrança sob demanda. Comunique-se diretamente com o cliente (por exemplo, por e-mail transacional ou uma solicitação no aplicativo) quando decidir que o método de pagamento precisa ser atualizado.

Novas tentativas de pagamento

Nosso sistema de detecção de fraude pode bloquear padrões agressivos de novas tentativas (e sinalizá-los como possíveis testes de cartão). Siga uma política de novas tentativas segura.
Padrões de novas tentativas em rajada podem ser sinalizados como fraudulentos ou como possível teste de cartão pelos nossos sistemas de risco e processadores. Evite novas tentativas agrupadas; siga o cronograma de espera e as orientações de alinhamento de horário abaixo.

Princípios para políticas de novas tentativas seguras

  • Mecanismo de espera: use espera exponencial entre as novas tentativas.
  • Limites de novas tentativas: limite o total de tentativas (3–4 no máximo).
  • Filtragem inteligente: faça novas tentativas apenas em falhas que permitem nova tentativa (por exemplo, erros de rede/do emissor, fundos insuficientes); nunca faça novas tentativas em recusas definitivas.
  • Prevenção de testes de cartão: não tente novamente falhas como DO_NOT_HONOR, STOLEN_CARD, LOST_CARD, PICKUP_CARD, FRAUDULENT, AUTHENTICATION_FAILURE.
  • Varie os metadados (opcional): se você mantiver seu próprio sistema de novas tentativas, diferencie as tentativas por meio de metadados (por exemplo, retry_attempt).

Cronograma sugerido de novas tentativas (assinaturas)

  • 1ª tentativa: imediatamente ao criar a cobrança
  • 2ª tentativa: após 3 dias
  • 3ª tentativa: após mais 7 dias (10 dias no total)
  • 4ª tentativa (final): após mais 7 dias (17 dias no total)
Etapa final: se o pagamento ainda não tiver sido efetuado, marque a assinatura como não paga ou cancele-a, de acordo com sua política. Notifique o cliente durante esse período para que atualize o método de pagamento.

Evite novas tentativas em rajada; alinhe ao horário da autorização

  • Baseie as novas tentativas no timestamp da autorização original para evitar um comportamento de “rajada” em todo o seu portfólio.
  • Exemplo: se o cliente iniciar um período de avaliação ou mandato hoje às 13h10, agende as novas tentativas subsequentes para as 13h10 nos dias seguintes, de acordo com sua espera (por exemplo, +3 dias → 13h10, +7 dias → 13h10).
  • Como alternativa, se você armazenar o horário do último pagamento bem-sucedido T, agende a próxima tentativa para T + X days a fim de preservar o alinhamento do horário do dia.
Fuso horário e horário de verão (DST): use um padrão de horário consistente para o agendamento e converta apenas para exibição, a fim de manter os intervalos.

Códigos de recusa para os quais você não deve fazer novas tentativas

  • STOLEN_CARD
  • DO_NOT_HONOR
  • FRAUDULENT
  • PICKUP_CARD
  • AUTHENTICATION_FAILURE
  • LOST_CARD
Para obter uma lista completa dos motivos de recusa e saber quais podem ser corrigidos pelo usuário, consulte a documentação de Falhas de transação.
Faça novas tentativas apenas em problemas temporários ou recuperáveis (por exemplo, insufficient_funds, issuer_unavailable, processing_error, tempos limite de rede). Se a mesma recusa se repetir, interrompa novas tentativas.

Diretrizes de implementação (sem código)

  • Use um scheduler/fila que mantenha timestamps precisos; calcule a próxima tentativa no deslocamento exato do horário do dia (por exemplo, T + 3 days no mesmo HH:MM).
  • Mantenha e consulte o timestamp do último pagamento bem-sucedido T para calcular a próxima tentativa; não agrupe várias assinaturas no mesmo instante.
  • Sempre avalie o último motivo de recusa; interrompa novas tentativas para recusas definitivas na lista acima.
  • Limite as novas tentativas simultâneas por cliente e por conta para evitar picos acidentais.
  • Comunique-se proativamente: envie um e-mail/SMS ao cliente para atualizar o método de pagamento antes da próxima tentativa agendada.
  • Use metadados apenas para observabilidade (por exemplo, retry_attempt); nunca tente “burlar” os sistemas de fraude/risco alternando campos irrelevantes.

Cancelamento

As assinaturas sob demanda seguem um fluxo de cancelamento diferente das assinaturas agendadas, pois não há um ciclo de cobrança fixo que sirva de referência para uma data de término imediata.

Comportamento do Customer Portal

Quando um cliente cancela uma assinatura sob demanda no Customer Portal, o cancelamento é agendado para a próxima data de cobrança por padrão. A opção Cancelar agora não é exibida intencionalmente para assinaturas sob demanda. O motivo é que assinaturas sob demanda não têm datas previsíveis de renovação recorrente — o horário da próxima cobrança é determinado inteiramente pelos seus eventos de uso. Agendar o cancelamento para a próxima data de cobrança mantém o mandato ativo até o fim do período, permitindo que qualquer uso em andamento ainda seja cobrado, e então encerra a assinatura corretamente. Depois que o cliente confirma o cancelamento:
  • A assinatura permanece em active e continua podendo ser cobrada por meio de POST /subscriptions/{id}/charge até a data de cancelamento agendada.
  • cancel_at_next_billing_date é definido como true na assinatura.
  • Um webhook subscription.cancelled é emitido quando o cancelamento entra em vigor.
Se precisar encerrar a assinatura imediatamente (por exemplo, em resposta a um reembolso ou a uma solicitação de suporte), cancele-a programaticamente pela API em vez de depender do fluxo do Customer Portal.

Cancelar programaticamente

Você pode cancelar uma assinatura sob demanda pela API a qualquer momento. Você controla se o cancelamento será imediato ou agendado. Endpoint: PATCH /subscriptions/{subscription_id}
Defina status da assinatura como cancelled para encerrá-la imediatamente. O mandato é revogado e nenhuma cobrança adicional pode ser criada.
cURL

Webhooks no cancelamento

Para distinguir cancelamentos sob demanda de cancelamentos de assinaturas agendadas no seu handler, verifique a flag on_demand da assinatura ao processar o webhook.

Acompanhe os resultados com webhooks

Implemente o tratamento de webhooks para acompanhar a jornada do cliente. Consulte Implementando Webhooks.
  • subscription.active: Mandato autorizado e assinatura ativada
  • subscription.failed: A criação falhou (por exemplo, falha no mandato)
  • subscription.on_hold: A assinatura foi colocada em espera (por exemplo, estado não pago)
  • subscription.cancelled: A assinatura foi totalmente cancelada (consulte Cancelamento)
  • payment.succeeded: A cobrança foi bem-sucedida
  • payment.failed: A cobrança falhou
Nos fluxos sob demanda, concentre-se em payment.succeeded e payment.failed para reconciliar cobranças baseadas em uso. Quando payment.failed for seguido por subscription.on_hold, consulte Como lidar com cobranças que falharam para recuperar a assinatura.

Testes e próximos passos

1

Create in test mode

Use sua chave de API de teste para criar a assinatura; em seguida, abra o checkout_url retornado e conclua o mandato.
2

Trigger a charge

Chame o endpoint de cobrança com um product_price pequeno (por exemplo, 100) e verifique se você recebe payment.succeeded.
3

Go live

Mude para sua chave de API de produção depois de validar os eventos e as atualizações do estado interno.

Solução de problemas

  • 422 Invalid Request: verifique se on_demand.mandate_only é fornecido na criação e se product_price é fornecido para as cobranças.
  • Erros de moeda: se você substituir product_currency, confirme se ela é compatível com sua conta e seu cliente.
  • Nenhum webhook recebido: verifique a configuração da URL do webhook e do secret de assinatura.
Última modificação em 6 de agosto de 2026