> ## Documentation Index
> Fetch the complete documentation index at: https://scaleup-c34c4386.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Downgrade de Assinatura

> Como implementar downgrade de plano com controle de periodo e revogacao de recursos na Chargefy

O downgrade permite que clientes migrem para um plano inferior quando precisam reduzir custos. Diferente do upgrade, o downgrade normalmente entra em vigor apenas no proximo ciclo de cobranca, garantindo que o cliente aproveite o que ja pagou.

## Downgrade vs cancelamento

| Acao | Resultado |
| - | - |
| **Downgrade** | Cliente continua assinante com menos recursos |
| **Cancelamento** | Cliente perde acesso ao final do periodo |

> [!TIP]
>
> Oferecer downgrade como alternativa ao cancelamento pode reduzir significativamente o churn. Considere apresentar a opcao de downgrade na pagina de cancelamento.

***

## Opcoes de downgrade

A Chargefy suporta dois modos de downgrade:

### 1. Downgrade ao final do periodo (recomendado)

O cliente mantem acesso ao plano atual ate o fim do ciclo ja pago. O novo preco entra em vigor no proximo ciclo.

```mermaid theme={null}
sequenceDiagram
    participant Cliente
    participant SeuApp
    participant Chargefy

    Cliente->>SeuApp: Solicitar downgrade
    SeuApp->>Chargefy: PATCH /subscriptions/:id (proration: false)
    Chargefy-->>SeuApp: Downgrade agendado
    Note over Cliente: Mantem acesso Pro ate fim do ciclo
    Note over Chargefy: No proximo ciclo...
    Chargefy->>Chargefy: Aplicar novo preco
    Chargefy-->>SeuApp: webhook subscription.updated
    SeuApp->>SeuApp: Revogar recursos Pro
```

### 2. Downgrade imediato

O novo preco e aplicado imediatamente. Pode gerar credito para o proximo ciclo.

***

## Passo 1: Agendar downgrade ao final do periodo

### Via SDK

```typescript theme={null}
// Downgrade de Pro (R$ 99,90/mes) para Basic (R$ 49,90/mes)
const downgraded = await chargefy.subscriptions.update('sub_xxxx', {
  productPriceId: 'price_basic_mensal_xxxx',
  proration: false, // aplicar no proximo ciclo
})

console.log('Downgrade agendado!')
console.log('Plano atual:', downgraded.product.name, '(ativo ate', downgraded.currentPeriodEnd, ')')
console.log('Mudanca agendada:', downgraded.scheduledChange?.productPriceId)
console.log('Novo valor a partir de:', downgraded.scheduledChange?.effectiveDate)
```

### Via cURL

```bash theme={null}
curl -X PATCH https://api.chargefy.io/v1/subscriptions/sub_xxxx \
  -H "Authorization: Bearer $CHARGEFY_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "productPriceId": "price_basic_mensal_xxxx",
    "proration": false
  }'
```

> [!NOTE]
>
> Com `proration: false`, nenhuma cobranca ou reembolso e gerado. O cliente simplesmente passa a pagar o valor do novo plano no proximo ciclo.

***

## Passo 2: Downgrade imediato com prorata

Se desejar aplicar o downgrade imediatamente, habilite a prorata. A Chargefy calcula o credito proporcional dos dias restantes do plano superior.

### Via SDK

```typescript theme={null}
const downgraded = await chargefy.subscriptions.update('sub_xxxx', {
  productPriceId: 'price_basic_mensal_xxxx',
  proration: true, // aplicar imediatamente com credito
})

console.log('Downgrade imediato!')
console.log('Credito gerado: R$', (downgraded.prorationCredit / 100).toFixed(2))
console.log('Novo valor mensal: R$', (downgraded.amount / 100).toFixed(2))
```

### Via cURL

```bash theme={null}
curl -X PATCH https://api.chargefy.io/v1/subscriptions/sub_xxxx \
  -H "Authorization: Bearer $CHARGEFY_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "productPriceId": "price_basic_mensal_xxxx",
    "proration": true
  }'
```

### Calculo do credito

```
Exemplo: Downgrade imediato no dia 16 de um ciclo mensal (31 dias)

Plano atual: Pro (R$ 99,90/mes)
Novo plano: Basic (R$ 49,90/mes)
Dias restantes: 15

Credito Pro: R$ 99,90 x (15/31) = R$ 48,34
Custo Basic: R$ 49,90 x (15/31) = R$ 24,15

Credito liquido: R$ 48,34 - R$ 24,15 = R$ 24,19
(aplicado como desconto no proximo ciclo)
```

