Billing API
Endpoints clave para creación de checkout, confirmación de suscripción y portal de cliente.
reference • updated 2026-03-17
Objetivo
Operar el ciclo completo de facturación recurrente: iniciar checkout, confirmar estado post-pago y habilitar autoservicio con trazabilidad por organización.
Endpoints y contrato operativo
| Endpoint | Cuándo usar | Requisitos clave |
|---|---|---|
POST /api/billing/subscription/checkout?org={slug}&mode={test|live} | iniciar suscripción o upgrade | bearer token Beacon, OWNER/ADMIN, plan y billingCycle |
POST /api/billing/subscription/confirm?org={slug}&mode={test|live} | reconciliar estado tras el retorno del checkout | contexto de organización; body opcional con sessionId |
POST /api/billing/subscription/portal?org={slug}&mode={test|live} | abrir gestión self-service | cliente Stripe asociado y suscripción elegible |
Flujo recomendado
11) Crear checkout
Genera sesión con plan, ciclo y contexto de organización. Guarda
checkoutSessionId.22) Redirigir usuario
Envía al usuario a
redirectUrly evita submits concurrentes en frontend.33) Confirmar estado
Tras el retorno del checkout, llama
subscription/confirm. Si tienes elsession_idde la success URL, envíalo comosessionId.44) Exponer portal
Genera sesiones de portal solo cuando ya existe un cliente/suscripción Stripe gestionable.
Ejemplo de creación 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"
}
}
Confirmación y consistencia
- El checkout no expone un
Idempotency-Keypúblico; la clave Stripe se genera en servidor. - Si ya existe un checkout pendiente para el mismo plan y ciclo, la API puede reutilizarlo y devolver
pending: true. - Si existe un checkout pendiente para otro plan o la organización ya tiene una suscripción activa, la API responde con
409. - No asumas éxito solo por el redirect; confirma el estado final por
subscription/confirmy eventos Stripe.
Ejemplo de confirmación
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"
}
}
Errores frecuentes
| Código | Causa típica | Acción recomendada |
|---|---|---|
400 | org, plan o billingCycle inválidos | corregir payload/query y reintentar |
401 | token inválido/expirado | renovar la sesión Beacon y reintentar |
403 | el usuario no es OWNER/ADMIN | revisar permisos de la organización |
409 | suscripción activa, checkout pendiente o sesión aún no lista | reutilizar el estado existente o esperar unos segundos |
404 | organización inexistente o inactiva | confirmar slug y contexto activo |
Checklist de go-live
- Flujo completo validado en
mode=testsin estados pendientes. - Alertas activas para fallos de confirmación y picos de retries.
- Portal limitado por perfil con trazabilidad de acceso.