Referencia de APISubscriptions

Subscriptions

/v1/subscriptions — ligan un Customer a un Plan y disparan los cobros recurrentes. Ver también el concepto Suscripción.

El objeto Subscription

{
  "id": "sub_01HZXK7QJ5M8Z9X2R3TVQ7A1B2",
  "customer_id": "cus_01HZXK7QJ5M8Z9X2R3TVQ7A1B2",
  "plan_id": "plan_01HZXK7QJ5M8Z9X2R3TVQ7A1B2",
  "status": "active",
  "cycle": "monthly",
  "current_period_start": "2026-08-24T00:00:00Z",
  "current_period_end": "2026-09-24T00:00:00Z",
  "next_charge_date": "2026-09-24T00:00:00Z",
  "default_payment_method_id": "pm_01HZXK7QJ5M8Z9X2R3TVQ7A1B2",
  "trial_end": null,
  "cancel_at_period_end": false,
  "failed_attempts": 0,
  "created_at": "2026-08-24T15:00:00Z"
}
CampoTipoDescripción
idstringIdentificador único
customer_idstringCliente dueño de la suscripción
plan_idstringPlan al que está suscrito
statusstringtrialing · active · past_due · paused · paused_insufficient_balance · canceled
cyclestringmonthly o annual
current_period_start / current_period_enddatetimeInicio y fin del periodo de facturación actual
next_charge_datedatetimePróxima fecha de cobro programada
default_payment_method_idstringMétodo de pago usado para los cobros
trial_enddatetime | nullFin del periodo de prueba, si aplica
cancel_at_period_endbooleanSi se cancelará al terminar el periodo actual
failed_attemptsintegerIntentos de cobro fallidos consecutivos
created_atdatetimeFecha de creación

Crear una suscripción

Las suscripciones se crean con el checkout hospedado, no con una llamada directa a este recurso: creas una checkout session, rediriges a tu cliente y Rekurra crea el Customer, el PaymentMethod y la Subscription en un solo flujo. Ver la guía Crear una suscripción y API → Checkout sessions.

Este recurso (/v1/subscriptions) se usa para consultar y gestionar suscripciones ya creadas: listarlas, obtener una, cancelar, pausar/reanudar, cambiar de plan, forzar un cobro y administrar addons.

También expone POST /v1/subscriptions para crear una suscripción directamente (sin checkout hospedado) cuando ya tienes un customer_id y un payment_method_id propios — por ejemplo, al migrar suscripciones desde otro proveedor. Acepta customer_id, plan_id, cycle, payment_method_id, trial_days, start_date y, al igual que la creación vía checkout, un metadata opcional (objeto libre, máx. 60 KB serializado). Ese metadata queda guardado en la suscripción y se repite en data.metadata de cada webhook que dispares para ella — ver Webhooks → metadata en cada evento.


Listar suscripciones

GET /v1/subscriptions

Filtros opcionales: ?status=, ?customer_id=, ?plan_id=, más paginación estándar.

curl "https://api.rekurra.dev/v1/subscriptions?status=active" \
  -H "Authorization: Bearer rk_live_XXXXXXXXXXXXXXXXXXXXXXXX"

Obtener una suscripción

GET /v1/subscriptions/{id}

curl https://api.rekurra.dev/v1/subscriptions/sub_01HZXK7QJ5M8Z9X2R3TVQ7A1B2 \
  -H "Authorization: Bearer rk_live_XXXXXXXXXXXXXXXXXXXXXXXX"

Errores posibles

Statuserror.typeCausa
404invalid_requestLa suscripción no existe

Cancelar una suscripción

POST /v1/subscriptions/{id}/cancel

{ "at_period_end": true }
curl -X POST https://api.rekurra.dev/v1/subscriptions/sub_01HZXK7QJ5M8Z9X2R3TVQ7A1B2/cancel \
  -H "Authorization: Bearer rk_live_XXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{ "at_period_end": true }'

Si at_period_end es true (u omitido), la suscripción sigue active hasta el fin del periodo actual con cancel_at_period_end: true, y luego pasa a canceled. Si es false, cancela de inmediato.


Pausar / reanudar

POST /v1/subscriptions/{id}/pause · POST /v1/subscriptions/{id}/resume

curl -X POST https://api.rekurra.dev/v1/subscriptions/sub_01HZXK7QJ5M8Z9X2R3TVQ7A1B2/pause \
  -H "Authorization: Bearer rk_live_XXXXXXXXXXXXXXXXXXXXXXXX"

Cambiar de plan

POST /v1/subscriptions/{id}/change-plan

Cambia el plan (y opcionalmente el ciclo) de una suscripción activa, con prorrateo por tiempo restante del periodo actual (igual que Stripe).

{ "plan_id": "plan_01HZ...", "cycle": "annual", "prorate": true }
CampoTipoRequeridoDescripción
plan_idstringSíPlan destino
cyclestringNomonthly o annual; si se omite, conserva el ciclo actual de la suscripción
proratebooleanNoPor defecto true. Ver semántica abajo

Semántica del prorrateo

Rekurra calcula la diferencia prorrateada entre el plan actual y el nuevo plan según la fracción de tiempo que falta del periodo de facturación vigente:

  • Upgrade (diferencia positiva) → se cobra de inmediato esa diferencia prorrateada, en el mismo momento en que aplicas el cambio, por el tiempo restante del periodo actual.
  • Downgrade (diferencia negativa) → no se reembolsa nada; el precio más bajo simplemente empieza a aplicarse desde el siguiente renovación (next_charge_date).
  • "prorate": false aplica el cambio de plan/ciclo sin el cobro inmediato — el nuevo precio rige a partir del siguiente ciclo, sin importar si es upgrade o downgrade.

