Aller au contenu

Prévia da troca de plano

POST/api/subscriptions/{id}/change-tier/quote

Auth
Jeton requis
Clé d’API:
Clé d’API non acceptée
X-CommunityId
X-CommunityId Envoyez le X-CommunityId de la communauté où l’opération a lieu.
Les descriptions des endpoints viennent directement de la spécification de l’API et sont en portugais pour l’instant. L’interface autour est traduite.

Sem efeito: diz o que `POST /change-tier` faria com o mesmo corpo. `:id` é a assinatura do plano, do próprio membro, na comunidade do X-CommunityId; de outra pessoa ou de outra comunidade responde 404. As recusas são as mesmas de `change-tier`. `changeType`: `UPGRADE` (opção mais cara na mesma periodicidade), `DOWNGRADE`, `SAME_PRICE` ou `INTERVAL_CHANGE` (mensal ↔ anual). `mode`: `IMMEDIATE` só para `UPGRADE` com `immediate` ausente ou `true` e sem adicional que a opção nova deixe de oferecer; o resto é `SCHEDULED`, para `effectiveDate` (o fim do período pago), e `scheduledReason` diz por quê (`DOWNGRADE`, `SAME_PRICE`, `INTERVAL_CHANGE`, `ADD_ONS_END` ou `REQUESTED`). No `IMMEDIATE`: `prorataAmount` é a diferença de preço proporcional aos `remainingDays` de `periodDays`; com menos de 3 dias ou menos de R$ 10, `floorApplied = true` e `amountDueNow = 0` (troca na hora, sem cobrança). `amountToCharge` soma a taxa da plataforma quando o comprador a paga (`feePayer = BUYER`). A cobrança é no cartão salvo (`cardRequired`, `hasSavedCard`), em até `maxInstallments` parcelas (meses restantes no anual; 1 no mensal). Sempre: `newPrice` (preço por período da opção nova), `nextChargeDate` e `nextChargeTotal` (a primeira cobrança no preço novo, com os adicionais que continuam); `addOns` (cada adicional cobrado com o plano: `outcome = KEPT` continua, no valor da periodicidade nova, `newAmount`; `ENDS` termina com a troca); `contract` (`commitmentEndsAt` depois da troca; `carriedOver = true` quando o contrato atual continua valendo); `couponEnds` (o cupom da assinatura deixa de valer na troca); `replacesScheduledChange` (a troca agendada que esta substituiria, ou `null`). **Adicionais na troca:** `addOnProductIds` (opcional) são adicionais que entram com a troca. A regra é a do checkout: cada um precisa estar na lista do plano de destino, ser assinatura mensal à venda, aparecer uma vez e não estar assinado ainda; senão 400 `param = addOnProductIds`. Em `addOns`, além de `KEPT` e `ENDS`, cada um aparece com `outcome = JOINS` (`newAmount` por período da opção nova, `joinsAt` e `amountDueNow`). No `IMMEDIATE`, o pedido é um só: `lines` traz a linha do plano (`kind = PLAN`, a diferença proporcional) e uma por adicional (`kind = ADD_ON`, o valor do período proporcional aos mesmos dias), cada uma com o seu piso (`floorApplied`) e `feePayer`; a taxa fixa da plataforma entra uma vez, na primeira linha cobrada. `prorataAmount`, `amountDueNow` e `amountToCharge` são os totais do pedido. Na troca que vale na renovação, os adicionais entram junto, nessa renovação, sem cobrança hoje (`lines = []`); um plano que renova por PIX ou boleto só aceita adicionais numa troca cobrada agora (400 `monetization.subscription.changeTierAddOnsNeedCard`). `nextChargeTotal` já soma os adicionais que entram. **Cartão:** `needsCard = true` quando a troca cobra agora e não há cartão salvo válido: a tela pede o cartão e manda `cardToken` em `POST /change-tier`. **Meios de pagamento:** `allowedMethods` traz os meios desse pedido pela regra do checkout (os meios aceitos pela opção de destino): `[{ method, totalAmount, cashAmount, installmentOptions? }]`, com `method` em `CREDIT_CARD`, `PIX` ou `BOLETO`. O total à vista é o mesmo em todos (a taxa da plataforma independe do meio); no cartão, `installmentOptions` (`[{ installments, percent, totalAmount, installmentAmount }]`) como no `calculate-price`, até `maxInstallments`. O boleto só aparece quando faltam mais de 4 dias para a renovação (3 de vencimento + 1 de compensação). Sem cobrança agora (agendada ou abaixo do piso), `allowedMethods = []`. `pendingChange`: a troca que espera o PIX ou o boleto (`purchaseId`, `orderId`, `paymentMethod`, `newProductId`, `addOnProductIds`, `amount`, `currency`, `pixCode`, `qrCode`, `boletoUrl`, `boletoBarcode`, `expiresAt`, `createdAt`), ou `null`; enquanto ela existe, `POST /change-tier` responde 409. Uma opção de plano só de link (`link_only`) nunca é destino (400 `param = newProductId`). **Empresa:** o admin da empresa com vínculo vivo age como o assinante na assinatura da empresa (`companyId` na resposta); funcionário da empresa que não é admin recebe 403 (`monetization.company.adminOnly`); quem não tem relação com ela, 404.

Paramètres

NomEmplacementTypeDescription
idobligatoirepathstring (uuid)

En-têtes

NomTypeDescription
X-CommunityIdfacultatifstring (uuid)ID da comunidade em que a operação acontece. Obrigatório na maioria dos endpoints com escopo de comunidade.

Corps de la requête application/json

NomTypeDescription
newProductIdobligatoirestring (uuid)A opção de plano de destino
immediatefacultatifbooleanAusente vale `true` aqui: a prévia do upgrade na hora
addOnProductIdsfacultatifstring (uuid)[]Adicionais que entram com a troca.

Réponses

StatutDescription
200Operação realizada com sucesso.
400Requisição inválida — falha de validação.
401Token ausente, inválido ou expirado; token de outra comunidade (o `X-CommunityId` ou o `communityId` do corpo não é o do token); token antigo ou de uma sessão encerrada (troca de senha, convite aceito). Nesses casos a mensagem pede para entrar de novo (`auth.signInAgain`).
403Autenticado, mas sem permissão para esta operação.
404Recurso não encontrado.
409Conflito com o estado atual do recurso.
500Erro interno do servidor.

Exemple curl

curl -X POST "https://api.memberfy.net/api/subscriptions/<id>/change-tier/quote" \
  -H "Authorization: Bearer $TOKEN" \
  -H "X-CommunityId: $COMMUNITY_ID" \
  -H "Content-Type: application/json" \
  -d '{"newProductId":"00000000-0000-0000-0000-000000000000"}'