vexorpayDocs

Referencia de API

Referencia general de la API de vexorpay: base URL, autenticación, formato, paginación, idempotencia, rate limit y errores.

Base URL

https://api.vexorpay.com/api/v1           # producción (claves vxp_live_)
https://api.sandbox.vexorpay.com/api/v1   # sandbox (claves vxp_test_)

Autenticación

Todos los endpoints requieren tu clave de API, enviada en el header Authorization:

Authorization: Bearer vxp_live_tu_clave

Aprende más en Autenticación.

Conexiones OAuth: las apps conectadas pueden autenticarse con un token OAuth (vxo_at_…) en vez de una API key. En ese caso la conexión fija el modo (sandbox o producción) y cada endpoint exige un scope: si la conexión no lo tiene, la API responde 403 insufficient_scope. Ver vexorpay MCP.

Formato de respuesta

  • Los recursos (links, ventas, suscripciones) se devuelven como objeto plano (p. ej. GET /api/v1/payment-links/{id} o GET /api/v1/orders/{id}).
  • Los listados se devuelven en un envoltorio con paginación:
{
  "data": [ { "...": "recurso" } ],
  "has_more": false,
  "total_count": 12,
  "url": "/v1/orders?limit=10"
}

Paginación

Los listados usan paginación por cursor:

ParámetroDescripción
limitCantidad por página (default 10, mínimo 1, máximo 100).
starting_afterID del último elemento de la página anterior; devuelve los siguientes.
ending_beforeID del primer elemento de la página anterior; devuelve los anteriores.

limit tiene que ser un entero entre 1 y 100: con 0, -5, 101, 2.5 o un valor no numérico la API responde 400 validation_error. En la respuesta, la url de paginación refleja el limit efectivo de esa página.

Producción y sandbox

Hay dos entornos, cada uno con su host y su familia de claves. El modo lo define la API key, no el request:

EntornoBase URLClaves
Producciónhttps://api.vexorpay.com/api/v1vxp_live_...
Sandbox (pruebas)https://api.sandbox.vexorpay.com/api/v1vxp_test_...

Sandbox es un entorno aparte, con sus propios usuarios y datos: las claves de prueba se crean desde dashboard.sandbox.vexorpay.com. No existe un parámetro sandbox en los requests. Una clave en el host equivocado responde 403 livemode_mismatch. Ver Modo sandbox.

Cobros y comisiones

  • Los precios son siempre en USD, con un mínimo de USD 4 por cobro y por plan. No hay planes gratis ni precios por asiento.
  • Sin suscripción: cada venta paga una sola comisión de vexorpay, desde 2,7 % + USD 1 con el procesamiento incluido. Cada venta trae el desglose en feeCents y netCents.
  • En los pagos únicos el comprador puede pagar en su moneda local; las suscripciones se cobran en USD. Las ventas se informan siempre en USD.
  • Para cobrar hace falta la cuenta de cobro activada desde el dashboard (si no, 409 payment_account_not_ready). Ver Cómo funcionan los cobros.

Idempotencia

Los POST que crean recursos aceptan el header Idempotency-Key. Si repites la misma clave con el mismo body, no se crea nada nuevo: se devuelve el recurso original (replay 200). Con la misma clave y un body distinto, recibes un error idempotency_conflict (409).

Lo aceptan la creación de links (POST /api/v1/payment-links), los reembolsos (POST /api/v1/orders/{id}/refund) y el alta de cuentas de retiro (POST /api/v1/payout-methods, donde la clave también llega al procesador de pagos: un reintento tras un 502 no crea una segunda cuenta). Recomendado: usar una clave por operación (p. ej. el UUID del pedido) para no duplicar un reembolso si el request se repite. El checkout (POST /api/v1/payment-links/{id}/checkout) no es idempotente: cada llamada crea una sesión de checkout nueva.

La clave tiene de 1 a 255 bytes (p. ej. un UUID); vacía o más larga responde 400 invalid_idempotency_key sin ejecutar nada.

Cada clave se conserva 24 horas: pasado ese plazo se descarta y una clave repetida vuelve a ejecutar la operación (se crea un recurso nuevo). Si el recurso original ya no existe (p. ej. fue eliminado dentro de esas 24 horas), el replay responde 404 not_found.

Rate limit

La API tiene un límite de 100 requests por minuto por clave. Cada respuesta incluye los headers X-RateLimit-Limit, X-RateLimit-Remaining y X-RateLimit-Reset (también en los errores 401 y 429). Al superarlo recibes 429 Too Many Requests con Retry-After y X-RateLimit-Remaining: 0. Todas las respuestas traen además X-Request-Id (id único para cruzar con soporte) y Cache-Control: no-store.

Errores

Los errores usan el formato:

{
  "error": "invalid_amount",
  "message": "The minimum amount per charge is USD 4.",
  "detail": { "resetInSeconds": 42 }
}

detail es opcional y siempre un objeto (p. ej. resetInSeconds en un 429 o required_scope en un 403 insufficient_scope). Nunca contiene mensajes crudos de errores internos: esos se registran del lado del servidor.

