Suscripciones
Lista, consulta, cancela y gestiona las suscripciones de tus links recurrentes.
Las suscripciones se crean cuando un comprador paga uno de los planes de tu link recurrente. Polar (el Merchant of Record) cobra cada ciclo y acredita cada renovación en tu saldo de Polar, y puedes enterarte de cada cobro por el webhook subscription.payment.completed.
El objeto Subscription
{
"id": "66f1c1e2c8a4b0d1f2e3a4b7",
"provider": "polar",
"polarSubscriptionId": "5c2e7a1b-...",
"paymentLinkId": "66f1c1e2c8a4b0d1f2e3a4b6",
"paymentLinkPriceId": "66f1c1e2c8a4b0d1f2e3a4c1",
"price": {
"amountCents": 900,
"currency": "usd",
"interval": "month",
"intervalCount": 1,
"trialPeriodDays": null,
"seats": 1,
"seatTotalCents": 900,
"perSeatAmountCents": null
},
"status": "active",
"customerEmail": "cliente@ejemplo.com",
"reference": "ORD-1001",
"metadata": null,
"currentPeriodStart": "2026-01-02T12:00:00.000Z",
"currentPeriodEnd": "2026-02-02T12:00:00.000Z",
"canceledAt": null,
"cancelAtPeriodEnd": false,
"trialStart": null,
"trialEnd": null,
"sandbox": false,
"createdAt": "2026-01-02T12:00:00.000Z"
}Estados posibles (status): active, trialing, past_due, canceled, unpaid, pending, incomplete, incomplete_expired y paused (los de Polar). El filtro status del listado acepta active, trialing, past_due, canceled, unpaid, pending e incomplete.
provider es siempre "polar" y polarSubscriptionId trae el id de la suscripción en Polar.
reference y metadata
son los tuyos del checkout que creó la suscripción (ver Identificar cada venta);
el listado acepta ?reference=. trialStart y trialEnd son null, y price.seatTotalCents es el total por ciclo que informa Polar.
paymentLinkId y paymentLinkPriceId vienen vacíos si el producto de Polar no es de un link de
vexorpay (p. ej. uno creado directamente en Polar).
Listar suscripciones
GET /api/v1/subscriptions
| Query param | Descripción |
|---|---|
status | Filtra por estado. |
payment_link_id | Filtra por link. |
limit | Tamaño de página (default 10, máx 100). |
starting_after / ending_before | Paginación por cursor (id de suscripción). |
curl "https://api.vexorpay.com/api/v1/subscriptions?status=active" \
-H "Authorization: Bearer vxp_live_tu_clave"La respuesta usa el formato de lista con data, has_more y total_count.
Ver una suscripción
GET /api/v1/subscriptions/{id}
El entorno lo define la API key: con una clave vxp_test_... operas sobre suscripciones de prueba.
curl "https://api.vexorpay.com/api/v1/subscriptions/66f1c1e2c8a4b0d1f2e3a4b7" \
-H "Authorization: Bearer vxp_live_tu_clave"Cancelar una suscripción
POST /api/v1/subscriptions/{id}/cancel
Programa la cancelación en Polar al final del período (cancelAtPeriodEnd: true): el cliente conserva el acceso hasta que termine el ciclo pago y no se le vuelve a cobrar. Es idempotente: cancelar una suscripción ya cancelada responde 200 con su estado actual.
El cuerpo es {}. El entorno lo define la API key, no el body.
curl https://api.vexorpay.com/api/v1/subscriptions/66f1c1e2c8a4b0d1f2e3a4b7/cancel \
-X POST \
-H "Authorization: Bearer vxp_live_tu_clave" \
-H "Content-Type: application/json" \
-d '{}'Cambiar la cantidad de asientos
PATCH /api/v1/subscriptions/{id}
En planes per_seat puedes cambiar cuántos asientos tiene el suscriptor:
curl https://api.vexorpay.com/api/v1/subscriptions/66f1c1e2c8a4b0d1f2e3a4b7 \
-X PATCH \
-H "Authorization: Bearer vxp_live_tu_clave" \
-H "Content-Type: application/json" \
-d '{ "seats": 8 }'Valida los límites del plan: si seats cae fuera de minSeats/maxSeats responde
invalid_seats. El cambio se hace en Polar y la diferencia se factura al instante (cobro al
agregar asientos, crédito a favor del comprador al quitarlos); los ciclos siguientes se cobran
por el nuevo total. Sólo se puede en suscripciones active o trialing sin cancelación
programada; si Polar rechaza el cambio responde 502 polar_update_failed.
El entorno lo define la API key: con una clave vxp_test_... operas sobre suscripciones de prueba.
Abrir el portal del cliente
POST /api/v1/subscriptions/{id}/portal
Devuelve { "url": "https://polar.sh/..." } (el portal del cliente de Polar) para que el suscriptor gestione su método de pago, vea facturas o cancele por su cuenta. Redirige al comprador a esa URL.
curl https://api.vexorpay.com/api/v1/subscriptions/66f1c1e2c8a4b0d1f2e3a4b7/portal \
-X POST \
-H "Authorization: Bearer vxp_live_tu_clave" \
-H "Content-Type: application/json" \
-d '{}'Errores
| Error | HTTP | Causa |
|---|---|---|
unauthorized | 401 | Falta el header Authorization. |
invalid_key | 401 | La API key es inválida o fue revocada. |
validation_error | 400 | status inválido en el listado, cursor inexistente, o un campo distinto de seats (o sin seats) en el PATCH. |
subscription_not_found | 404 | No existe esa suscripción, o es de otro modo (sandbox). |
price_not_found | 404 | El plan de la suscripción ya no existe (cambio de asientos). |
invalid_seats | 400 | seats fuera de minSeats/maxSeats del plan, seats en un plan de precio fijo, o suscripción no activa o con cancelación programada. |
polar_update_failed | 502 | Polar rechazó o no respondió la cancelación, el cambio de asientos o el portal. Reintenta. |
polar_reconnect_required | 409 | La conexión de Polar no tiene el permiso de suscripciones: el creador reconecta Polar. |
unexpected_error | 500 | Error interno inesperado. |
rate_limited | 429 | Superaste el límite de 100 requests por minuto. |