# Calcular pró-rata ou crédito

**Área:** Plano e itens

Simula uma troca de plano ou de quantidade **sem alterar nada**. Mostra quanto será cobrado agora, quanto vira crédito e qual será a próxima cobrança. Use antes de **Trocar plano ou quantidade**: o cálculo é exatamente o mesmo que a troca vai executar.

`POST /v1/subscriptions/:subscriptionId/prorata`

**Base URL Produção:** `https://api.validapay.com.br`  
**Base URL Sandbox:** `https://sandbox.validapay.com.br`

**Scopes necessários:** `subscriptions/write`

**Os três resultados possíveis (`type`):**

- **`CHARGE_NOW`** — plano mais caro na mesma periodicidade. O cliente recebe uma cobrança agora com a diferença proporcional aos dias que faltam (pró-rata).
- **`NEXT_CHARGE`** — plano mais barato sem crédito, ou troca que só vale na próxima cobrança. Nada é cobrado agora; a próxima cobrança já vem no valor novo.
- **`CREDIT`** — troca de periodicidade (ex.: anual para mensal) ou plano mais barato com crédito. O que já foi pago vira crédito que abate as próximas cobranças.

**Como o crédito funciona na troca de periodicidade:** o valor já pago e não usado vira **dias** do plano novo. A próxima cobrança vai para o dia seguinte ao último dia coberto. A sobra, menor que o valor de um dia do plano novo, é descontada dessa próxima cobrança.

*Exemplo:* faltam 72 dias de um plano anual de R$ 1.080 (R$ 216 de crédito). Na troca para um mensal de R$ 100 (R$ 3,33 por dia), o crédito cobre 64 dias; a próxima cobrança fica para depois desses 64 dias e sai por R$ 97,33 (R$ 100 − R$ 2,67 de sobra).

**Quando a troca de periodicidade é recusada:**
- `RECURRENCE_CHANGE_REQUIRES_PAID_CYCLE`: o ciclo atual ainda não foi pago; o crédito sai dele.
- `NEXT_CYCLE_ALREADY_BILLED`: a próxima cobrança já foi emitida; troque depois que ela for paga.
- `RECURRENCE_CHANGE_WITH_ADDONS`: o plano precisa ser o único item recorrente da assinatura.
- `RECURRENCE_CHANGE_REQUIRES_NEW_ADHESION`: no Pix Automático, troque antes a forma de pagamento.

> O formato antigo (`old` e `new` no corpo) continua aceito, mas está **descontinuado** e não considera troca de periodicidade, cupom nem desconto.

### Path parameters

| Campo | Obrigatório | Descrição |
|---|---|---|
| `subscriptionId` | **sim** | ID da assinatura (ex: sub_xxx) - required |

### Request body

```json
{
    "itemId": "item_xxx", 
    "priceId": "price_yyy", 
    "quantity": 1 
}
```

### Campos do body

**Obrigatórios:** `itemId`

| Campo | Descrição |
|---|---|
| `itemId` | Item que será trocado, em items[].itemId de Ver uma assinatura |

**Opcionais**

| Campo | Descrição |
|---|---|
| `priceId` | Plano novo. Informe priceId, quantity ou os dois |
| `quantity` | Quantidade nova. Sem ela, mantém a atual |

### Resposta 200: 200 plano mais caro

```json
{
    "subscriptionId": "sub_xxx", 
    "itemId": "item_xxx", 
    "type": "CHARGE_NOW", 
    "current": { 
        "priceId": "price_xxx", 
        "amount": 99.9, 
        "recurrence": "MONTHLY", 
        "recurrenceInterval": 1 
    },
    "new": { 
        "priceId": "price_yyy", 
        "amount": 149.9, 
        "recurrence": "MONTHLY", 
        "recurrenceInterval": 1 
    },
    "charge": { 
        "amount": 25.0, 
        "prorataAmount": 25.0, 
        "paymentType": "CREDIT_CARD", 
        "dueDate": null, 
        "period": { 
            "startDate": "2026-09-24", 
            "endDate": "2026-10-09", 
            "days": 15 
        }
    },
    "credit": null, 
    "nextCharge": { 
        "date": "2026-10-10", 
        "amount": 149.9 
    },
    "warnings": [] 
}
```

#### Campos da resposta

| Campo | Descrição |
|---|---|
| `subscriptionId` | ID da assinatura |
| `itemId` | Item que seria trocado |
| `type` | Resultado da troca. CHARGE_NOW: cobra a diferença agora. NEXT_CHARGE: nada é cobrado agora, o valor novo vale a partir da próxima cobrança. CREDIT: o que já foi pago vira crédito (valores: CHARGE_NOW, NEXT_CHARGE, CREDIT) |
| `current` | Plano atual |
| `current.priceId` | ID do plano atual |
| `current.amount` | Valor do plano atual por período, em reais |
| `current.recurrence` | Periodicidade atual (valores: DAILY, WEEKLY, MONTHLY, QUARTERLY, SEMIANNUAL, YEARLY) |
| `current.recurrenceInterval` | A cada quantos períodos cobra |
| `new` | Plano depois da troca |
| `new.priceId` | ID do plano novo |
| `new.amount` | Valor do plano novo por período, em reais |
| `new.recurrence` | Periodicidade nova (valores: DAILY, WEEKLY, MONTHLY, QUARTERLY, SEMIANNUAL, YEARLY) |
| `new.recurrenceInterval` | A cada quantos períodos cobra |
| `charge` | Cobrança gerada ao confirmar a troca. Só vem em CHARGE_NOW |
| `charge.amount` | Valor que será cobrado agora, em reais |
| `charge.prorataAmount` | Parte do valor que é a diferença proporcional aos dias restantes (pró-rata) |
| `charge.paymentType` | Como será cobrada (valores: CREDIT_CARD, PIX, BOLETO, PIX_AUTOMATICO) |
| `charge.dueDate` | Vencimento da cobrança. null no cartão, que é cobrado na hora (formato: date) |
| `charge.period` | Dias cobrados na pró-rata |
| `charge.period.startDate` | Primeiro dia cobrado (formato: date) |
| `charge.period.endDate` | Último dia cobrado (formato: date) |
| `charge.period.days` | Quantidade de dias cobrados |
| `credit` | Crédito gerado pela troca. Só vem em CREDIT |
| `nextCharge` | Próxima cobrança recorrente depois da troca |
| `nextCharge.date` | Data da próxima cobrança (formato: date) |
| `nextCharge.amount` | Valor da próxima cobrança, já com abatimentos, cupom e desconto que continuam valendo, em reais |
| `warnings` | Avisos sobre efeitos da troca, como cupom que será encerrado |

