Skip to Content
Documentación de integración del API de Seif. ¿Dudas? soporte@pagosripei.com
EndpointsSesiones de pago

Sesiones de pago

Una sesión de pago representa una intención de cobro. La creas en tu servidor y obtienes un checkoutUrl para cobrar al comprador. Referencia pública: cs_…. Es de corta duración (actualmente ~5 minutos): créala justo antes de cobrar y usa expiresAt para el momento exacto de expiración.


Crear una sesión

POST /v1/sessions

Autenticación: clave secreta (Authorization: Bearer sk_…).

Cuerpo

CampoTipoRequeridoDescripción
amountMinorenteroMonto en unidades menores (céntimos). Mínimo 1.
currencystringVES o USD. Hoy el cobro con tarjeta se liquida en VES.
customerRefstringNoTu id de cliente. La tarjeta guardada quedará asociada a él. Máx. 120.
cardTokenstringNoToken de una tarjeta ya guardada (tok_seif_…). El checkout pedirá solo el CVV. Ver Cobrar una tarjeta guardada.
returnUrlstring (URL)NoA dónde redirigir al comprador tras un cobro aprobado.
descriptionstringNoTexto corto mostrado en el checkout. Máx. 140.
maxFailuresenteroNoCuántos intentos fallidos tolera la sesión antes de cerrarse sola. Omítelo para el comportamiento por defecto. Entre 0 y 10. Ver Limitar los intentos.

Ejemplo

curl -X POST https://api.seif.pagosripei.com/v1/sessions \ -H "Authorization: Bearer sk_test_tu_clave" \ -H "Content-Type: application/json" \ -d '{ "amountMinor": 105000, "currency": "VES", "customerRef": "usuario_123", "description": "Pedido #1042", "returnUrl": "https://mitienda.com/gracias" }'

Respuesta 201

{ "id": "9f0c1f2a-...-e3", "reference": "cs_8sKd2pQ1Aa", "status": "created", "amountMinor": 105000, "currency": "VES", "expiresAt": "2026-06-09T18:30:00.000Z", "checkoutUrl": "https://checkout.seif.pagosripei.com/checkout?session=cs_8sKd2pQ1Aa", "description": "Pedido #1042" }
CampoDescripción
referenceReferencia pública de la sesión (cs_…).
statusEstado de la sesión (ver abajo).
checkoutUrlURL para abrir el checkout incrustado.
expiresAtCuándo expira (ISO-8601).

Cobrar una tarjeta guardada (solo CVV)

Cuando tu cliente ya tiene una tarjeta guardada, no vuelvas a pedirle el número. Crea la sesión con el cardToken de esa tarjeta y el checkout mostrará únicamente:

  • la tarjeta con la que va a pagar (marca y últimos 4 dígitos),
  • el campo CVV,
  • su documento de identidad.

El número y el vencimiento salen de la bóveda del lado de Seif. Tu servidor nunca toca datos de tarjeta, así que el flujo es 100 % PCI para ti.

curl -X POST https://api.seif.pagosripei.com/v1/sessions \ -H "Authorization: Bearer sk_test_tu_clave" \ -H "Content-Type: application/json" \ -d '{ "amountMinor": 105000, "currency": "VES", "cardToken": "tok_seif_Xa92...kQ", "description": "Pedido #1043" }'

La respuesta es idéntica a la de cualquier sesión: abre el checkoutUrl (o móntalo con seif-js) y el comprador solo confirma su CVV.

Si no envías customerRef, la sesión hereda el de la tarjeta. Y si tu pasarela pide OTP, el flujo del checkout es el mismo que en un pago normal.

Errores propios de este flujo

HTTPCausaSolución
400cardToken no empieza por tok_seif_.Usa el seifToken tal cual lo devuelve GET /v1/cards.
404La tarjeta no existe en tu comercio, o fue eliminada.Vuelve a listar las tarjetas del cliente y usa una activa.
409La tarjeta no admite este flujo (por ejemplo, quedó guardada en una pasarela que no pide CVV).Escríbenos a soporte: esa tarjeta se cobra con un flujo servidor a servidor.

El cardToken se valida al crear la sesión, no al pagar: un token inválido falla en tu servidor, nunca delante del comprador.


Consultar una sesión

GET /v1/sessions/{reference}
curl https://api.seif.pagosripei.com/v1/sessions/cs_8sKd2pQ1Aa \ -H "Authorization: Bearer sk_test_tu_clave"

