Guardar una tarjeta sin cobrar
Crea una sesión de registro de tarjeta para que el cliente guarde primero una tarjeta: para suscripciones o para agregar un método de pago.
Una sesión de registro de tarjeta (enrollment) guarda la tarjeta de un cliente sin cobrarle:
para el alta en una suscripción, para agregar un método de pago, o para cualquier flujo que
necesite una tarjeta guardada antes del primer cobro. Es un checkout de un solo uso (válido hasta
por 24 horas) que muestra únicamente el formulario de tarjeta y un botón para guardarla: sin monto,
sin artículos, sin otros métodos de pago.
No se crea ningún pago, así que el payment_id de la sesión es 0 y no se envía ningún webhook de
pago. Las sesiones de registro de tarjeta siempre usan el diseño de checkout de primera generación
(v1).
Si Card-on-File está habilitado para tu cuenta, al guardar la tarjeta se ejecuta una verificación 3D Secure con el emisor de la tarjeta (puede aparecer una ventana de verificación), y la tarjeta guardada puede usarse después en pagos posteriores sin pedir el CVV. Si no está habilitado, la tarjeta se guarda directamente. Tu integración es la misma en ambos casos.
Paso a paso
Envía session_type: "enrollment" y el cliente. La tarjeta se guarda para este cliente.
curl -X POST 'https://api-stage.tonder.io/checkout/v1/sessions' \
-H 'Authorization: Token YOUR_TEST_API_KEY' \
-H 'Content-Type: application/json' \
-d '{
"session_type": "enrollment",
"customer": { "first_name": "Ana", "last_name": "Garcia", "email": "ana@example.com" },
"locale": "es",
"return_url": "https://your-store.com/card-saved"
}'curl -X POST 'https://api.tonder.io/checkout/v1/sessions' \
-H 'Authorization: Token YOUR_API_KEY' \
-H 'Content-Type: application/json' \
-d '{
"session_type": "enrollment",
"customer": { "first_name": "Ana", "last_name": "Garcia", "email": "ana@example.com" },
"locale": "es",
"return_url": "https://your-store.com/card-saved"
}'{
"id": "cs_97_0_abc123",
"url": "https://stage-payflow.tonder.io/checkout/cs_97_0_abc123",
"status": "pending",
"session_type": "enrollment",
"checkout_type": "hosted",
"payment_id": 0,
"locale": "es",
"return_url": "https://your-store.com/card-saved",
"expires_at": 1776370888,
"customer": { "first_name": "Ana", "last_name": "Garcia", "email": "ana@example.com" }
}Redirige al cliente a la url. Verá el formulario de tarjeta (nombre del titular, número de
tarjeta, fecha de expiración, CVV) y un botón para guardar la tarjeta.
Con Card-on-File, primero puede aparecer una verificación 3D Secure. Si todo sale bien, la página muestra una confirmación de "tarjeta guardada". Si algo falla —verificación rechazada, error de red, sesión expirada, tarjeta inválida— el cliente ve un error y puede reintentar sin recargar.
La sesión pasa a completed y, con redirect_on_completion: "always", el cliente es enviado a
return_url. Confírmalo desde tu backend con
Consultar una sesión:
{ "id": "cs_97_0_abc123", "status": "completed", "session_type": "enrollment", "payment_id": 0 }Campos
| Campo | Tipo | Requerido | Valores | Descripción |
|---|---|---|---|---|
session_type | string | Sí | enrollment | Hace que esta sea una sesión para guardar una tarjeta. |
customer | object | Sí | first_name, last_name, email (requeridos); phone, address, identification (opcionales) | La tarjeta se guarda para este cliente. |
return_url | string | No | URL | A dónde va el cliente después de guardar la tarjeta. |
locale | string | No | es (por defecto), en, zh | Idioma de la página. El cliente puede cambiarlo. |
expires_at | number | No | Tiempo Unix en segundos | De 30 minutos a 24 horas a partir de ahora. Por defecto 24 horas. |
external_id | string | No | — | Tu referencia. |
metadata | object | No | — | Cualquier dato que quieras recibir de vuelta después. |
ui_config | object | No | Colores, fuente, formas, etiquetas, textos de ejemplo | Apariencia para esta sesión, sobre la apariencia guardada de tu negocio. |
checkout_type | string | No | hosted (por defecto), embedded | Usa embedded para mostrar la página en un iframe. |
post_message_enabled | boolean | No | true, false | Envía eventos a tu página. Requiere embedded. |
redirect_on_completion | string | No | always (por defecto), never | never mantiene al cliente en la página para que tu sitio maneje la navegación. |
Los campos de pago no están permitidos en el registro de tarjeta: amount_total, currency,
line_items, payment_method_types, payment_method_config, success_url, pending_url,
cancel_url y submit_type devuelven 400 E004.
Checkout embebido y eventos
Crea la sesión con checkout_type: "embedded" y post_message_enabled: true, y carga la url en
un iframe como se describe en Embeber el checkout. Las sesiones
de registro de tarjeta envían tres eventos, cada uno con session_type: "enrollment":
| Evento | Cuándo |
|---|---|
checkout.initiated | El formulario de tarjeta terminó de cargar. |
checkout.completed | La tarjeta se guardó (session_status: "completed"). |
checkout.failed | El guardado falló; el cliente puede reintentar. |
Errores
| Estado HTTP | Código | Significado | Qué hacer |
|---|---|---|---|
| 400 | E004 | Falta un campo, tiene un valor no permitido, o es un campo de pago. | Lee metadata.errors, corrige el cuerpo y reintenta. |
| 400 | E0014 | Pediste el pago de una sesión de registro de tarjeta. | No hay pago; usa Consultar una sesión. |
| 401 / 403 | — | Llave API faltante o inválida. | Revisa el header Authorization y el entorno. |
| 404 | E003 | No hay ninguna sesión con este id. | Revisa el id y el entorno. |