### Resposta 200: 200 troca de periodicidade

```json
{
    "subscriptionId": "sub_xxx",
    "itemId": "item_xxx",
    "type": "CREDIT",
    "current": { "priceId": "price_anual", "amount": 1080.0, "recurrence": "YEARLY", "recurrenceInterval": 1 },
    "new": { "priceId": "price_mensal", "amount": 100.0, "recurrence": "MONTHLY", "recurrenceInterval": 1 },
    "charge": null,
    "credit": { 
        "amount": 216.0, 
        "unusedDays": 72, 
        "coveredDays": 64, 
        "coveredUntil": "2026-11-26", 
        "remainder": 2.67, 
        "lost": 0, 
        "allocations": null 
    },
    "nextCharge": {
        "date": "2026-11-27", 
        "amount": 97.33 
    },
    "warnings": ["O cupom BEMVINDO tinha ciclos limitados e será encerrado com a troca de recorrência."]
}
```

#### Campos da resposta

| Campo | Descrição |
|---|---|
| `credit` | Crédito gerado pela troca |
| `credit.amount` | Valor do crédito: dias já pagos e não usados do plano atual, em reais |
| `credit.unusedDays` | Dias já pagos do plano atual que ainda não foram usados |
| `credit.coveredDays` | Dias inteiros do plano novo que o crédito paga |
| `credit.coveredUntil` | Último dia pago pelo crédito (formato: date) |
| `credit.remainder` | Sobra menor que um dia do plano novo; é abatida da próxima cobrança |
| `credit.lost` | Parte do crédito que não pôde ser usada (maior que a próxima cobrança) |
| `credit.allocations` | Distribuição do crédito entre as próximas cobranças. Só vem em troca para plano mais barato na mesma periodicidade |
| `nextCharge.date` | Dia seguinte ao último dia pago pelo crédito |
| `nextCharge.amount` | Valor do plano novo menos a sobra do crédito |

### Resposta 200: 200 plano mais barato com crédito

```json
{
    "subscriptionId": "sub_xxx",
    "itemId": "item_xxx",
    "type": "CREDIT",
    "current": { "priceId": "price_yyy", "amount": 149.9, "recurrence": "MONTHLY", "recurrenceInterval": 1 },
    "new": { "priceId": "price_xxx", "amount": 99.9, "recurrence": "MONTHLY", "recurrenceInterval": 1 },
    "charge": null,
    "credit": {
        "amount": 25.0, 
        "unusedDays": null,
        "coveredDays": null,
        "coveredUntil": null,
        "remainder": null,
        "lost": 0, 
        "allocations": [ 
            {
                "cycleNumber": 3, 
                "chargeDate": "2026-10-10", 
                "amount": 25.0, 
                "coverage": "PARTIAL" 
            }
        ]
    },
    "nextCharge": { "date": "2026-10-10", "amount": 74.9 },
    "warnings": []
}
```

#### Campos da resposta

| Campo | Descrição |
|---|---|
| `credit.amount` | Crédito pelos dias restantes do plano mais caro, em reais |
| `credit.lost` | Parte do crédito que sobrou depois de abater as próximas cobranças |
| `credit.allocations` | Quanto do crédito abate cada próxima cobrança |
| `credit.allocations.cycleNumber` | Ciclo que recebe o abatimento |
| `credit.allocations.chargeDate` | Vencimento desse ciclo (formato: date) |
| `credit.allocations.amount` | Valor abatido nesse ciclo, em reais |
| `credit.allocations.coverage` | FULL: o ciclo fica todo pago pelo crédito. PARTIAL: o cliente paga o restante (valores: FULL, PARTIAL) |

### Resposta 400: 400 sem itemId

```json
{
    "error": {
        "message": "itemId é obrigatório",
        "code": "MISSING_ITEM_ID",
        "details": null,
        "timestamp": "2026-09-24T12:00:00.000Z"
    }
}
```


### Resposta 400: 400 ciclo atual não pago

```json
{
    "error": {
        "message": "A troca de recorrência aproveita o que já foi pago no ciclo atual; quite a cobrança em aberto antes de trocar",
        "code": "RECURRENCE_CHANGE_REQUIRES_PAID_CYCLE",
        "details": null,
        "timestamp": "2026-09-24T12:00:00.000Z"
    }
}
```


---

Página: https://docs.validapay.com.br/referencia/post-calcular-pro-rata-ou-credito  
Contrato OpenAPI: https://docs.validapay.com.br/openapi.json