Devuelve el mismo objeto, con el status actualizado.

Estados de una sesión

EstadoSignificado
createdLista para cobrar.
processingEl comprador inició el pago.
completedPagada con éxito.
failedEl cobro falló o fue rechazado.
expiredSe alcanzó expiresAt sin pagarse.
canceledCancelada.

failed significa que un cobro falló pero la sesión sigue viva y se puede reintentar. Una sesión cerrada —por tiempo o por agotar sus intentos— siempre se reporta como expired.


Limitar los intentos

Por defecto una sesión se puede reintentar libremente hasta que expire. Si un cobro es rechazado, el comprador puede corregir los datos o probar otra tarjeta. Eso funciona bien para la mayoría, pero no para todos: hay integraciones que necesitan un número fijo de intentos y una respuesta definitiva, para que su propio sistema deje de esperar.

Para eso está maxFailures.

{ "amountMinor": 105000, "currency": "VES", "maxFailures": 0 }

Qué significa el número

maxFailures es cuántos fallos tolera la sesión, no cuántos intentos concede. El intento que rompe el límite también cuenta, así que el total de intentos es maxFailures + 1.

ValorIntentos totalesComportamiento
(omitido)IlimitadosReintentos libres hasta expiresAt. Es el comportamiento por defecto.
01Al primer fallo la sesión se cierra. No espera a que expire.
12Tolera un fallo; el segundo la cierra.
23Tolera dos fallos; el tercero la cierra.

0 no es lo mismo que omitir el campo. Omitirlo significa “sin límite”; 0 significa “cierra al primer fallo”. Si tu cliente HTTP descarta los ceros al serializar, revísalo: la diferencia entre los dos es total.

Qué cuenta como fallo

Cualquier intento que termine en error. No distinguimos entre un rechazo del banco y un dato mal escrito: si el cobro no salió, gastó un intento.

  • Rechazado por el banco emisor — cuenta.
  • Fallido en el procesador — cuenta.
  • Datos inválidos (400: falta el documento, falta el nombre del titular) — cuenta.

No consumen intentos las peticiones que nunca llegaron a ser un intento:

  • Una sesión ya cerrada, expirada o con un cobro en curso (409 / 410).
  • Los OTP incorrectos, que tienen su propio límite independiente.

Cómo se cierra

Una sesión ahora puede terminar de dos maneras: por tiempo (expiresAt) o por fallos (maxFailures). La que ocurra primero.

Se cierre como se cierre, el resultado es el mismo:

  • Su estado pasa a expired y attemptsRemaining queda en 0.
  • El checkout muestra la pantalla de sesión expirada, sin botón de reintento.
  • Un nuevo intento de cobro devuelve 409.
  • Se emite el webhook session.expired, con el mismo formato en ambos casos. El campo reason dice de qué manera murió.
{ "event": "session.expired", "data": { "sessionReference": "cs_8sKd2pQ1Aa", "reason": "max_failures_reached", "failureCount": 1, "maxFailures": 0 } }
reasonSignificado
expiredSe alcanzó expiresAt sin completarse.
max_failures_reachedSe agotaron los intentos permitidos.

Es un solo evento con un solo formato: si hoy manejas session.expired, no tienes que cambiar nada para enterarte también de los cierres por fallos. reason está ahí solo si quieres distinguirlos.

En el checkout

Al comprador se le avisa cuando le queda un solo intento, para que no lo gaste reintentando la misma tarjeta. Antes de eso no se le dice nada: mostrar un contador desde el principio agrega presión sin cambiar nada.

Cerrar y volver a cobrar

Una sesión cerrada no se reabre. Si quieres darle otra oportunidad al comprador, crea una sesión nueva. Es deliberado: el sentido de maxFailures es que la decisión de reintentar sea tuya y explícita, no del comprador.


Errores

HTTPCausaSolución
400Falta amountMinor/currency, o amountMinor < 1, o returnUrl no es una URL válida.Revisa el cuerpo según la tabla de campos.
401Clave secreta inválida o ausente.Verifica el header Authorization.
404La sesión consultada no existe.Revisa la reference.
409El comercio aún no está aprovisionado.Contacta a soporte para activar tu comercio.

La sesión es de un solo uso. Una vez completed (o expired), genera una nueva para un nuevo cobro.

Last updated on