Crear link de pago recurrente
Crea planes por suscripción (pagos recurrentes) en dólares con la API de vexorpay.
Un link recurrente agrupa hasta 5 planes (precios por ciclo) y cobra automáticamente cada período. El comprador elige un plan en url y paga en el checkout; a partir de ahí la suscripción se renueva sola cada ciclo, en USD, y cada renovación se acredita en tu saldo como una venta nueva.
Necesitas la cuenta de cobro activada (si no, 409 payment_account_not_ready). Ver Suscripciones.
Request
POST /api/v1/payment-links
Headers
| Header | Valor |
|---|---|
Authorization | Bearer vxp_live_tu_clave |
Content-Type | application/json |
Idempotency-Key | opcional — para repetir sin duplicar |
Vexor-Account | opcional — id del usuario conectado, para crear el link en su nombre (cuentas conectadas) |
Body
| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
type | string | sí | "recurring". |
prices | array | sí | Entre 1 y 5 planes. |
title | string | sí | Título del producto: lo ve el comprador en el checkout y en el recibo. |
description | string | no | Descripción. |
image_file_id | string | no | Foto del producto (archivo tuyo subido desde el dashboard). |
reference | string | no | Referencia tuya para reconciliar. |
metadata | object | no | Pares clave/valor libres. |
Cada elemento de prices
| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
amount | number | sí | Precio por ciclo en dólares. Mínimo USD 4. No hay planes gratis. |
interval | string | sí | day, week, month o year. |
interval_count | number | no | Cada N intervalos (entero 1–12, default 1). El intervalo year solo admite 1. |
trial_period_days | number | no | Días de prueba gratis (1–90). El primer cobro se hace al terminar la prueba. |
description | string | no | Nombre visible del plan ("Básico", "Pro", "Anual"…). |
Todos los planes deben ser en USD. El link en sí queda con amountCents: 0; el precio real vive en cada plan.
Planes gratis, asientos y pruebas
- Planes gratis: cada plan vale al menos USD 4. Un plan con
amount: 0responde400 unsupported_plany no se crea nada. - Precio por asiento: una suscripción es siempre de una unidad.
pricing_type: "per_seat"(o cualquier campo de asientos) responde400 unsupported_plan. Para equipos, crea un plan por tamaño (por ejemplo "Equipo 5" y "Equipo 10"). - Prueba gratis: al suscribirse con prueba, el comprador deja su tarjeta y se registra una
venta de USD 0 (
billingReason: "subscription_create"); el primer cobro real llega al terminar la prueba.
La API rechaza con validation_error cualquier key desconocida dentro de un
plan, así que un typo (por ejemplo trial_days en vez de trial_period_days) no se ignora en
silencio: falla el request.
Ejemplo
curl https://api.vexorpay.com/api/v1/payment-links \
-X POST \
-H "Authorization: Bearer vxp_live_tu_clave" \
-H "Content-Type: application/json" \
-d '{
"type": "recurring",
"title": "Membresía Vexor",
"reference": "MEMBRESIA",
"prices": [
{
"amount": 9,
"interval": "month",
"description": "Mensual"
},
{
"amount": 90,
"interval": "year",
"trial_period_days": 7,
"description": "Anual"
}
]
}'Respuesta exitosa
201 Created
{
"id": "66f1c1e2c8a4b0d1f2e3a4b6",
"amountCents": 0,
"currency": "usd",
"title": "Membresía Vexor",
"description": null,
"image": null,
"reference": "MEMBRESIA",
"metadata": null,
"status": "active",
"slug": "b2c3d4e5f6",
"sandbox": false,
"url": "https://www.vexorpay.com/p/b2c3d4e5f6",
"checkoutUrl": "https://…",
"type": "recurring",
"prices": [
{
"id": "66f1c1e2c8a4b0d1f2e3a4c1",
"amountCents": 900,
"currency": "usd",
"interval": "month",
"intervalCount": 1,
"trialPeriodDays": null,
"description": "Mensual",
"isDefault": true
},
{
"id": "66f1c1e2c8a4b0d1f2e3a4c2",
"amountCents": 9000,
"currency": "usd",
"interval": "year",
"intervalCount": 1,
"trialPeriodDays": 7,
"description": "Anual",
"isDefault": false
}
],
"createdAt": "2026-01-02T12:00:00.000Z",
"updatedAt": "2026-01-02T12:00:00.000Z"
}El comprador elige el plan desde url (la página pública del link), o puedes llevarlo directo a un plan con POST /v1/payment-links/{id}/checkout y price_id. El tipo del link no se puede cambiar con PATCH, y de los planes existentes solo se edita el nombre (description): cambiar el precio, el intervalo, la prueba gratis o la cantidad de planes exige un link nuevo (ver Listar y gestionar links).
Errores
| Error | HTTP | Causa |
|---|---|---|
unauthorized | 401 | Falta el header Authorization. |
invalid_key | 401 | La API key es inválida o fue revocada. |
livemode_mismatch | 403 | La clave no corresponde al host (clave de prueba contra producción o al revés). |
prices_required | 400 | type: "recurring" sin prices[]. |
too_many_prices | 400 | Más de 5 planes. |
minimum_amount | 400 | Algún plan es menor a USD 4. |
invalid_interval | 400 | interval distinto de day, week, month o year. |
invalid_interval_count | 400 | interval_count fuera de 1–12 (o year ≠ 1). |
invalid_trial | 400 | trial_period_days fuera de 1–90. |
unsupported_plan | 400 | Plan gratis (amount: 0) o precio por asiento: no se pueden cobrar. |
validation_error | 400 | Falta el title (o está vacío), u otros datos inválidos (p. ej. moneda distinta de USD o una key desconocida dentro de un plan). |
payment_account_not_ready | 409 | Tu cuenta de cobro no está activada (o fue rechazada): actívala desde el dashboard. |
idempotency_conflict | 409 | La Idempotency-Key ya se usó con un body distinto. |
rate_limited | 429 | Superaste el límite de 100 requests por minuto. |
payment_link_failed | 502 | El procesador de pagos rechazó la creación del link. No quedó nada publicado: reintenta. |