Compatibilidad: los campos desconocidos que mandes en un body se ignoran (no validan) y no se devuelven en la respuesta. Las excepciones son las keys desconocidas dentro de un plan de un link recurrente (prices[]) y en el body de POST /api/v1/payout-methods (datos bancarios): ahí responden 400 validation_error para que un typo no pase en silencio. Del otro lado, la API puede agregar campos nuevos a las respuestas en cualquier momento: trata los campos que no conozcas como opcionales.

errorHTTPCausa
unauthorized401Falta el header Authorization.
invalid_key401La API key es inválida o fue revocada.
insufficient_scope403La conexión (token de una app conectada) no tiene el permiso que exige este endpoint. detail.required_scope indica cuál hace falta.
livemode_mismatch403La clave y el host no coinciden en modo: diste una clave de prueba contra api.vexorpay.com (o una live contra api.sandbox.vexorpay.com).
invalid_connected_account403El header Vexor-Account apunta a una cuenta sin conexión activa de la app, o la credencial no es de una app de marketplace. También si se manda en los endpoints de cuentas de retiro, que no se gestionan en nombre de una cuenta conectada.
payment_account_suspended403La cuenta de cobro está suspendida (por el procesador de pagos o por vexorpay): no se pueden crear links ni checkouts (y sus links no aceptan pagos) hasta que se reactive. No se resuelve cambiando el request.
validation_error400Algún parámetro tiene un valor inválido.
invalid_request400El body es inválido o falta un dato requerido.
invalid_amount400El monto no es válido o es menor a USD 4.
minimum_amount400El precio de un plan recurrente es menor a USD 4.
prices_required400Un link recurring necesita al menos un precio.
too_many_prices400Se superó el máximo de 5 planes por link.
invalid_interval400El interval del precio no es week, month o year (no hay suscripciones diarias).
invalid_interval_count400El interval_count está fuera de rango.
invalid_trial400El trial_period_days está fuera de rango (1–90).
unsupported_plan400El plan no se puede cobrar: plan gratis (USD 0), precio por asiento, o un cambio de planes en un link recurrente existente (precio, intervalo, prueba o cantidad de planes: hace falta un link nuevo).
payment_link_inactive400El link de pago no está activo.
dispute_not_respondable400La disputa ya está cerrada o no se puede aceptar.
invalid_idempotency_key400El header Idempotency-Key vino vacío o tiene más de 255 bytes.
link_not_found404No existe ese link de pago.
subscription_not_found404No existe esa suscripción.
dispute_not_found404No existe esa disputa.
order_not_found404No existe esa venta.
customer_not_found404No existe ese cliente.
price_not_found404El price_id no es un plan de ese link.
not_found404El recurso no existe (p. ej. una conexión de marketplace), o la Idempotency-Key apunta a un recurso que ya no existe.
payment_account_not_ready409La cuenta de cobro no está lista: todavía no se activó, fue rechazada o falta verificar la identidad (sin verificar no se crean links, checkouts ni retiros, ni se gestionan cuentas de retiro). Se resuelve desde el dashboard.
idempotency_conflict409La Idempotency-Key ya se usó con un body distinto.
already_processed409El recurso ya fue eliminado o archivado (p. ej. un link archivado).
rate_limited429Superaste el límite de 100 requests por minuto.
unexpected_error500Error interno inesperado.
payment_link_failed502El procesador de pagos rechazó o no respondió la creación o la edición del link. No se cambió nada: reintenta en unos minutos.
upstream_error502El procesador de pagos falló o no respondió (checkout, reembolso, cancelación, disputa, saldo, retiro o cuenta de retiro). No se cambió nada: reintenta más tarde.

Endpoints

  • Crear link de pago único — POST /api/v1/payment-links
  • Crear link de pago recurrente — POST /api/v1/payment-links con type: "recurring"
  • Listar y gestionar links — GET /api/v1/payment-links, GET / PATCH / DELETE /api/v1/payment-links/{id}, GET /api/v1/payment-links/{id}/stats
  • Checkout por compra — POST /api/v1/payment-links/{id}/checkout
  • Ventas — GET /api/v1/orders, GET /api/v1/orders/{id}, POST /api/v1/orders/{id}/refund
  • Clientes — GET /api/v1/customers, GET /api/v1/customers/{id}
  • Disputas — GET /api/v1/disputes, GET /api/v1/disputes/{id}, POST /api/v1/disputes/{id}/accept
  • Suscripciones — GET /api/v1/subscriptions, GET /api/v1/subscriptions/{id}, POST /api/v1/subscriptions/{id}/cancel, POST /api/v1/subscriptions/{id}/portal
  • Saldo — GET /api/v1/balance
  • Retiros — GET /api/v1/payouts (sólo lectura: los retiros se piden en el dashboard, en Retirar)
  • Cuentas de retiro — GET / POST /api/v1/payout-methods, GET /api/v1/payout-methods/supported, GET /api/v1/payout-methods/supported/{id}
  • Eventos de reconciliación — GET /api/v1/events
  • Cuentas conectadas (marketplace) — Vexor-Account, GET /api/v1/connected-accounts, GET / DELETE /api/v1/connected-accounts/{id}
  • Webhooks salientes — configurar y verificar notificaciones
  • Autenticación — claves, rotación y seguridad
  • Modo sandbox — prueba tu integración sin mover dinero real