Pagos con tarjeta
Los dos flujos de tarjeta —tokenizado y datos en crudo— y el alcance PCI de cada uno.
Tonder ofrece dos caminos para procesar pagos con tarjeta en API Direct. La elección correcta depende de tu estado de cumplimiento PCI DSS y tu infraestructura.
- Flujo tokenizado — para la mayoría de comercios. Tokenizas los datos de la tarjeta primero y luego procesas los pagos con tokens. Minimiza tu alcance PCI.
- Datos en crudo — solo para comercios certificados PCI Nivel 1. Procesas pagos con números de tarjeta directamente. Requiere infraestructura de cumplimiento completa.
Comparación
| Aspecto | Flujo tokenizado | Datos en crudo |
|---|---|---|
| Requisito PCI | SAQ A o SAQ A-EP | PCI DSS Nivel 1 completo |
| Ideal para | La mayoría de comercios, startups, mid-market | Empresas, procesadores, plataformas de alto volumen |
| Pasos | 3 (obtener token → tokenizar → procesar) | 2 (obtener token → procesar) |
| Latencia | Ligeramente mayor (llamada extra de tokenización) | Menor (procesamiento directo) |
| Manejo de la tarjeta | Nunca toca tus servidores | Pasa por tus servidores |
| Costo de cumplimiento | Menor | Significativamente mayor |
El procesamiento de datos en crudo requiere prueba de certificación PCI DSS Nivel 1. Debes compartir tu Attestation of Compliance (AOC) con Tonder antes de activar el acceso a producción de los endpoints de datos en crudo.
Endpoints
| Propósito | Endpoint |
|---|---|
| Obtener access token | GET https://stage.tonder.io/api/v1/tokenization/auth/ |
| Tokenizar datos de tarjeta | POST https://token-sandbox.tonder.io/v1/gateway/inboundRoutes/{route_id}/token |
| Procesar pago (tokenizado) | POST https://stage.tonder.io/api/v1/process/ |
| Procesar pago (datos en crudo) | POST https://process-sandbox.tonder.io/raw-data |
| Propósito | Endpoint |
|---|---|
| Obtener access token | GET https://app.tonder.io/api/v1/tokenization/auth/ |
| Tokenizar datos de tarjeta | POST https://token.tonder.io/v1/gateway/inboundRoutes/{route_id}/token |
| Procesar pago (tokenizado) | POST https://app.tonder.io/api/v1/process/ |
| Procesar pago (datos en crudo) | POST https://process.tonder.io/raw-data |
Tu route_id se entrega en tu dashboard tras el onboarding. Contacta a soporte si no lo tienes.
Flujo tokenizado
Tonder tokeniza cada campo de la tarjeta por separado (número, CVV, mes de expiración, etc.); usarás cada token individual en lugar del valor original al hacer la petición de pago.
Llama a GET /api/v1/tokenization/auth/ con tu llave API. Devuelve un JWT en access_token.
curl -X GET https://stage.tonder.io/api/v1/tokenization/auth/ \
-H "Authorization: Token <YOUR_TONDER_API_KEY>"{ "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." }Envía los datos en crudo al servicio de tokenización, autorizado con el access token del paso
anterior (header X-Skyflow-Authorization). Campos requeridos:
| Campo | Tipo | Descripción |
|---|---|---|
card_number | string | El número completo de la tarjeta. |
cardholder_name | string | El nombre en la tarjeta. |
cvv | string | Código de seguridad (3-4 dígitos). |
expiration_month | string | Mes de expiración futuro (p. ej. "07"). |
expiration_year | string | Año de expiración futuro (p. ej. "26"). |
curl -X POST https://token.tonder.io/v1/gateway/inboundRoutes/{route_id}/token \
-H "X-Skyflow-Authorization: <YOUR_ACCESS_TOKEN_FROM_STEP_1>" \
-H "Content-Type: application/json" \
-d '{
"card_number": "4000000000000077",
"cardholder_name": "Ozzy Osbourne",
"cvv": "123",
"expiration_month": "07",
"expiration_year": "26"
}'El servicio responde con un token individual por cada campo. No son intercambiables entre campos.
Haz una petición estándar a /process/. En payment_method, usa los valores tokenizados en
lugar de los datos en crudo:
{
"operation_type": "payment",
"amount": 150.00,
"currency": "MXN",
"customer": { "name": "John Doe", "email": "john.doe@email.com" },
"payment_method": {
"type": "CARD",
"card_number": "9230-0892-4469-1474",
"cardholder_name": "c05d89b2-299c-4f93-b49a-42be00d3b64b",
"cvv": "d31f0da3-0ed3-4ad8-8b68-14c2669a99a7",
"expiration_month": "e401a32e-4174-424f-9688-727005f6a80e",
"expiration_year": "bd9ccc23-3d00-4109-9626-fc6581389063"
},
"client_reference": "ORD-001"
}La petición se autentica con tu llave API, igual que cualquier otro pago. Tonder destokeniza los valores del lado del servidor.
Valida siempre tanto id (identificador único de la transacción, guárdalo) como status (estado
actual del pago). Nunca confíes solo en el código HTTP.
3D Secure
3DS se maneja en el flujo de la tarjeta cuando el emisor lo requiere. Consulta el Ciclo de vida 3DS.
Referencia de la API
Endpoints del flujo tokenizado (el pago final se hace en POST /process/, documentado en
Resumen):
Autorización
Authorization Tu API key con prefijo Token , p. ej. Token <API_KEY>
In: header
Cuerpo de la respuesta
application/json
application/json
curl -X GET "https://example.com/tokenization/auth/"{
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}{
"error": {
"code": "string",
"message": "string",
"type": "request_error",
"details": {}
},
"request_id": "string"
}Autorización
TokenizationAuth Authorization Access token from /tokenization/auth/ endpoint
In: header
Tu API key con prefijo Token , p. ej. Token <API_KEY>
In: header
Cuerpo de la petición
application/json
TypeScript Definitions
Use the request body type in TypeScript.
Cuerpo de la respuesta
application/json
application/json
application/json
application/json
curl -X POST "https://example.com/token" \ -H "Content-Type: application/json" \ -d '{ "card_number": "4242424242424242", "cardholder_name": "John Doe", "cvv": "123", "expiration_month": "07", "expiration_year": "2025" }'{
"card_number": "9230-0892-4469-1474",
"cardholder_name": "c05d89b2-299c-4f93-b49a-42be00d3b64b",
"cvv": "d31f0da3-0ed3-4ad8-8b68-14c2669a99a7",
"expiration_month": "e401a32e-4174-424f-9688-727005f6a80e",
"expiration_year": "bd9ccc23-3d00-4109-9626-fc6581389063"
}{
"error": {
"code": "string",
"message": "string",
"type": "request_error",
"details": {}
},
"request_id": "string"
}{
"error": {
"code": "string",
"message": "string",
"type": "request_error",
"details": {}
},
"request_id": "string"
}{
"error": {
"code": "string",
"message": "string",
"type": "request_error",
"details": {}
},
"request_id": "string"
}