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 permite cobrar automáticamente cada período. El comprador elige un plan en url y paga con Checkout de Stripe; a partir de ahí la suscripción se cobra sola.
La suscripción vive en la cuenta global de la plataforma (modelo separate charges and transfers) y en cada ciclo se te transfiere el neto exacto (precio − comisión de Stripe − USD 1). Ver Suscripciones.
Request
POST /api/v1/payment-links
Headers
| Header | Valor |
|---|---|
Authorization | Bearer vxp_u_tu_clave |
Content-Type | application/json |
Idempotency-Key | opcional — para repetir sin duplicar |
Body
| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
type | string | sí | "recurring". |
prices | array | sí | Entre 1 y 5 planes. |
title | string | no | Título del link. |
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. |
sandbox | boolean | no | Crea el link en modo de prueba. Más sobre sandbox. |
Cada elemento de prices
| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
amount | number | sí | Precio por ciclo en dólares. Mínimo USD 4. |
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). |
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.
Ejemplo
curl https://api.vexorpay.com/api/v1/payment-links \
-X POST \
-H "Authorization: Bearer vxp_u_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",
"type": "recurring",
"prices": [
{
"id": "66f1c1e2c8a4b0d1f2e3a4c1",
"stripePriceId": "price_1P...",
"amountCents": 900,
"currency": "usd",
"interval": "month",
"intervalCount": 1,
"trialPeriodDays": null,
"description": "Mensual",
"isDefault": true
},
{
"id": "66f1c1e2c8a4b0d1f2e3a4c2",
"stripePriceId": "price_1P...",
"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"
}Los links recurrentes no traen checkoutUrl en la respuesta del POST: la suscripción se inicia desde url (el comprador elige el plan ahí) o directo a un plan con POST /links/{id}/checkout y price_id (ver checkout). El tipo no se puede editar después con PATCH (hay que crear un link nuevo), pero los planes sí: PATCH /links/{id} acepta un array prices para agregar, editar o quitar planes (ver payment-links).
Errores
| Error | HTTP | Causa |
|---|---|---|
unauthorized | 401 | Falta el header Authorization. |
invalid_key | 401 | La API key es inválida o fue revocada. |
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. |
validation_error | 400 | Otros datos inválidos (p. ej. moneda distinta de USD). |
invalid_interval_count | 400 | interval_count fuera de 1–12 (o year ≠ 1). |
invalid_trial | 400 | trial_period_days fuera de 1–90. |
kyc_required | 400 | Todavía no verificaste tu identidad (necesario para links de producción). |
account_not_connected | 400 | La cuenta Stripe Express no está conectada o fue revocada. |
sandbox_account_not_ready | 400 | La cuenta Express de prueba no está conectada. Más sobre sandbox. |
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. |