***

## Passo 3: Cancelar downgrade agendado

Se o cliente mudar de ideia antes do downgrade ser efetivado, cancele a mudanca agendada.

### Via SDK

```typescript theme={null}
const restored = await chargefy.subscriptions.update('sub_xxxx', {
  cancelScheduledChange: true,
})

console.log('Downgrade cancelado — plano Pro mantido')
console.log('Mudanca agendada:', restored.scheduledChange) // null
```

### Via cURL

```bash theme={null}
curl -X PATCH https://api.chargefy.io/v1/subscriptions/sub_xxxx \
  -H "Authorization: Bearer $CHARGEFY_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "cancelScheduledChange": true
  }'
```

***

## Passo 4: Revogar recursos no momento certo

A parte mais importante do downgrade e revogar o acesso aos recursos do plano superior no momento correto.

### Para downgrade ao final do periodo

Revogue os recursos quando receber o webhook `subscription.updated` com o novo preco.

```typescript theme={null}
case 'subscription.updated':
  const { data } = event

  // Verificar se foi downgrade
  if (data.previousAmount && data.amount < data.previousAmount) {
    console.log('Downgrade efetivado!')
    console.log(`De R$ ${(data.previousAmount / 100).toFixed(2)} para R$ ${(data.amount / 100).toFixed(2)}`)

    // Atualizar banco de dados
    await db.subscriptions.update(
      { chargefy_id: data.id },
      {
        product_id: data.product.id,
        amount: data.amount,
        tier: data.product.metadata?.tier,
      }
    )

    // Revogar recursos do plano superior
    await downgradeFeatures(data.customer.id, data.product.metadata?.tier)

    // Notificar cliente
    await sendEmail(data.customer.email, 'plan_downgraded', {
      newPlan: data.product.name,
      newAmount: `R$ ${(data.amount / 100).toFixed(2)}`,
    })
  }
  break
```

### Funcao de revogacao de recursos

```typescript theme={null}
async function downgradeFeatures(customerId: string, newTier: string) {
  const featureLimits: Record<string, { users: number; storage: number; apiCalls: number }> = {
    basic: { users: 1, storage: 5, apiCalls: 1000 },
    pro: { users: 10, storage: 50, apiCalls: 10000 },
    enterprise: { users: -1, storage: -1, apiCalls: -1 }, // ilimitado
  }

  const limits = featureLimits[newTier]
  if (!limits) return

  // Atualizar limites no banco
  await db.organizations.update(
    { customer_id: customerId },
    {
      max_users: limits.users,
      max_storage_gb: limits.storage,
      max_api_calls: limits.apiCalls,
    }
  )

  // Verificar se organizacao excede novos limites
  const org = await db.organizations.findOne({ customer_id: customerId })
  if (limits.users > 0 && org.active_users > limits.users) {
    // Notificar admin que precisa reduzir usuarios
    await sendEmail(org.admin_email, 'reduce_users_required', {
      currentUsers: org.active_users,
      maxUsers: limits.users,
      deadline: '7 dias',
    })
  }
}
```

> [!WARNING]
>
> Para limites de usuarios, nao desative contas automaticamente. Envie um aviso ao admin e de um prazo (ex: 7 dias) para que ele escolha quais usuarios manter.

***

## Webhooks do downgrade

| Evento | Quando ocorre | Contexto |
| - | - | - |
| `subscription.updated` | Downgrade efetivado (inicio do novo ciclo ou imediato) | `data.amount` contem novo valor |
| `subscription.active` | Proximo ciclo cobrado com valor reduzido | Valor do plano inferior |

### Diferenciar upgrade de downgrade no webhook

```typescript theme={null}
case 'subscription.updated':
  const isUpgrade = event.data.amount > (event.data.previousAmount || 0)
  const isDowngrade = event.data.amount < (event.data.previousAmount || Infinity)

  if (isUpgrade) {
    await upgradeFeatures(event.data.customer.id, event.data.product.metadata?.tier)
  } else if (isDowngrade) {
    await downgradeFeatures(event.data.customer.id, event.data.product.metadata?.tier)
  }
  break
```

***

## Exemplo: Pagina de downgrade com confirmacao

