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

# Assinaturas

> Pix Automático: o cliente paga uma vez, autoriza no banco, e a renovação é cobrada sozinha.

Assinatura é **Pix Automático**, o padrão de recorrência do Banco Central. Você cria uma
vez, com o CPF de quem vai pagar; o cliente recebe um QR composto que paga o primeiro
ciclo e, no mesmo ato, autoriza os próximos no app do banco. A partir daí cada renovação
é cobrada sozinha, um período depois, e dispara webhook na mesma `callbackUrl`.

> [!NOTE]
>
> Assinatura sempre nasce de um produto cadastrado. O valor e o nome saem dele, então
> antes de criar a assinatura você precisa de um `productId` ativo. Veja
> [Produtos](https://docs.purin.cash/guias/produtos.md).

## Criando

```bash theme={null}
curl -X POST https://api.purin.cash/v1/subscriptions \
  -H "Authorization: Bearer $PURINCASH_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "productId": "65f0c2a1e4b0a1b2c3d4e5f6",
    "customer": { "name": "João Silva", "taxId": "529.982.247-25", "externalId": "user_42" },
    "frequency": "MONTHLY",
    "dayGenerateCharge": 15,
    "callbackUrl": "https://minhaloja.com/webhooks/purincash",
    "metadata": "{\"plano\":\"premium\"}"
  }'
```

**productId** `string` *required*

Produto ativo que define valor e nome da assinatura.

**customer.name** `string` *required*

Nome do titular da conta que vai pagar, como está no banco.

**customer.taxId** `string` *required*

CPF ou CNPJ do titular da conta que vai pagar. A autorização é presa a este documento:
o banco confere que é o dono da conta quem está aprovando. Documento inválido é 400.

**frequency** `string` (default: MONTHLY)

`WEEKLY`, `MONTHLY`, `QUARTERLY`, `SEMIANNUALLY` ou `ANNUALLY`.

**dayGenerateCharge** `integer`

Dia do mês do débito automático, de 1 a 28. Sem ele, o dia da compra. Não vale para
a periodicidade semanal.

**callbackUrl** `string`

Recebe os eventos da assinatura (`subscription.*`) e o `payment.paid` de **cada**
ciclo, não só do primeiro.

**metadata** `string`

String JSON de até 2 KB, devolvida sem alteração em todo evento.

```json Resposta theme={null}
{
  "paymentId": "psa_sub_a1b2c3d4",
  "status": "pending",
  "type": "subscription",
  "subscriptionId": "RN12345678202609200000000001",
  "authorizationStatus": "pending_authorization",
  "amountCents": 4990,
  "currency": "BRL",
  "productName": "Plano Premium",
  "frequency": "MONTHLY",
  "environment": "live",
  "pix": {
    "brCode": "00020101021226760014br.gov.bcb.pix...",
    "qrCodeImage": "data:image/png;base64,...",
    "paymentLinkUrl": null
  },
  "nextChargeDate": "2026-10-20",
  "dayGenerateCharge": 15
}
```

Mostre o `brCode` como qualquer PIX. O cliente paga o primeiro ciclo na hora e o app do
banco pede, na mesma tela, a autorização das próximas cobranças.

> [!TIP]
>
> O `dayGenerateCharge` vai até 28 de propósito. Assinatura marcada para dia 30 pularia
> fevereiro, e isso é uma classe inteira de bug que ninguém quer no faturamento.

## O que acontece depois

**1. Primeiro pagamento**

Chega um `payment.paid` do `paymentId` da criação (`subscriptionCycle: 0`). É uma
venda como outra qualquer.

**2. Autorização**

Quando o banco aprova a recorrência chega `subscription.authorized` e o
`authorizationStatus` vira `active`. Pagamento e autorização são atos diferentes e
podem chegar em qualquer ordem. Se o cliente pagar e não autorizar, você fica com
uma venda avulsa e um `authorizationStatus` que expira ou é recusado.

**3. Renovações**

Alguns dias antes de cada vencimento a cobrança é enviada ao banco do cliente, que
debita sozinho na data. Cada ciclo pago chega como `payment.paid` com
`subscriptionId` e `subscriptionCycle` (1, 2, 3…) e um `paymentId` próprio
(`psa_sub_…_c1`, `_c2`…).

**4. Quando não liquida**

`subscription.charge_failed` traz o ciclo, o vencimento e o código do banco. A
assinatura continua ativa: quando a política permite, a retentativa é pedida
sozinha (até 3 em 7 dias) e o ciclo seguinte segue normal.

**5. Fim**

`subscription.cancelled` quando você cancela, o cliente cancela no banco, a
autorização é recusada ou vence. Não há novas cobranças depois dele.

Os eventos estão detalhados em [Webhooks → Assinaturas](https://docs.purin.cash/webhooks/assinaturas.md).

## Acompanhando

```bash theme={null}
curl "https://api.purin.cash/v1/subscriptions?limit=20&status=paid" \
  -H "Authorization: Bearer $PURINCASH_KEY"
```

A listagem aceita `limit` (1 a 100, padrão 50), `offset` e `status`, e traz uma linha
por assinatura com `authorizationStatus`, `nextChargeDate` e `cyclesPaid`. As renovações
pagas aparecem em `GET /v1/payments` como pagamentos próprios.

Para uma assinatura só, com cada cobrança recorrente e suas tentativas:

```bash theme={null}
curl "https://api.purin.cash/v1/subscriptions/psa_sub_a1b2c3d4" \
  -H "Authorization: Bearer $PURINCASH_KEY"
```

```json theme={null}
{
  "paymentId": "psa_sub_a1b2c3d4",
  "subscriptionId": "RN12345678202609200000000001",
  "status": "paid",
  "authorizationStatus": "active",
  "frequency": "MONTHLY",
  "amountCents": 4990,
  "nextChargeDate": "2026-11-20",
  "firstChargeDate": "2026-10-20",
  "cyclesPaid": 2,
  "charges": [
    {
      "cycle": 1,
      "paymentId": "psa_sub_a1b2c3d4_c1",
      "dueDate": "2026-10-20",
      "amountCents": 4990,
      "status": "concluida",
      "paidAt": "2026-10-20T09:10:00.000Z",
      "attempts": [{ "settlementDate": "2026-10-20", "status": "PAGA" }]
    }
  ]
}
```

## Cancelando

```bash theme={null}
curl -X POST "https://api.purin.cash/v1/subscriptions/psa_sub_a1b2c3d4/cancel" \
  -H "Authorization: Bearer $PURINCASH_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "reason": "cliente pediu" }'
```

Cancela a autorização no banco e as cobranças ainda não liquidadas. O que já foi pago
não muda. O cliente também pode cancelar pelo app do banco: nesse caso o
`subscription.cancelled` chega do mesmo jeito.

## Controlando o acesso do assinante

A API não bloqueia o cliente sozinho. Quem decide se o acesso continua é você, e o dado
que sustenta essa decisão é o webhook.

**1. Guarde o subscriptionId no seu usuário**

É a chave estável entre as cobranças. O `paymentId` muda a cada ciclo.

**2. Renove a validade a cada payment.paid**

Ao receber um pagamento com aquele `subscriptionId`, empurre a data de expiração do
acesso para frente conforme a frequência.

**3. Deixe o acesso expirar sozinho**

Se o ciclo passou sem pagamento, a data vence e o acesso cai. O
`subscription.cancelled` é o aviso de que não vale esperar pela próxima.

> [!WARNING]
>
> Sempre confirme por `subscriptionId` antes de renovar. Um assinante com duas assinaturas
> ativas do mesmo produto é raro, mas acontece, e renovar pelo produto em vez da
> assinatura dá acesso de graça.

> [!NOTE]
>
> **Vendas pelo bot do Discord** já fazem isso sozinhas. Na variação marcada como
> assinatura você escolhe o que cada renovação entrega (um item novo do estoque, ou só
> manter o acesso), se os cargos saem quando a assinatura para, a carência em dias e o
> lembrete por DM antes do débito. A renovação cobra o preço da variação: cupom, desconto
> VIP e adicionais valem só no primeiro pagamento.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.