Skip to content

API de facturación

Estos endpoints públicos permiten gestionar planes de cuenta, saldo, add-ons de proyecto, cupones, referidos y la renovación. Los callbacks del proveedor de pago no forman parte de la API pública.

GET /api/billing/overview

Devuelve el resumen de facturación de la cuenta actual.

GET /api/billing/wallet/overview

Devuelve el resumen del saldo y del monedero de la cuenta.

POST /api/billing/wallet/crypto-topup

Crea una recarga de saldo con criptomonedas. Si se proporciona returnUrl o cancelUrl, la API establece su parámetro de consulta externalReference con la referencia exacta de la recarga creada y sustituye cualquier valor anterior. Conserva esa referencia durante la redirección del proveedor.

POST /api/billing/wallet/topup/refresh

Actualiza el estado de la recarga identificada por topupId o externalReference. Usa un identificador devuelto por la respuesta de creación o por la URL de retorno; no deduzcas el destino a partir de la recarga más reciente. Una página de retorno no debe solicitar la actualización si falta el identificador, está repetido o entra en conflicto con otro identificador.

POST /api/billing/account-plan/balance-purchase

Compra o mejora un plan de cuenta usando el saldo del monedero.

Cuerpo de la solicitud:

CampoObligatorioDescripción
planIdPlan de destino: advanced o pro.
durationMonthsPeriodo de facturación: 1, 3, 6 o 12 meses.
autoRenewNoIndica si la suscripción resultante se renueva automáticamente. Si se omite, su valor predeterminado es false.
requestIdNoClave de idempotencia de 8-128 caracteres unreserved de RFC 3986: A-Z, a-z, 0-9, ., _, ~ y -. Puede omitirse por compatibilidad con clientes anteriores, pero se recomienda usarla.

Usa un requestId estable para una única intención confirmada por el usuario. Si se produce un timeout u otro resultado desconocido, repite la solicitud con el mismo payload y requestId. Una repetición exacta devuelve los subscriptionId e invoiceId originales sin un segundo cargo al monedero. Se rechaza la reutilización de ese requestId con otro planId, durationMonths o autoRenew. Genera un requestId nuevo para una nueva intención de compra. Sin requestId, la solicitud sigue aceptándose por compatibilidad con clientes anteriores, pero los intentos HTTP separados no son retry-safe ni idempotentes.

Caso de idempotenciaComportamiento obligatorio
same-intentEnvía el same-requestId con el same-payload.
exact-replayDevuelve original-subscriptionId y original-invoiceId con no-second-debit.
conflicting-payloadLa solicitud es rejected.
new-intentGenera un new-requestId.
missing-requestIdMantiene backward-compatible, pero es not-retry-safe y not-idempotent-across-HTTP-attempts.

Respuesta: HTTP 200 OK.

CampoObligatorioDescripción
subscriptionIdIdentificador de la suscripción activada.
invoiceIdIdentificador de la factura pagada.

POST /api/billing/account-plan/checkout

Crea un checkout para un plan de cuenta.

POST /api/billing/account-plan/crypto-checkout

Crea un checkout directo con criptomonedas para un plan de cuenta.

POST /api/billing/project-addon/balance-purchase

Compra con saldo un add-on de acceso gratuito para un proyecto.

Cuerpo de la solicitud:

CampoObligatorioDescripción
projectFullnameNombre completo del proyecto que recibirá el add-on.
addonCodeIdentificador del add-on: project-free-access.
durationMonthsPeriodo de facturación: 1, 3, 6 o 12 meses.
autoRenewNoIndica si la suscripción resultante se renueva automáticamente. Si se omite, su valor predeterminado es false.
requestIdNoClave de idempotencia de 8-128 caracteres unreserved de RFC 3986: A-Z, a-z, 0-9, ., _, ~ y -. Puede omitirse por compatibilidad con clientes anteriores, pero se recomienda usarla.

Usa un requestId estable para una única intención confirmada por el usuario. Si se produce un timeout u otro resultado desconocido, repite la solicitud con el mismo requestId y el mismo payload completo, incluidos projectFullname, addonCode, durationMonths y autoRenew. Una repetición exacta devuelve los subscriptionId e invoiceId originales sin un segundo cargo al monedero. Se rechaza la reutilización de ese requestId tras cambiar cualquiera de esos campos. Genera un requestId nuevo para una nueva intención de compra. Sin requestId, la solicitud sigue aceptándose por compatibilidad con clientes anteriores, pero los intentos HTTP separados no son retry-safe ni idempotentes.

Caso de idempotenciaComportamiento obligatorio
same-intentEnvía el same-requestId con el same-full-payload: projectFullname, addonCode, durationMonths y autoRenew.
exact-replayDevuelve original-subscriptionId y original-invoiceId con no-second-debit.
conflicting-payloadCambiar projectFullname, addonCode, durationMonths o autoRenew hace que la solicitud sea rechazada (rejected).
new-intentGenera un new-requestId.
missing-requestIdMantiene backward-compatible, pero es not-retry-safe y not-idempotent-across-HTTP-attempts.

Respuesta: HTTP 200 OK.

