# Executar upgrade ou downgrade de plano

URL: https://staging.pagpolar.com/docs/referencia/assinaturas/change-subscription-plan

> Executa a troca de plano de uma assinatura. A direção (upgrade ou downgrade) é
determinada automaticamente pela comparação de preço entre o plano atual e o novo plano.

- **Upgrade**: cobra a diferença proporcional imediatamente, no cartão salvo da assinatura
  (`payment_choice=current`) ou em um novo cartão informado no corpo da requisição
  (`payment_choice=new_card`).
- **Upgrade no cartão aprovado, mas sem a troca concluída na hora** (por exemplo, falha no
  gateway ao atualizar o plano): a resposta é `200` com `upgrade.status` `pending`, e a venda
  da diferença continua em `PROCESSING`. A troca é confirmada quando o gateway avisa o pagamento; nesse
  momento a venda passa a `PAID` e o webhook `TRANSACTION_PAID` é enviado. Não cobre de novo.
- **Downgrade**: não gera cobrança imediata; é agendado para entrar em vigor na próxima
  renovação da assinatura.

O header `Idempotency-Key` é **obrigatório**. Em caso de timeout, reenvie a requisição
com a mesma chave: a resposta original será devolvida sem processar a troca duas vezes.

`POST /subscriptions/{id}/plan-change`

## Autenticação

- Token Bearer no header `Authorization` (esquema `BearerAuth`). Token de acesso devolvido por POST /auth/token. Envie como "Authorization: Bearer <token>". Vale 24 horas.

## Parâmetros de caminho

| Parâmetro | Tipo | Obrigatório | Descrição |
| --- | --- | --- | --- |
| `id` | texto (uuid) | sim | — |

## Parâmetros de header

| Parâmetro | Tipo | Obrigatório | Descrição |
| --- | --- | --- | --- |
| `Idempotency-Key` | texto | sim | Exemplo: `3a2b1c4d-9e8f-4a7b-8c6d-5e4f3a2b1c0d`. |

## Corpo da requisição

Content-type: `application/json`.

| Campo | Tipo | Obrigatório | Descrição |
| --- | --- | --- | --- |
| `new_product_price_id` | texto (uuid) | sim | — |
| `payment_choice` | enum | não | Só é relevante para upgrade. Ignorado em downgrade. Valores: `current`, `new_card`. |
| `card` | objeto | não | Obrigatório somente quando payment_choice=new_card |
| `card.number` | texto | não | — |
| `card.holder_name` | texto | não | — |
| `card.holder_document` | texto | não | CPF (11 dígitos) ou CNPJ (14 dígitos) do titular, com ou sem pontuação. Fora disso, 400. |
| `card.exp_month` | inteiro | não | — |
| `card.exp_year` | inteiro | não | — |
| `card.cvv` | texto | não | — |

### Exemplo do corpo

Upgrade cobrando no cartão salvo:

```json
{
  "new_product_price_id": "b2c3d4e5-f6a7-4b8c-9d0e-1f2a3b4c5d6e",
  "payment_choice": "current"
}
```

Upgrade com novo cartão:

```json
{
  "new_product_price_id": "b2c3d4e5-f6a7-4b8c-9d0e-1f2a3b4c5d6e",
  "payment_choice": "new_card",
  "card": {
    "number": "4111111111111111",
    "holder_name": "FULANO DE TAL",
    "holder_document": "12345678909",
    "exp_month": 12,
    "exp_year": 2030,
    "cvv": "123"
  }
}
```

Downgrade (agendado para a próxima renovação):

```json
{
  "new_product_price_id": "c3d4e5f6-a7b8-4c9d-0e1f-2a3b4c5d6e7f"
}
```

## Respostas

### 200 — Troca de plano processada

| Campo | Tipo | Obrigatório | Descrição |
| --- | --- | --- | --- |
| `data` | [Troca de plano](/docs/referencia/entidades/troca-de-plano) | não | — |

#### Exemplo

Upgrade cobrado via PIX:

```json
{
  "data": {
    "type": "UPGRADE",
    "upgrade": {
      "transaction_id": "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d",
      "charge_amount": 49.9,
      "status": "pending",
      "pix": {
        "qr_code": "00020126..."
      }
    }
  }
}
```

Downgrade agendado:

```json
{
  "data": {
    "type": "DOWNGRADE"
  }
}
```

## Erros

| Status | Descrição |
| --- | --- |
| `400` | Dados inválidos ou Idempotency-Key ausente |
| `401` | Token ausente, inválido ou expirado, ou credencial revogada ou expirada. Chame POST /auth/token para obter um token novo. |
| `403` | Produto não permite troca de plano pelo cliente, plano não selecionável ou IP não autorizado |
| `404` | Assinatura ou plano não encontrado |
| `409` | Requisição idêntica em processamento |
| `429` | Limite de requisições excedido |
| `503` | Serviço de limite indisponível — repita a requisição com a mesma Idempotency-Key |

Lista completa de códigos e como tratá-los: [Erros](/docs/guias/fundamentos/erros).
