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
Prerequisites
- Dodo Payments merchant account and API key
- Webhook secret configured and an endpoint to receive events
- A subscription product in your catalog
How on-demand works
- You create a subscription with the
on_demandobject to authorize a payment method and optionally collect an initial charge. - Later, you create charges against that subscription with custom amounts using the dedicated charge endpoint.
- 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
- Node.js SDK
- Python SDK
- Go SDK
- cURL
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):Charge request body parameters
Charge request body parameters
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.
- Node.js SDK
- Python SDK
- Go SDK
- cURL
Success
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
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.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)
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 paraT + X daysa 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_CARDDO_NOT_HONORFRAUDULENTPICKUP_CARDAUTHENTICATION_FAILURELOST_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.
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 daysno mesmo HH:MM). - Mantenha e consulte o timestamp do último pagamento bem-sucedido
Tpara 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
activee continua podendo ser cobrada por meio dePOST /subscriptions/{id}/chargeaté a data de cancelamento agendada. cancel_at_next_billing_dateé definido comotruena 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}- Cancel immediately
- Cancel at next billing date
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
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
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 seproduct_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.