Billing API
Endpoints críticos para criação de checkout, confirmação de subscrição e portal de gestão.
reference • updated 2026-03-17
Objetivo
Operar o ciclo completo de faturação recorrente: iniciar checkout, confirmar estado pós-pagamento e abrir portal self-service sem perder rastreabilidade por organização.
Endpoints e contrato operativo
| Endpoint | Quando usar | Requisitos-chave |
|---|---|---|
POST /api/billing/subscription/checkout?org={slug}&mode={test|live} | iniciar subscrição ou upgrade | Bearer token Beacon, papel OWNER/ADMIN, plan e billingCycle |
POST /api/billing/subscription/confirm?org={slug}&mode={test|live} | reconciliar estado após retorno do checkout | contexto de organização; body opcional com sessionId |
POST /api/billing/subscription/portal?org={slug}&mode={test|live} | abrir gestão self-service de plano/método | cliente Stripe já associado e subscrição elegível |
Fluxo recomendado
11) Criar checkout
Gera sessão com plano, ciclo e contexto de organização. Guarda o
checkoutSessionIdpara rastreio.22) Redirecionar utilizador
Envia o utilizador para
redirectUrle evita submits concorrentes no frontend.33) Confirmar resultado
Após o retorno do checkout, chama
subscription/confirm. Se tiveres osession_iddo success URL, envia-o comosessionId.44) Expor portal
Disponibiliza
subscription/portalapenas quando já existe cliente/subscrição Stripe gerível.
Exemplo de criação de checkout
curl -X POST "https://test.beacon.pt/api/billing/subscription/checkout?org=acme&mode=test" \
-H "Authorization: Bearer <beacon_session_token>" \
-H "Content-Type: application/json" \
-d '{
"plan": "plus",
"billingCycle": "monthly"
}'
{
"ok": true,
"checkoutSessionId": "cs_123",
"redirectUrl": "https://checkout.stripe.com/c/pay/cs_123",
"plan": "PLUS",
"billingCycle": "monthly",
"context": {
"mode": "test",
"organizationSlug": "acme"
}
}
Confirmação e consistência
- O checkout não expõe
Idempotency-Keypública; a chave usada na Stripe é gerada no servidor. - Se já existir checkout pendente para o mesmo plano e ciclo, a API pode reutilizar a sessão pendente e devolver
pending: true. - Se existir checkout pendente para outro plano ou se a organização já tiver subscrição activa, a API responde com
409. - Não assumes sucesso apenas com o redirect concluído; o estado final deve ser confirmado por
subscription/confirme por eventos Stripe.
Exemplo de confirmação
curl -X POST "https://test.beacon.pt/api/billing/subscription/confirm?org=acme&mode=test" \
-H "Authorization: Bearer <beacon_session_token>" \
-H "Content-Type: application/json" \
-d '{"sessionId":"cs_test_a1b2c3"}'
{
"ok": true,
"subscription": {
"plan": "PLUS",
"status": "ACTIVE"
},
"context": {
"mode": "test",
"organizationSlug": "acme"
}
}
Erros frequentes
| Código | Causa típica | Ação recomendada |
|---|---|---|
400 | org, plan ou billingCycle inválidos | corrigir payload/query e repetir |
401 | token inválido ou expirado | renovar sessão Beacon e repetir |
403 | utilizador sem OWNER/ADMIN | rever permissões da organização |
409 | subscrição activa, checkout pendente ou sessão ainda não pronta | usar o estado existente ou aguardar alguns segundos |
404 | organização inexistente ou inactiva | confirmar slug e contexto activo |
Checklist de go-live
- Fluxo testado em
mode=testcom sucesso e sem estados pendentes. - Alertas ativos para falhas de confirmação e aumento de retries.
- Portal restrito por perfil e com auditoria de acesso.