Este endpoint dispara el webhook subscription.plan_changed. Si quieres saber cuánto se cobraría antes de aplicar el cambio, usa la vista previa de abajo.

curl -X POST https://api.rekurra.dev/v1/subscriptions/sub_01HZXK7QJ5M8Z9X2R3TVQ7A1B2/change-plan \
  -H "Authorization: Bearer rk_live_XXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{ "plan_id": "plan_01HZ...", "cycle": "annual", "prorate": true }'

Errores posibles

Statuserror.typeCausa
404invalid_requestLa suscripción o el plan_id no existen
400invalid_requestcycle inválido (ni monthly ni annual)

Vista previa de cambio de plan

POST /v1/subscriptions/{id}/change-plan/preview

Calcula cuánto se cobraría (o no) si aplicaras un cambio de plan sin aplicarlo: es un dry-run puro — no muta la suscripción, no dispara webhooks y no genera ningún cobro. Úsalo para mostrarle a tu usuario el monto de la diferencia antes de que confirme el upgrade/downgrade.

⚠️

La vista previa es solo para el ciclo de facturación actual de la suscripción: el cuerpo únicamente acepta plan_id (no cycle), así que previsualiza un cambio de plan manteniendo el ciclo vigente. Si necesitas cambiar de ciclo (ej. monthly → annual) a la vez que el plan, aplica directamente POST /{id}/change-plan con el cycle deseado — ese endpoint sí lo soporta, solo la vista previa está limitada al ciclo actual.

{ "plan_id": "plan_01HZ..." }
curl -X POST https://api.rekurra.dev/v1/subscriptions/sub_01HZXK7QJ5M8Z9X2R3TVQ7A1B2/change-plan/preview \
  -H "Authorization: Bearer rk_live_XXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{ "plan_id": "plan_01HZ..." }'

Response — 200 OK

{ "prorated_amount_cents": 850000, "immediate_charge": true }
CampoTipoDescripción
prorated_amount_centsintegerDiferencia prorrateada, en centavos de COP. Positiva en un upgrade, negativa en un downgrade
immediate_chargebooleantrue cuando prorated_amount_cents > 0 (upgrade) — es decir, lo que se cobraría de inmediato si aplicas el cambio con prorate: true. false en downgrades o si no hay diferencia

Errores posibles

Statuserror.typeCausa
404invalid_requestLa suscripción o el plan_id no existen

Forzar un reintento de cobro

POST /v1/subscriptions/{id}/charge-now

curl -X POST https://api.rekurra.dev/v1/subscriptions/sub_01HZXK7QJ5M8Z9X2R3TVQ7A1B2/charge-now \
  -H "Authorization: Bearer rk_live_XXXXXXXXXXXXXXXXXXXXXXXX"

Errores posibles (acciones)

Statuserror.typeCausa
404invalid_requestLa suscripción no existe
409invalid_requestLa acción no es válida para el estado actual (ej. pause en una ya canceled)
422insufficient_balanceSaldo prepago insuficiente para procesar el cobro
422wompi_errorWompi rechazó el cobro

Addons de la suscripción

El monto recurrente de una suscripción es la suma del precio del Plan más el precio de cada Addon activo adjunto a ella.

Adjuntar un addon

POST /v1/subscriptions/{id}/addons

{ "addon_id": "addon_01HZXK7QJ5M8Z9X2R3TVQ7A1B2", "prorate": true }
curl -X POST https://api.rekurra.dev/v1/subscriptions/sub_01HZXK7QJ5M8Z9X2R3TVQ7A1B2/addons \
  -H "Authorization: Bearer rk_live_XXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{ "addon_id": "addon_01HZXK7QJ5M8Z9X2R3TVQ7A1B2", "prorate": true }'

prorate es opcional y por defecto true: cobra de inmediato la parte proporcional del periodo actual (desde ahora hasta current_period_end). Si es false, el addon queda adjunto sin cobro inmediato y su costo se incluye a partir del siguiente ciclo de facturación.

Errores posibles

Statuserror.typeCausa
404invalid_requestLa suscripción o el addon no existen
409invalid_requestEl addon ya está adjunto a esta suscripción
409invalid_requestLa suscripción está canceled y no admite addons
422invalid_requestEl addon está desactivado (active: false)

Quitar un addon

DELETE /v1/subscriptions/{id}/addons/{addon_id}

curl -X DELETE https://api.rekurra.dev/v1/subscriptions/sub_01HZXK7QJ5M8Z9X2R3TVQ7A1B2/addons/addon_01HZXK7QJ5M8Z9X2R3TVQ7A1B2 \
  -H "Authorization: Bearer rk_live_XXXXXXXXXXXXXXXXXXXXXXXX"

Detiene el cobro del addon a partir del siguiente periodo; el periodo actual ya facturado no se reembolsa.

Listar los addons de una suscripción

GET /v1/subscriptions/{id}/addons

curl https://api.rekurra.dev/v1/subscriptions/sub_01HZXK7QJ5M8Z9X2R3TVQ7A1B2/addons \
  -H "Authorization: Bearer rk_live_XXXXXXXXXXXXXXXXXXXXXXXX"
{ "data": [ /* Addon[] */ ], "has_more": false, "next_cursor": null }