# Trocar plano ou quantidade

**Área:** Plano e itens

Troca o plano de um item (inclusive por um plano de outro produto) ou muda a quantidade.

`PUT /v1/subscriptions/:subscriptionId/items/:itemId`

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

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

**O que acontece com a cobrança:**
- **Plano mais caro:** cobra agora a diferença proporcional aos dias que faltam (pró-rata). O plano novo vale quando essa cobrança é paga.
- **Plano mais barato:** nada é cobrado agora; o valor novo vale a partir da próxima cobrança. Os dias restantes podem virar crédito nas próximas cobranças.
- **Outra periodicidade** (ex.: anual para mensal): nada é cobrado agora; o que já foi pago vira dias do plano novo e a próxima cobrança é remarcada.

> Quer saber o valor antes? Use **Calcular pró-rata ou crédito**. Ela faz exatamente o mesmo cálculo desta rota, sem alterar nada.

> O formato antigo (`PATCH /v1/subscriptions/{id}` com `old` e `new`) continua aceito, mas está **descontinuado**.

### Path parameters

| Campo | Obrigatório | Descrição |
|---|---|---|
| `subscriptionId` | **sim** | ID da assinatura (ex: sub_xxx) - required |
| `itemId` | **sim** | ID do item da assinatura, em items[].itemId de Ver uma assinatura (ex: item_xxx) - required |

### Request body

```json
{
    "priceId": "price_yyy", 
    "quantity": 2, 

    "prorata": { 
        "enabled": true, 
        "mergeWithNextCycle": false, 
        "dueDate": "2026-09-27" 
    },
    "boletoInstructions": { 
        "fine": 2.0, 
        "interest": 1.0 
    },
    "expirationAfterDueDate": 30, 
    "dryRun": false 

}
```

### Campos do body

**Opcionais**

| Campo | Descrição |
|---|---|
| `priceId` | Plano novo. Informe priceId, quantity ou os dois |
| `quantity` | Quantidade nova |
| `prorata` | Como cobrar a diferença dos dias restantes |
| `prorata.enabled` | false: não cobra pró-rata; o valor novo só vale na próxima cobrança (padrão true) |
| `prorata.mergeWithNextCycle` | true: a pró-rata entra na próxima cobrança em vez de gerar uma cobrança agora (padrão false) |
| `prorata.dueDate` | Vencimento do Pix ou boleto da pró-rata (YYYY-MM-DD). Padrão: 3 dias |
| `boletoInstructions` | Multa, juros e desconto do boleto da pró-rata |
| `boletoInstructions.fine` | Multa por atraso, em % |
| `boletoInstructions.interest` | Juros ao mês, em % |
| `expirationAfterDueDate` | Dias depois do vencimento em que o boleto ou Pix ainda pode ser pago (0 a 60) |
| `dryRun` | true: só simula e não altera nada |

### Resposta 200: 200 plano trocado

```json
{
    "success": true, 
    "intent": "REPLACE", 
    "mode": "PRORATA_NOW", 
    "settlement": "AWAITING_PAYMENT", 
    "item": { 
        "itemId": "item_yyy", 
        "priceId": "price_yyy", 
        "quantity": 1, 
        "amount": 149.9, 
        "status": "PENDING_UPGRADE" 
    },
    "replacedItemId": "item_xxx", 
    "adjustmentItemId": null, 
    "amounts": { 
        "delta": 50.0, 
        "prorata": 25.0, 
        "recurringTotal": 149.9, 
        "chargeTotal": 25.0 
    },
    "prorataPeriod": { 
        "startDate": "2026-09-24", 
        "endDate": "2026-10-09", 
        "days": 15, 
        "factor": 0.5, 
        "prorataAmount": 25.0 
    },
    "effectiveAt": "2026-10-10T00:00:00.000Z", 
    "invoiceId": "inv_yyy", 
    "charge": { 
        "chargeId": "cha_yyy", 
        "status": "AWAITING_PAYMENT", 
        "paymentType": "PIX", 
        "dueDate": "2026-09-27" 
    },
    "payment": { 
        "method": "PIX", 
        "pix": { 
            "emv": "00020126...", 
            "qrCode": "data:image/png;base64,iVBOR...", 
            "transactionId": "tx_xxx" 
        },
        "boleto": null, 
        "dueDate": "2026-09-27" 
    },
    "type": "DEFERRED_UPGRADE", 
    "chargeId": "cha_yyy", 
    "prorataAmount": 25.0, 
    "newAmount": 149.9, 
    "recurringTotal": 149.9, 
    "amount": 25.0, 
    "paymentMethod": "PIX", 
    "pix": { "emv": "00020126...", "qrCode": "data:image/png;base64,iVBOR...", "transactionId": "tx_xxx" }, 
    "dueDate": "2026-09-27" 
}
```

