# Assinar um plano

URL: https://staging.pagpolar.com/docs/guias/jornadas/assinar-um-plano

> Crie um plano e uma oferta de plano, assine um cliente no cartão e acompanhe a confirmação e as renovações.

Use este guia para cobrar um cliente de forma recorrente, a cada semana, mês ou ano.

Pela API, a assinatura é **sempre no cartão de crédito**. Assinaturas em PIX ou boleto só nascem no checkout da PagPolar. Veja [Ciclo de vida da assinatura](/docs/guias/conceitos/ciclo-de-vida-da-assinatura).

Para uma cobrança única, use [Vender com cartão de crédito](/docs/guias/jornadas/vender-com-cartao).

## Visão geral

O diagrama mostra o caminho completo, da criação do plano até a renovação.

```mermaid
sequenceDiagram
  autonumber
  participant I as Seu sistema
  participant A as API PagPolar
  participant G as Gateway
  participant W as Seu servidor de webhook
  I->>A: POST /plans e POST /plans/ID/offers
  A-->>I: 201 com o id do plano e o código da oferta de plano
  I->>A: POST /plans/offer/CODIGO/subscribe com Idempotency-Key
  A-->>I: 201 com a assinatura em DRAFT
  A-)W: TRANSACTION_CREATED e SUBSCRIPTION_CREATED
  A->>G: cria a assinatura depois da resposta
  alt gateway aceita
    A-)W: SUBSCRIPTION_CONFIRMED com status DRAFT
    G-)A: primeira cobrança paga, assinatura fica ACTIVE
  else gateway recusa
    A-)W: SUBSCRIPTION_FAILED com status FAILED
  end
  G-)A: cobrança de um ciclo seguinte paga
  A-)W: SUBSCRIPTION_RENEWED
```

## Antes de começar