CampoObligatorioDescripción
subscriptionIdIdentificador de la suscripción activada del add-on del proyecto.
invoiceIdIdentificador de la factura pagada.

POST /api/billing/project-addon/checkout

Crea un checkout para un add-on de proyecto.

Si el checkout alojado correspondiente sigue pendiente, un reintento devuelve los subscriptionId, invoiceId y externalReference existentes junto con un nuevo formulario checkout firmado. Envía el último formulario devuelto.

Caso del checkoutComportamiento obligatorio
pending-hosted-retryDevuelve los subscriptionId, invoiceId y externalReference existentes con un nuevo formulario checkout firmado.

POST /api/billing/project-addon/crypto-checkout

Crea un checkout directo con criptomonedas para un add-on de proyecto.

Si un checkout pendiente ya está vinculado a una orden del proveedor, el reintento devuelve los mismos providerOrderId y paymentUrl. Si la creación o vinculación de la orden tiene un resultado ambiguo, el checkout permanece pendiente y falla de forma cerrada: no inicies otro hasta cancelar o reconciliar el pendiente.

Caso del checkoutComportamiento obligatorio
pending-linked-order-retryDevuelve los mismos providerOrderId y paymentUrl.
ambiguous-provider-creation-or-linkageMantiene fail-closed-pending y exige cancel-or-reconcile-before-new-attempt.

POST /api/billing/coupon/redeem

Canjea un cupón para un plan de cuenta de pago.

Cuerpo de la solicitud:

CampoObligatorioDescripción
codeCódigo del cupón. Se eliminan los espacios iniciales y finales (trim) y la comparación es case-insensitive.

El periodo pagado del plan de cuenta del cupón se aplica una sola vez. Según el periodo de pago actual, el canje lo amplía, superpone el periodo aplicable o inicia un periodo nuevo.

Caso de canjeComportamiento obligatorio
code-normalizationAplica trim y comparación case-insensitive.
same-account-retryDevuelve same-couponId, same-subscriptionId y same-invoiceId con no-second-application.
unavailable-or-unsafeUn cupón redeemed-by-another-account, deleted, invalid o con unsafe-subscription-lineage debe hacer fail-closed.
paid-account-plan-periodUsa extend, overlay o inicia un new-term, as-applicable.

Respuesta: HTTP 200 OK.

CampoObligatorioDescripción
couponIdIdentificador del cupón canjeado.
subscriptionIdIdentificador de la suscripción resultante del plan de cuenta.
invoiceIdIdentificador de la factura pagada del cupón.

POST /api/billing/coupon/gift-purchase

Compra un cupón regalo usando el saldo del monedero.

Cuerpo de la solicitud:

CampoObligatorioDescripción
planIdPlan de cuenta de pago: advanced o pro.
durationMonthsDuración del cupón: 1, 3, 6 o 12 meses.
requestIdNoClave de idempotencia de 8-128 caracteres unreserved de RFC 3986: A-Z, a-z, 0-9, ., _, ~ y -. Puede omitirse por compatibilidad con clientes anteriores, pero se recomienda usarla.

Dentro de la misma cuenta, usa un requestId estable para una única compra de regalo confirmada. Si se produce un timeout u otro resultado desconocido, repite la solicitud con el mismo plan y la misma duración.

Caso de compraComportamiento obligatorio
same-intentEnvía el same-requestId, same-planId y same-durationMonths.
exact-replayDevuelve el same-couponId y el same-code con no-second-debit y no-second-referral-reward.
conflicting-payloadReutilizar el identificador de solicitud con otro plan o duración es rejected.
new-intentGenera un new-requestId.
missing-requestIdMantiene backward-compatible, pero es not-retry-safe y not-idempotent-across-HTTP-attempts.

Respuesta: HTTP 200 OK.

CampoObligatorioDescripción
couponIdIdentificador del cupón regalo comprado.
codeCódigo que se entrega al destinatario del cupón.

GET /api/billing/referral/overview

Devuelve el resumen del saldo y del enlace de referidos.

POST /api/billing/referral/link/create

Crea un enlace de referido.

POST /api/billing/referral/claim

Reclama un código de referido.

POST /api/billing/subscription/update-renewal

Actualiza la renovación automática de la facturación.

POST /api/billing/crypto-checkout/refresh

Actualiza el estado de un checkout con criptomonedas.

Para un add-on de proyecto, un pago tardío tras cancelar el checkout o transferir el proyecto no reactiva la suscripción ni el acceso al proyecto. El pago pasa a reconciliación o reembolso.

Caso del ciclo de vidaComportamiento obligatorio
late-payment-after-cancel-or-project-transferConserva no-reactivation y usa reconciliation-or-refund.

POST /api/billing/crypto-checkout/cancel

Cancela un checkout con criptomonedas.

La cancelación es definitiva para la activación del add-on del proyecto. Si el pago se detecta más tarde, incluso después de transferir el proyecto, no se reactivan la suscripción ni el acceso y se aplica reconciliación o reembolso.

Caso del ciclo de vidaComportamiento obligatorio
late-payment-after-cancel-or-project-transferConserva no-reactivation y usa reconciliation-or-refund.