```tsx src/components/DowngradePlan.tsx theme={null}
import { useState } from 'react'

interface DowngradeProps {
  subscriptionId: string
  currentPlan: string
  currentAmount: number
  targetPlan: string
  targetAmount: number
  currentPeriodEnd: string
}

export function DowngradePlan({
  subscriptionId, currentPlan, currentAmount,
  targetPlan, targetAmount, currentPeriodEnd,
}: DowngradeProps) {
  const [confirmed, setConfirmed] = useState(false)
  const [processing, setProcessing] = useState(false)
  const [mode, setMode] = useState<'end_of_period' | 'immediate'>('end_of_period')

  const formatCurrency = (cents: number) => `R$ ${(cents / 100).toFixed(2)}`
  const savings = currentAmount - targetAmount

  async function handleDowngrade() {
    setProcessing(true)

    const res = await fetch(`/api/subscriptions/${subscriptionId}/change-plan`, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        newPriceId: `price_${targetPlan}_mensal`,
        immediate: mode === 'immediate',
      }),
    })

    if (res.ok) {
      alert(mode === 'end_of_period'
        ? `Downgrade agendado para ${new Date(currentPeriodEnd).toLocaleDateString('pt-BR')}`
        : 'Downgrade aplicado imediatamente'
      )
      window.location.href = '/dashboard'
    } else {
      alert('Erro ao processar downgrade.')
      setProcessing(false)
    }
  }

  return (
    <div style={{ maxWidth: '500px', margin: '0 auto' }}>
      <h2>Downgrade de plano</h2>

      <div style={{ background: '#fef3c7', padding: '1rem', borderRadius: '8px', marginBottom: '1.5rem' }}>
        <p><strong>Atencao:</strong> Ao fazer downgrade, voce perdera acesso aos recursos do plano {currentPlan}.</p>
      </div>

      <div style={{ border: '1px solid #e5e7eb', borderRadius: '8px', padding: '1.5rem', marginBottom: '1rem' }}>
        <p><strong>Plano atual:</strong> {currentPlan} — {formatCurrency(currentAmount)}/mes</p>
        <p><strong>Novo plano:</strong> {targetPlan} — {formatCurrency(targetAmount)}/mes</p>
        <p style={{ color: '#16a34a' }}><strong>Economia:</strong> {formatCurrency(savings)}/mes</p>
      </div>

      <div style={{ marginBottom: '1.5rem' }}>
        <p><strong>Quando aplicar?</strong></p>
        <label style={{ display: 'block', padding: '0.5rem 0' }}>
          <input
            type="radio"
            checked={mode === 'end_of_period'}
            onChange={() => setMode('end_of_period')}
          />
          {' '}Ao final do periodo atual ({new Date(currentPeriodEnd).toLocaleDateString('pt-BR')})
        </label>
        <label style={{ display: 'block', padding: '0.5rem 0' }}>
          <input
            type="radio"
            checked={mode === 'immediate'}
            onChange={() => setMode('immediate')}
          />
          {' '}Imediatamente (credito proporcional aplicado)
        </label>
      </div>

      <label style={{ display: 'flex', alignItems: 'center', gap: '0.5rem', marginBottom: '1rem' }}>
        <input type="checkbox" checked={confirmed} onChange={e => setConfirmed(e.target.checked)} />
        Entendo que perderei acesso aos recursos do plano {currentPlan}
      </label>

      <button
        onClick={handleDowngrade}
        disabled={!confirmed || processing}
        style={{
          width: '100%', padding: '0.75rem',
          background: confirmed ? '#dc2626' : '#d1d5db',
          color: 'white', border: 'none', borderRadius: '6px',
          cursor: confirmed && !processing ? 'pointer' : 'not-allowed',
        }}
      >
        {processing ? 'Processando...' : 'Confirmar downgrade'}
      </button>
    </div>
  )
}
```

***

## Boas praticas

* **Prefira downgrade ao final do periodo** para evitar complexidade de reembolsos
* **Avise com antecedencia** quais recursos serao perdidos antes de confirmar
* **De prazo para ajustes** quando o cliente excede os limites do novo plano (ex: usuarios)
* **Ofereça alternativas** — desconto temporario pode ser mais vantajoso que downgrade
* **Registre o motivo** do downgrade para analise de churn

***

## Proximos passos

> [card] [Upgrade de Assinatura](https://scaleup-c34c4386.mintlify.site/guides/subscription-upgrades.md)
>
> Implemente o fluxo reverso — upgrade de plano.

> [card] [Multiplas Assinaturas](https://scaleup-c34c4386.mintlify.site/guides/allow-multiple-subscriptions.md)
>
> Permita que clientes tenham mais de uma assinatura ativa.


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