* Um token de acesso. Veja [Autenticação](/docs/guias/fundamentos/autenticacao#obter-o-token); os exemplos assumem a variável `accessToken`.
* A URL do webhook cadastrada na credencial. Veja [Configurar o webhook](/docs/webhooks/configurar).

Para testar sem cobrança real, use a chave de Homologação. Veja [Ambiente de testes](/docs/guias/fundamentos/ambientes#ambiente-de-testes). Com a chave de Produção, o cartão é cobrado a cada ciclo: [cancele a assinatura](/docs/guias/jornadas/cancelar-assinatura) no final do teste.

## Passo a passo

1. **Crie o plano**

   O plano é o produto de assinatura. Ele guarda só o nome e a descrição.

   #### cURL

   ```bash
           curl -X POST "https://api.pagpolar.com/v1/plans" \
             -H "Authorization: Bearer <SEU_TOKEN_DE_ACESSO>" \
             -H "Content-Type: application/json" \
             -d '{
               "name": "Clube de exemplo",
               "description": "Plano criado pelo guia de assinatura"
             }'
           ```

   #### Node.js

   ```js
           const response = await fetch('https://api.pagpolar.com/v1/plans', {
             method: 'POST',
             headers: {
               Authorization: `Bearer ${accessToken}`,
               'Content-Type': 'application/json',
             },
             body: JSON.stringify({
               name: 'Clube de exemplo',
               description: 'Plano criado pelo guia de assinatura',
             }),
           });

           console.log(response.status, await response.json());
           ```

       | Campo         | Obrigatório | O que é                                  |
       | ------------- | ----------- | ---------------------------------------- |
       | `name`        | Sim         | Nome do plano, até 255 caracteres.       |
       | `description` | Não         | Descrição do plano, até 5000 caracteres. |

       Resposta `201` (resumida):

       ```json
       {
         "data": {
           "id": "b7e1c2d3-4f5a-4b6c-8d7e-9f0a1b2c3d4e",
           "name": "Clube de exemplo",
           "type": "SUBSCRIPTION",
           "is_active": true
         }
       }
       ```

       Guarde `data.id`. Ele é o `<ID_DO_PLANO>` do próximo passo. Contrato completo: [`POST /plans`](/docs/referencia/planos/create-plan).

2. **Crie a oferta de plano**

   A oferta de plano define o preço e de quanto em quanto tempo o cliente é cobrado. `price` é em **centavos**: `1990` = R$ 19,90.

   #### cURL

   ```bash
           curl -X POST "https://api.pagpolar.com/v1/plans/<ID_DO_PLANO>/offers" \
             -H "Authorization: Bearer <SEU_TOKEN_DE_ACESSO>" \
             -H "Content-Type: application/json" \
             -d '{
               "title": "Mensal",
               "price": 1990,
               "cycle": "MONTHLY",
               "cycle_interval": 1,
               "is_enabled_credit_card": true,
               "max_credit_card_installments": 1
             }'
           ```

   #### Node.js

   ```js
           const response = await fetch('https://api.pagpolar.com/v1/plans/<ID_DO_PLANO>/offers', {
             method: 'POST',
             headers: {
               Authorization: `Bearer ${accessToken}`,
               'Content-Type': 'application/json',
             },
             body: JSON.stringify({
               title: 'Mensal',
               price: 1990,
               cycle: 'MONTHLY',
               cycle_interval: 1,
               is_enabled_credit_card: true,
               max_credit_card_installments: 1,
             }),
           });

           console.log(response.status, await response.json());
           ```

       | Campo                          | Obrigatório | O que é                                                                                                                     |
       | ------------------------------ | ----------- | --------------------------------------------------------------------------------------------------------------------------- |
       | `price`                        | Sim         | Valor de cada ciclo, em centavos, número inteiro a partir de `0`.                                                           |
       | `cycle`                        | Sim         | Unidade do ciclo: `WEEKLY`, `MONTHLY` ou `YEARLY`.                                                                          |
       | `cycle_interval`               | Não         | A cada quantas unidades de `cycle` o cliente é cobrado. Número inteiro, mínimo `1`. `MONTHLY` com `3` cobra a cada 3 meses. |
       | `title`                        | Não         | Nome da oferta, até 255 caracteres.                                                                                         |
       | `is_enabled_credit_card`       | Não         | Cartão na oferta. Começa ligado. A assinatura pela API precisa dele ligado.                                                 |
       | `max_credit_card_installments` | Não         | Só aceita `1`. Sem o campo, a API usa `1`.                                                                                  |
       | `is_active`                    | Não         | Sem o campo, a oferta nasce ativa.                                                                                          |

   > **Abaixo de R$ 5,00, a oferta de plano fica sem cartão**
   >
   > Ao salvar, a API desliga o cartão quando `price` fica abaixo de `500` (R$ 5,00), mesmo com `is_enabled_credit_card: true`. Com o cartão desligado, a assinatura pela API responde `409` com `Método de pagamento CREDIT_CARD não habilitado para esta oferta`. Confira `payment_methods` na resposta. Na edição com [`PATCH /plan-offers/{id}`](/docs/referencia/planos/update-plan-offer), a mesma regra recalcula os meios. Veja [Meios de pagamento e valor mínimo](/docs/guias/jornadas/criar-produto-e-oferta#meios-de-pagamento).

   > **Envie cycle_interval**
   >
   > A API não define um valor padrão para `cycle_interval`. Sem o campo, a oferta fica com `cycle_interval: null`. Envie `1` para cobrar a cada semana, mês ou ano.

       Resposta `201` (resumida):

       ```json
       {
         "data": {
           "id": "c8f2d3e4-5a6b-4c7d-9e8f-0a1b2c3d4e5f",
           "identifier": "PPP1234567890",
           "title": "Mensal",
           "price": 19.9,
           "product_id": "b7e1c2d3-4f5a-4b6c-8d7e-9f0a1b2c3d4e",
           "payment_methods": {
             "credit_card": true
           },
           "max_credit_card_installments": 1,
           "cycle": "MONTHLY",
           "cycle_interval": 1
         }
       }
       ```

       Na resposta, `price` volta em **reais**: `19.9` é R$ 19,90. Veja [Valores nas respostas](/docs/guias/fundamentos/valores-datas-e-identificadores#valores-nas-respostas).

       Guarde `data.identifier`. Ele é o `<CODIGO_DA_OFERTA>` do próximo passo. O `data.id` também funciona no lugar do código. Contrato completo: [`POST /plans/{id}/offers`](/docs/referencia/planos/create-plan-offer).

3. **Assine o cliente**

   Envie o código da oferta de plano na URL e os dados do cliente e do cartão no corpo. Envie também o header `Idempotency-Key`, um valor único para esta assinatura. Veja [Idempotência](/docs/guias/fundamentos/idempotencia).

   #### cURL

   ```bash
           curl -X POST "https://api.pagpolar.com/v1/plans/offer/<CODIGO_DA_OFERTA>/subscribe" \
             -H "Authorization: Bearer <SEU_TOKEN_DE_ACESSO>" \
             -H "Idempotency-Key: 8d2f4a6b-1c3e-4f5a-9b7c-2d4e6f8a0b1c" \
             -H "Content-Type: application/json" \
             -d '{
               "installments": 1,
               "external_reference": "ASSINATURA-0001",
               "customer": {
                 "name": "Maria Silva",
                 "email": "cliente@exemplo.com",
                 "document": "<CPF_DO_CLIENTE>",
                 "phone": "<TELEFONE_DO_CLIENTE>"
               },
               "credit_card": {
                 "holder_name": "MARIA SILVA",
                 "holder_document": "<CPF_DO_TITULAR>",
                 "number": "<NUMERO_DO_CARTAO>",
                 "expiration_month": 12,
                 "expiration_year": 2030,
                 "cvv": ""
               }
             }'
           ```

   #### Node.js

   ```js
           import { randomUUID } from 'node:crypto';

           const response = await fetch(
             'https://api.pagpolar.com/v1/plans/offer/<CODIGO_DA_OFERTA>/subscribe',
             {
               method: 'POST',
               headers: {
                 Authorization: `Bearer ${accessToken}`,
                 'Idempotency-Key': randomUUID(),
                 'Content-Type': 'application/json',
               },
               body: JSON.stringify({
                 installments: 1,
                 external_reference: 'ASSINATURA-0001',
                 customer: {
                   name: 'Maria Silva',
                   email: 'cliente@exemplo.com',
                   document: '<CPF_DO_CLIENTE>',
                   phone: '<TELEFONE_DO_CLIENTE>',
                 },
                 credit_card: {
                   holder_name: 'MARIA SILVA',
                   holder_document: '<CPF_DO_TITULAR>',
                   number: '<NUMERO_DO_CARTAO>',
                   expiration_month: 12,
                   expiration_year: 2030,
                   cvv: '',
                 },
               }),
             },
           );

           console.log(response.status, await response.json());
           ```

       | Campo                | Obrigatório | O que é                                                                                           |
       | -------------------- | ----------- | ------------------------------------------------------------------------------------------------- |
       | `installments`       | Sim         | Número de parcelas. Envie `1`: a oferta de plano criada pela API aceita no máximo 1.              |
       | `external_reference` | Não         | Código da assinatura no seu sistema, até 255 caracteres. Fica gravado na venda do primeiro ciclo. |

       Dados do cliente:

       | Campo               | Obrigatório | O que é                                                                                                                                                                    |
       | ------------------- | ----------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
       | `customer.name`     | Sim         | Nome do cliente, até 255 caracteres.                                                                                                                                       |
       | `customer.email`    | Sim         | E-mail válido do cliente.                                                                                                                                                  |
       | `customer.document` | Sim         | CPF ou CNPJ do cliente, com ou sem pontuação. Veja o formato em [Documento e telefone](/docs/guias/fundamentos/valores-datas-e-identificadores#documento-e-telefone).      |
       | `customer.phone`    | Sim         | Telefone do cliente com DDD, com ou sem pontuação. Veja o formato em [Documento e telefone](/docs/guias/fundamentos/valores-datas-e-identificadores#documento-e-telefone). |

       Dados do cartão:

       | Campo                          | Obrigatório | O que é                                                                                                                                                                         |
       | ------------------------------ | ----------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
       | `credit_card.holder_name`      | Sim         | Nome impresso no cartão.                                                                                                                                                        |
       | `credit_card.holder_document`  | Sim         | CPF ou CNPJ do titular do cartão, com ou sem pontuação. Veja o formato em [Documento e telefone](/docs/guias/fundamentos/valores-datas-e-identificadores#documento-e-telefone). |
       | `credit_card.number`           | Sim         | Número do cartão. A API confere se o número é válido antes de enviar.                                                                                                           |
       | `credit_card.expiration_month` | Sim         | Mês de validade, número de `1` a `12`.                                                                                                                                          |
       | `credit_card.expiration_year`  | Sim         | Ano de validade com 4 dígitos, número.                                                                                                                                          |
       | `credit_card.cvv`              | Sim         | Código de segurança, texto com 3 ou 4 caracteres.                                                                                                                               |

       No ambiente de testes, use os cartões de [Comprar no ambiente de testes](/docs/guias/fundamentos/ambientes#dados-de-teste).

       Campos opcionais:

       | Campo                  | Obrigatório | O que é                                                                                                                                        |
       | ---------------------- | ----------- | ---------------------------------------------------------------------------------------------------------------------------------------------- |
       | `address`              | Não         | Endereço do cliente. Se enviar, `street`, `number`, `neighborhood`, `city`, `state` e `postal_code` são obrigatórios. `complement` é opcional. |
       | `affiliate_identifier` | Não         | Código do afiliado que indicou a venda. Veja [Vender com afiliado](/docs/guias/jornadas/vender-com-afiliado).                                  |
       | `buyer_ip`             | Não         | IP do cliente. Se não enviar, a API usa o IP de quem chamou, ou seja, o do seu servidor.                                                       |
       | `buyer_user_agent`     | Não         | Navegador do cliente, até 512 caracteres. Se não enviar, a API usa o header `User-Agent` da sua requisição.                                    |

       Resposta `201` (resumida):

       ```json
       {
         "data": {
           "id": "e1f2a3b4-c5d6-4e7f-8a9b-0c1d2e3f4a5b",
           "status": "DRAFT",
           "payment_method": "CREDIT_CARD",
           "start_at": "2026-09-15T13:00:00.000Z",
           "end_at": null,
           "next_billing_at": null,
           "canceled_at": null,
           "cycle_limit": null,
           "created_at": "2026-09-15T13:00:00.000Z"
         }
       }
       ```

       Guarde `data.id`, o id da assinatura, junto do cliente. Você usa esse valor para consultar e cancelar.

       A resposta também traz `customer`, `offer` e `product`. Contrato completo: [`POST /plans/offer/{id}/subscribe`](/docs/referencia/assinaturas/create-subscription).

   > **201 não quer dizer cartão aprovado**
   >
   > A PagPolar só envia a assinatura ao gateway **depois** de responder. Por isso a resposta é sempre `201` com `status: DRAFT`, mesmo quando o cartão vai ser recusado. **Não libere o acesso ainda.** O resultado chega no próximo passo.

       Se a requisição não tiver resposta, repita com a **mesma** `Idempotency-Key`. Veja [O que acontece ao repetir](/docs/guias/fundamentos/idempotencia#o-que-acontece-ao-repetir). Para achar a venda do primeiro ciclo pela sua referência, use `GET /sales?external_reference=ASSINATURA-0001`.

4. **Espere a confirmação do gateway**

   A sua URL recebe os eventos abaixo. Depois dos dois primeiros, a PagPolar cria a assinatura no gateway e chega só **um** dos dois últimos.

       | Evento                                                                    | Quando é enviado                                                                                                           | O que fazer                                                                                                |
       | ------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------- |
       | [`TRANSACTION_CREATED`](/docs/webhooks/eventos/transaction-created)       | Logo depois da criação, com a venda do primeiro ciclo (`transaction.cycle: 1`).                                            | Registre a venda.                                                                                          |
       | [`SUBSCRIPTION_CREATED`](/docs/webhooks/eventos/subscription-created)     | Logo depois da criação, com a assinatura em `DRAFT`.                                                                       | Registre a assinatura. Não libere o acesso.                                                                |
       | [`SUBSCRIPTION_CONFIRMED`](/docs/webhooks/eventos/subscription-confirmed) | O gateway aceitou a assinatura. O status continua `DRAFT` e `external_id` vem preenchido.                                  | Guarde `external_id` se precisar. Ainda não libere o acesso.                                               |
       | [`SUBSCRIPTION_FAILED`](/docs/webhooks/eventos/subscription-failed)       | O gateway recusou a criação. Status `FAILED`. A venda do primeiro ciclo também fica `FAILED`, sem evento de venda próprio. | Não libere o acesso. Peça outro cartão ao cliente e crie uma assinatura nova, com outra `Idempotency-Key`. |

       Exemplo de `SUBSCRIPTION_CONFIRMED` (resumido):

       ```json
       {
         "id": "3c4d5e6f-7a8b-4c9d-0e1f-2a3b4c5d6e7f",
         "event": "SUBSCRIPTION_CONFIRMED",
         "creation_date": "2026-09-15T13:00:20.000Z",
         "version": "1.0.0",
         "data": {
           "subscription": {
             "id": "e1f2a3b4-c5d6-4e7f-8a9b-0c1d2e3f4a5b",
             "external_id": "sub_abc123",
             "status": "DRAFT",
             "payment_method": "CREDIT_CARD"
           },
           "source": {
             "channel": "API",
             "api_credential_id": "7c9e6679-7425-40de-944b-e07fc1f90ae7"
           }
         }
       }
       ```

       O webhook da credencial também recebe as assinaturas vendidas no checkout, com `data.source.channel: CHECKOUT`. Veja [Canal da venda](/docs/webhooks/formato-do-evento#source).

       Um `SUBSCRIPTION_CONFIRMED` pode chegar antes do `SUBSCRIPTION_CREATED`: use o `status` que veio no evento. Veja [Processar eventos sem duplicar](/docs/webhooks/processar-sem-duplicar).

5. **Libere o acesso quando a assinatura ficar **

`ACTIVE`

       A assinatura fica `ACTIVE` quando o gateway avisa que a primeira cobrança foi paga.

       Nenhum evento de assinatura avisa essa ativação. Para confirmar, consulte a assinatura:

   #### cURL

   ```bash
           curl "https://api.pagpolar.com/v1/subscriptions/e1f2a3b4-c5d6-4e7f-8a9b-0c1d2e3f4a5b" \
             -H "Authorization: Bearer <SEU_TOKEN_DE_ACESSO>"
           ```

   #### Node.js

   ```js
           const response = await fetch(
             'https://api.pagpolar.com/v1/subscriptions/e1f2a3b4-c5d6-4e7f-8a9b-0c1d2e3f4a5b',
             { headers: { Authorization: `Bearer ${accessToken}` } },
           );

           console.log(response.status, await response.json());
           ```

       Resposta `200` (resumida):

       ```json
       {
         "data": {
           "id": "e1f2a3b4-c5d6-4e7f-8a9b-0c1d2e3f4a5b",
           "status": "ACTIVE",
           "payment_method": "CREDIT_CARD",
           "next_billing_at": "2026-10-15T13:00:00.000Z"
         }
       }
       ```

       Com `ACTIVE`, libere o acesso. O que fazer em cada status está em [Ciclo de vida](#ciclo-de-vida).

       Consulte com moderação: a consulta conta no limite geral da credencial. Veja [Limites de requisição](/docs/guias/fundamentos/limites-de-requisicao). Contrato completo: [`GET /subscriptions/{id}`](/docs/referencia/assinaturas/get-subscription).

6. **Acompanhe as renovações**

   A cada ciclo, o gateway cobra o cartão sozinho. Você não precisa chamar a API.

       Quando a cobrança de um ciclo, a partir do segundo, é paga, chega [`SUBSCRIPTION_RENEWED`](/docs/webhooks/eventos/subscription-renewed):

       * a assinatura continua `ACTIVE`;
       * `subscription.next_billing_at` traz a data da próxima cobrança;
       * cada ciclo gera uma venda nova, com `id` próprio.

       Mantenha o acesso e atualize a data da próxima cobrança no seu sistema.

       Se o gateway informar uma cobrança pendente, a assinatura fica `PROCESSING`, sem evento próprio. Quando a cobrança é paga, ela volta para `ACTIVE`.

   > **Limite de ciclos**
   >
   > `cycle_limit` mostra quantos ciclos a assinatura cobra no máximo. `null` quando não há limite. A criação de oferta de plano pela API não aceita esse limite.

## Ciclo de vida

A tabela resume os status que aparecem neste guia. Todos os status e transições estão em [Ciclo de vida da assinatura](/docs/guias/conceitos/ciclo-de-vida-da-assinatura).

| Status       | Significado                                                                                     | O que fazer                                                                       |
| ------------ | ----------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------- |
| `DRAFT`      | Assinatura registrada. O gateway ainda não confirmou ou a primeira cobrança ainda não foi paga. | Não libere o acesso. Consulte de novo mais tarde.                                 |
| `FAILED`     | O gateway recusou a criação.                                                                    | Não libere o acesso. Crie uma assinatura nova.                                    |
| `ACTIVE`     | A cobrança do ciclo foi paga.                                                                   | Libere ou mantenha o acesso. `next_billing_at` mostra a data da próxima cobrança. |
| `PROCESSING` | O gateway informou uma cobrança pendente.                                                       | Espere.                                                                           |

## Eventos de webhook deste fluxo

Os eventos da criação estão em [Espere a confirmação do gateway](#confirmacao-do-gateway). Nas renovações chega [`SUBSCRIPTION_RENEWED`](/docs/webhooks/eventos/subscription-renewed): veja [Acompanhe as renovações](#renovacoes).

## Quando algo dá errado

Além dos [erros comuns a todas as rotas](/docs/guias/fundamentos/erros#erros-comuns), este fluxo pode responder:

| Passo | Situação                                                                                            | Resposta                                                                                                                                                                                                                         | Como resolver                                                                                                                        |
| ----- | --------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------ |
| 1 e 2 | Campo obrigatório ausente, ou `cycle` fora da lista, como `cycle: DAILY`.                           | `400 invalid_request`. A `message` traz o campo, como `O campo price é obrigatório` ou `Para o campo cycle os valores permitidos são [WEEKLY,MONTHLY,YEARLY]`. Sem `name` no passo 1, a mensagem é `O campo nome é obrigatório`. | Corrija o campo indicado em `message`.                                                                                               |
| 2     | `price` com casas decimais, como `19.9`.                                                            | `400 invalid_request`                                                                                                                                                                                                            | `price` é em centavos e só aceita inteiro. Envie `1990`.                                                                             |
| 2     | `price` negativo ou `cycle_interval` menor que `1`, como `0`.                                       | `400 invalid_request` com `message` vazia                                                                                                                                                                                        | Envie `price` em centavos a partir de `0` e `cycle_interval` inteiro a partir de `1`.                                                |
| 2     | `<ID_DO_PLANO>` errado, de outra conta ou de um produto que não é plano.                            | `404` com `Plano não encontrado`                                                                                                                                                                                                 | Use o `data.id` do passo 1.                                                                                                          |
| 2     | `max_credit_card_installments` maior que `1`.                                                       | `400` com `Ofertas de plano não podem ser parceladas no cartão de crédito (máximo de 1x)`                                                                                                                                        | Envie `1` ou não envie o campo.                                                                                                      |
| 3     | Dados do cartão inválidos, como número de cartão inválido, mês `13` ou ano fora de `2000` a `2100`. | `400 invalid_request`, em geral com `message` vazia                                                                                                                                                                              | Confira os campos na tabela do passo 3.                                                                                              |
| 3     | Código da oferta errado, de outra conta, de uma oferta oculta ou de uma oferta que não é de plano.  | `404` com `Oferta de plano não encontrada`                                                                                                                                                                                       | Use o `data.identifier` do passo 2.                                                                                                  |
| 3     | Oferta de plano desativada.                                                                         | `409` com `Oferta inativa`                                                                                                                                                                                                       | Ative a oferta ou use outra.                                                                                                         |
| 3     | Oferta de plano com data de expiração vencida.                                                      | `409` com `Oferta expirada`                                                                                                                                                                                                      | Use outra oferta.                                                                                                                    |
| 3     | Cartão desligado na oferta de plano.                                                                | `409` com `Método de pagamento CREDIT_CARD não habilitado para esta oferta`                                                                                                                                                      | Ligue `is_enabled_credit_card` na oferta e confira o [valor mínimo](/docs/guias/jornadas/criar-produto-e-oferta#meios-de-pagamento). |
| 3     | `installments` maior que o máximo da oferta.                                                        | `400` com `Número de parcelas acima do permitido para esta oferta (máximo 1)`                                                                                                                                                    | Envie `installments: 1`.                                                                                                             |
| 4     | O gateway recusou a assinatura.                                                                     | `SUBSCRIPTION_FAILED`, status `FAILED`                                                                                                                                                                                           | Peça outro cartão e crie uma assinatura nova com outra `Idempotency-Key`.                                                            |
| 5     | Id da assinatura errado ou de outra conta.                                                          | `404` com `Assinatura não encontrada`                                                                                                                                                                                            | Use o `data.id` do passo 3.                                                                                                          |

## Confira no painel

O plano aparece em **Meus produtos → Assinaturas**. Na aba **Ofertas e Configurações** ficam as ofertas de plano, com o código, o preço por ciclo, os meios de pagamento e as parcelas:

Cada cobrança da assinatura vira uma venda em **Vendas → Minhas vendas**. Esta é a venda do primeiro ciclo, paga no cartão:

## Próximos passos

- [Cancelar assinatura](/docs/guias/jornadas/cancelar-assinatura) — Encerre a assinatura e saiba quando o cancelamento vale.
- [Ciclo de vida da assinatura](/docs/guias/conceitos/ciclo-de-vida-da-assinatura) — Todos os status, no cartão, no PIX e no boleto.
- [Processar eventos sem duplicar](/docs/webhooks/processar-sem-duplicar) — Trate repetições e eventos fora de ordem.