#### Campos da resposta

| Campo | Descrição |
|---|---|
| `success` | true quando a alteração foi registrada |
| `intent` | ADD: item adicionado. REPLACE: item trocado (valores: ADD, REPLACE) |
| `mode` | Como a diferença de valor foi tratada (valores: PRORATA_NOW, NO_PRORATA, PRORATA_NEXT_CYCLE, SCHEDULED_DOWNGRADE, RECURRENCE_CHANGE, PENDING_REWRITE) |
| `settlement` | Situação da cobrança da diferença. PAID: paga no cartão. AWAITING_PAYMENT: Pix ou boleto emitido. NEXT_CYCLE_ENGINE: entra na próxima cobrança. CREDITED: virou crédito. RESCHEDULED: próxima cobrança remarcada. NONE: nada a cobrar (valores: PAID, AWAITING_PAYMENT, NONE, NEXT_CYCLE_ENGINE, MERGED_INTO_OPEN_CHARGE, MERGED_INTO_CHECKOUT, CREDITED, RESCHEDULED) |
| `item` | Item criado ou alterado, no mesmo formato de items[] em Ver uma assinatura |
| `item.itemId` | ID do item |
| `item.priceId` | ID do plano |
| `item.quantity` | Quantidade |
| `item.amount` | Valor unitário, em reais |
| `item.status` | PENDING_UPGRADE: o item passa a valer quando a pró-rata for paga |
| `replacedItemId` | Item substituído. Só na troca |
| `adjustmentItemId` | Ajuste de pró-rata lançado na próxima cobrança |
| `amounts` | Valores da alteração, em reais |
| `amounts.delta` | Diferença por período entre o valor novo e o antigo |
| `amounts.prorata` | Diferença proporcional aos dias restantes do ciclo |
| `amounts.recurringTotal` | Novo total recorrente da assinatura |
| `amounts.chargeTotal` | Valor cobrado agora |
| `prorataPeriod` | Dias considerados na pró-rata |
| `prorataPeriod.startDate` | Primeiro dia (formato: date) |
| `prorataPeriod.endDate` | Último dia (formato: date) |
| `prorataPeriod.days` | Quantidade de dias |
| `prorataPeriod.factor` | Fração do ciclo que os dias representam |
| `prorataPeriod.prorataAmount` | Valor da pró-rata, em reais |
| `effectiveAt` | Quando o valor novo passa a valer nas cobranças |
| `invoiceId` | Fatura da cobrança da diferença |
| `charge` | Cobrança da diferença |
| `charge.chargeId` | ID da cobrança |
| `charge.status` | PAID ou AWAITING_PAYMENT (valores: PAID, AWAITING_PAYMENT) |
| `charge.paymentType` | Forma de pagamento (valores: CREDIT_CARD, PIX, BOLETO, PIX_AUTOMATICO) |
| `charge.dueDate` | Vencimento. null no cartão (formato: date) |
| `payment` | Como pagar a cobrança da diferença |
| `payment.method` | Forma de pagamento |
| `payment.pix` | Pix copia e cola e QR Code. Só no Pix |
| `payment.pix.emv` | Código Pix copia e cola |
| `payment.pix.qrCode` | Imagem do QR Code em base64 |
| `payment.pix.transactionId` | Identificador da transação |
| `payment.boleto` | Dados do boleto (transactionId, dueDate e linha digitável em boletoUrl). Só no boleto |
| `payment.dueDate` | Vencimento (formato: date) |
| `type` | Resultado no formato antigo. Use mode e settlement |
| `chargeId` | Use charge.chargeId |
| `prorataAmount` | Use amounts.prorata |
| `newAmount` | Valor novo do item. Use item.amount |
| `recurringTotal` | Use amounts.recurringTotal |
| `amount` | Use amounts.chargeTotal |
| `paymentMethod` | Use payment.method |
| `pix` | Use payment.pix |
| `dueDate` | Use charge.dueDate |

### Resposta 400: 400 pagamento recusado

```json
{
    "error": {
        "message": "Cartão recusado por saldo insuficiente",
        "code": "PAYMENT_DECLINED",
        "details": { "declinedCode": "insufficient_funds" },
        "timestamp": "2026-09-24T12:00:00.000Z"
    }
}
```


### Resposta 404: 404

```json
{
    "error": {
        "message": "Item não encontrado",
        "code": "ITEM_NOT_FOUND",
        "details": null,
        "timestamp": "2026-09-24T12:00:00.000Z"
    }
}
```


---

Página: https://docs.validapay.com.br/referencia/put-trocar-plano-ou-quantidade  
Contrato OpenAPI: https://docs.validapay.com.br/openapi.json