> ## Documentation Index
> Fetch the complete documentation index at: https://docs.dodopayments.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Subscription Integration Guide

> This guide will help you integrate the Dodo Payments Subscription Product into your website.

## Prerequisites

To integrate the Dodo Payments API, you'll need:

* A Dodo Payments merchant account
* API credentials (API key and webhook secret key) from the dashboard

For a more detailed guide on the prerequisites, check this [section](/developer-resources/integration-guide#dashboard-setup).

## API Integration

### Checkout Sessions

Use Checkout Sessions to sell subscription products with a secure, hosted checkout. Pass your subscription product in `product_cart` and redirect customers to the returned `checkout_url`.

<Tip>
  **Mixed Checkout**: You can combine subscription products with one-time products in the same checkout session. This enables use cases like setup fees with subscriptions, hardware bundles with SaaS, and more. See the [Checkout Sessions guide](/developer-resources/checkout-session) for examples.
</Tip>

<Tabs>
  <Tab title="Node.js SDK">
    ```javascript theme={null}
    import DodoPayments from 'dodopayments';

    const client = new DodoPayments({
      bearerToken: process.env.DODO_PAYMENTS_API_KEY,
      environment: 'test_mode', // defaults to 'live_mode'
    });

    async function main() {
      const session = await client.checkoutSessions.create({
        product_cart: [
          { product_id: 'prod_subscription_monthly', quantity: 1 }
        ],
        // Optional: configure trials for subscription products
        subscription_data: { trial_period_days: 14 },
        customer: {
          email: 'subscriber@example.com',
          name: 'Jane Doe',
        },
        return_url: 'https://example.com/success',
      });

      console.log(session.checkout_url);
    }

    main();
    ```
  </Tab>

  <Tab title="Python SDK">
    ```python theme={null}
    import os
    from dodopayments import DodoPayments

    client = DodoPayments(
        bearer_token=os.environ.get("DODO_PAYMENTS_API_KEY"),
        environment="test_mode",  # defaults to "live_mode"
    )

    session = client.checkout_sessions.create(
        product_cart=[
            {"product_id": "prod_subscription_monthly", "quantity": 1}
        ],
        subscription_data={"trial_period_days": 14},  # optional
        customer={
            "email": "subscriber@example.com",
            "name": "Jane Doe",
        },
        return_url="https://example.com/success",
    )

    print(session.checkout_url)
    ```
  </Tab>

  <Tab title="REST API">
    ```javascript theme={null}
    const response = await fetch('https://test.dodopayments.com/checkouts', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'Authorization': `Bearer ${process.env.DODO_PAYMENTS_API_KEY}`
      },
      body: JSON.stringify({
        product_cart: [
          { product_id: 'prod_subscription_monthly', quantity: 1 }
        ],
        subscription_data: { trial_period_days: 14 }, // optional
        customer: {
          email: 'subscriber@example.com',
          name: 'Jane Doe'
        },
        return_url: 'https://example.com/success'
      })
    });

    if (!response.ok) {
      throw new Error(`HTTP error! status: ${response.status}`);
    }

    const session = await response.json();
    console.log(session.checkout_url);
    ```
  </Tab>
</Tabs>

### API Response

The following is an example of the response:

```json theme={null}
{
  "session_id": "cks_Gi6KGJ2zFJo9rq9Ukifwa",
  "checkout_url": "https://test.checkout.dodopayments.com/session/cks_Gi6KGJ2zFJo9rq9Ukifwa"
}
```

Redirecione o cliente para `checkout_url`.

### Webhooks

Ao integrar assinaturas, você receberá webhooks para acompanhar o ciclo de vida da assinatura. Esses webhooks ajudam você a gerenciar estados de assinatura e cenários de pagamento de forma eficaz.

Para configurar seu endpoint de webhook, siga nosso [Guia de Integração Detalhado](/developer-resources/integration-guide#implementing-webhooks).

#### Tipos de Eventos de Assinatura

Os seguintes eventos de webhook acompanham as mudanças de status de assinatura:

1. **`subscription.active`** - Assinatura ativada com sucesso.
2. **`subscription.updated`** - Objeto de assinatura foi atualizado (acionado em qualquer alteração de campo).
3. **`subscription.on_hold`** - Assinatura suspensa devido a falha na renovação.
4. **`subscription.failed`** - Falha na criação da assinatura durante a criação do mandato.
5. **`subscription.renewed`** - Assinatura renovada para o próximo período de cobrança.

Para uma gestão confiável do ciclo de vida da assinatura, recomendamos acompanhar esses eventos de assinatura.

<Tip>
  Use `subscription.updated` para receber notificações em tempo real sobre qualquer alteração na assinatura, mantendo o estado do seu aplicativo em sincronia sem fazer polling na API.
</Tip>

#### Cenários de Pagamento

**Fluxo de Pagamento Bem-Sucedido**

Quando um pagamento tem sucesso, você receberá os seguintes webhooks:

1. `subscription.active` - Indica ativação da assinatura
2. `payment.succeeded` - Confirma o pagamento inicial:
   * Para cobrança imediata (0 dias de teste): Esperado dentro de 2-10 minutos
   * Para dias de teste: sempre que isso terminar
3. `subscription.renewed` - Indica dedução de pagamento e renovação para o próximo ciclo. (Basicamente, sempre que o pagamento for deduzido para produtos de assinatura, você receberá o webhook `subscription.renewed` junto com `payment.succeeded`)

**Cenários de Falha de Pagamento**

1. Falha na Assinatura

* `subscription.failed` - Falha na criação da assinatura devido a falha na criação do mandato.
* `payment.failed` - Indica falha no pagamento.

2. Assinatura em Suspenso

* `subscription.on_hold` - Assinatura suspensa devido a falha no pagamento de renovação ou falha na cobrança de alteração de plano.
* Quando uma assinatura é suspensa, ela não se renovará automaticamente até que o método de pagamento seja atualizado.

<Info>**Melhor Prática**: Para simplificar a implementação, recomendamos acompanhar principalmente os eventos de assinatura para gerenciar o ciclo de vida da assinatura.</Info>

<Tip>
  Para um guia completo sobre como ler `error_code`/`error_message`, decidir quando tentar novamente e apresentar falhas aos clientes, veja [Gerenciar Falhas de Pagamento](/developer-resources/handle-payment-failures).
</Tip>

#### `subscription.failed` vs. `subscription.on_hold`

Esses dois eventos são fáceis de confundir, mas requerem manuseio muito diferente:

| Evento                 | Quando é acionado                                                                                   | Status    | Recuperável?       | O que fazer                                                                                                                   |
| ---------------------- | --------------------------------------------------------------------------------------------------- | --------- | ------------------ | ----------------------------------------------------------------------------------------------------------------------------- |
| `subscription.failed`  | O **mandato inicial** não pôde ser criado na **criação** da assinatura                              | `failed`  | **Não — terminal** | Não conceda acesso. Peça ao cliente para iniciar uma **nova** assinatura com um método de pagamento diferente.                |
| `subscription.on_hold` | Um pagamento de **renovação** (ou cobrança de alteração de plano) falhou em uma assinatura já ativa | `on_hold` | **Sim**            | Recupere atualizando o método de pagamento; veja [Gerenciando Assinatura em Suspenso](#handling-subscription-on-hold) abaixo. |

<Warning>
  `subscription.failed` é terminal — a assinatura não pode ser reativada. O cliente deve criar uma nova assinatura. Nunca conceda direitos quando este evento for acionado.
</Warning>

### Gerenciando Assinatura em Suspenso

Quando uma assinatura entra no estado `on_hold`, você precisa atualizar o método de pagamento para reativá-la. Esta seção explica quando assinaturas entram em suspenso e como gerenciá-las.

#### Quando Assinaturas Entram em Suspenso

Uma assinatura é colocada em suspenso quando:

* **Falha no pagamento de renovação**: A cobrança automática de renovação falha devido a fundos insuficientes, cartão expirado ou recusa do banco
* **Falha na cobrança de alteração de plano**: Uma cobrança imediata durante uma atualização/rebaixamento de plano falha
* **Falha na autorização do método de pagamento**: O método de pagamento não pode ser autorizado para cobranças recorrentes

<Warning>
  Assinaturas no estado `on_hold` não se renovarão automaticamente. Você deve atualizar o método de pagamento para reativar a assinatura.
</Warning>

#### Reativando Assinaturas em Suspenso

Para reativar uma assinatura do estado `on_hold`, use a API de Atualizar Método de Pagamento. Isso automaticamente:

1. Cria uma cobrança para dívidas restantes
2. Gera uma fatura para a cobrança
3. Processa o pagamento usando o novo método de pagamento
4. Reativa a assinatura para o estado `active` após pagamento bem-sucedido

<Steps>
  <Step title="Handle subscription.on_hold webhook">
    Quando você recebe um webhook `subscription.on_hold`, atualize o estado de seu aplicativo e notifique o cliente:

    ```javascript theme={null}
    // Webhook handler
    app.post('/webhooks/dodo', async (req, res) => {
      const event = req.body;
      
      if (event.type === 'subscription.on_hold') {
        const subscription = event.data;
        
        // Update subscription status in your database
        await updateSubscriptionStatus(subscription.subscription_id, 'on_hold');
        
        // Notify customer to update payment method
        await sendEmailToCustomer(subscription.customer_id, {
          subject: 'Payment Required - Subscription On Hold',
          message: 'Your subscription is on hold. Please update your payment method to continue service.'
        });
      }
      
      res.json({ received: true });
    });
    ```
  </Step>

  <Step title="Update payment method">
    Quando o cliente estiver pronto para atualizar o método de pagamento, chame a API de Atualizar Método de Pagamento:

    <CodeGroup>
      ```javascript Node.js theme={null}
      // Update with new payment method
      const response = await client.subscriptions.updatePaymentMethod(subscriptionId, {
        type: 'new',
        return_url: 'https://example.com/return'
      });

      // For on_hold subscriptions, a charge is automatically created
      if (response.payment_id) {
        console.log('Charge created for remaining dues:', response.payment_id);
        // Redirect customer to response.payment_link to complete payment
      }
      ```

      ```python Python theme={null}
      # Update with new payment method
      response = client.subscriptions.update_payment_method(
          subscription_id=subscription_id,
          type="new",
          return_url="https://example.com/return"
      )

      # For on_hold subscriptions, a charge is automatically created
      if response.payment_id:
          print("Charge created for remaining dues:", response.payment_id)
          # Redirect customer to response.payment_link to complete payment
      ```
    </CodeGroup>

    <Info>
      Você também pode usar um ID de método de pagamento existente se o cliente tiver métodos de pagamento salvos:

      ```javascript theme={null}
      await client.subscriptions.updatePaymentMethod(subscriptionId, {
        type: 'existing',
        payment_method_id: 'pm_abc123'
      });
      ```
    </Info>
  </Step>

  <Step title="Monitor webhook events">
    Após atualizar o método de pagamento, monitore estes eventos de webhook:

    1. **`payment.succeeded`** - A cobrança para dívidas restantes foi bem-sucedida
    2. **`subscription.active`** - A assinatura foi reativada

    ```javascript theme={null}
    if (event.type === 'payment.succeeded') {
      const payment = event.data;
      
      // Check if this payment is for an on_hold subscription
      if (payment.subscription_id) {
        // Wait for subscription.active webhook to confirm reactivation
      }
    }

    if (event.type === 'subscription.active') {
      const subscription = event.data;
      
      // Update subscription status in your database
      await updateSubscriptionStatus(subscription.subscription_id, 'active');
      
      // Restore customer access
      await restoreCustomerAccess(subscription.customer_id);
      
      // Notify customer of successful reactivation
      await sendEmailToCustomer(subscription.customer_id, {
        subject: 'Subscription Reactivated',
        message: 'Your subscription has been reactivated successfully.'
      });
    }
    ```
  </Step>
</Steps>

### Exemplo de Payload de Evento de Assinatura

***

| Propriedade   | Tipo   | Obrigatório | Descrição                                                                                   |
| ------------- | ------ | ----------- | ------------------------------------------------------------------------------------------- |
| `business_id` | string | Sim         | O identificador único para o negócio                                                        |
| `timestamp`   | string | Sim         | O timestamp de quando o evento ocorreu (não necessariamente o mesmo de quando foi entregue) |
| `type`        | string | Sim         | O tipo de evento. Veja [Tipos de Evento](#event-types)                                      |
| `data`        | objeto | Sim         | O payload de dados principal. Veja [Objeto de Dados](#data-object)                          |

## Mudança nos Planos de Assinatura

Você pode fazer upgrade ou downgrade de um plano de assinatura usando o endpoint da API de mudança de plano. Isso permite que você modifique o produto da assinatura, quantidade e manipule prorratações.

<Card title="Change Plan API Reference" icon="arrows-rotate" href="/api-reference/subscriptions/change-plan">
  Para informações detalhadas sobre mudança de planos de assinatura, por favor, consulte nossa documentação da API de Mudança de Plano.
</Card>

### Opções de Prorratação

Ao mudar de planos de assinatura, você tem duas opções para lidar com a cobrança imediata:

#### 1. `prorated_immediately`

* Calcula o valor prorrateado com base no tempo restante no ciclo de cobrança atual
* Cobra do cliente apenas a diferença entre o plano antigo e o novo
* Durante um período de teste, isso mudará imediatamente o usuário para o novo plano, cobrando imediatamente do cliente

#### 2. `full_immediately`

* Cobra do cliente o valor total da assinatura para o novo plano
* Ignora qualquer tempo restante ou créditos do plano anterior
* Útil quando você deseja reiniciar o ciclo de cobrança ou cobrar o valor total, independentemente da prorratação

#### 3. `difference_immediately`

* Ao fazer upgrade, o cliente é imediatamente cobrado pela diferença entre os valores dos dois planos.
* Por exemplo, se o plano atual for 30 Dólares e o cliente fizer um upgrade para 80 Dólares, ele será cobrado \$50 instantaneamente.
* Ao fazer downgrade, o valor não utilizado do plano atual é adicionado como crédito interno e aplicado automaticamente às renovações futuras da assinatura.
* Por exemplo, se o plano atual for 50 Dólares e o cliente mudar para um plano de 20 Dólares, os \$30 restantes são creditados e usados no próximo ciclo de cobrança.

### Comportamento

* Ao invocar esta API, o Dodo Payments inicia imediatamente uma cobrança com base na opção de prorratação selecionada
* Se a mudança de plano for um downgrade e você usar `prorated_immediately`, os créditos serão calculados automaticamente e adicionados ao saldo de créditos da assinatura. Estes créditos são específicos para essa assinatura e serão usados apenas para compensar pagamentos recorrentes futuros da mesma assinatura
* A opção `full_immediately` ignora cálculos de créditos e cobra o valor total do novo plano

<Tip>
  **Escolha sua opção de prorratação com cuidado**: Use `prorated_immediately` para cobranças justas que consideram o tempo não utilizado, ou `full_immediately` quando você deseja cobrar o valor total do novo plano, independentemente do ciclo de cobrança atual.
</Tip>

### Processamento de Cobrança

* A cobrança imediata iniciada após a mudança de plano geralmente completa o processamento em menos de 2 minutos
* Se essa cobrança imediata falhar por qualquer motivo, a assinatura é automaticamente colocada em suspenso até que o problema seja resolvido

## Assinaturas Sob Demanda

<Info>
  Assinaturas sob demanda permitem que você cobre clientes de forma flexível, não apenas em um cronograma fixo. Este recurso está disponível para todas as contas.
</Info>

**Para criar uma assinatura sob demanda:**

Para criar uma assinatura sob demanda, use o endpoint da API [POST /subscriptions](/api-reference/subscriptions/post-subscriptions) e inclua o campo `on_demand` no corpo da sua solicitação. Isso permite autorizar um método de pagamento sem uma cobrança imediata ou definir um preço inicial personalizado.

**Para cobrar uma assinatura sob demanda:**

Para cobranças subsequentes, use o endpoint [POST /subscriptions/{subscription_id}/charge](/api-reference/subscriptions/create-charge) e especifique o valor a ser cobrado do cliente para essa transação.

<Note>
  Para um guia completo, passo a passo — incluindo exemplos de solicitações/respostas, políticas de nova tentativa seguras e manuseio de webhooks — veja o <a href="/developer-resources/ondemand-subscriptions">Guia de Assinaturas Sob Demanda</a>.
</Note>

## Referência de API Relacionada

<CardGroup cols={2}>
  <Card title="Create Subscription" icon="code" href="/api-reference/subscriptions/post-subscriptions">
    Referência de API para criar produtos de assinatura e gerenciar o ciclo de vida de assinatura
  </Card>

  <Card title="Change Subscription Plan" icon="arrows-rotate" href="/api-reference/subscriptions/change-plan">
    Referência de API para fazer upgrade, downgrade ou mudar planos de assinatura com opções de prorratação
  </Card>

  <Card title="Update Payment Method" icon="credit-card" href="/api-reference/subscriptions/update-payment-method">
    Referência de API para atualizar métodos de pagamento e reativar assinaturas em suspenso
  </Card>

  <Card title="Patch Subscription" icon="pen" href="/api-reference/subscriptions/patch-subscriptions">
    Referência de API para atualizar detalhes e configuração de assinaturas
  </Card>
</CardGroup>
