Documentación de la API
La API REST de Saldo.tech permite a instituciones financieras y billeteras integrar ofertas vinculadas a pagos en sus apps —en tarjetas, PIX y otros medios—. Todos los endpoints usan JSON sobre HTTPS y se autentican con una API key por institución (Bearer token): la institución siempre se deriva de la key, nunca del cuerpo de la solicitud.
Descripción general
La API se organiza en torno a estas áreas de recursos:
Webhook de transacciones
POST /api/v1/transactionsEnvía eventos de transacción del tarjetahabiente para el emparejamiento de ofertas en tiempo real. El punto de integración principal para las instituciones financieras.
Transacciones por lote
POST /api/v1/transactions/batchEnviá muchos eventos de transacción en una sola solicitud firmada — para feeds heredados o de alto volumen.
Carga de archivo por lote (CSV)
CSV · Institution Portal¿Preferís un archivo diario? Subí un CSV de transacciones desde el Portal de Institución — validado y emparejado como el webhook.
Feed de ofertas
GET /api/v1/offersObtené las ofertas elegibles de un tarjetahabiente para mostrarlas en tu app o en el widget integrable.
Agregar oferta (inscribir)
POST /api/v1/offers/{id}/addInscribí a un tarjetahabiente en una oferta para que sus transacciones empiecen a emparejarse con ella.
Reportes — Canjes
GET /api/v1/reporting/redemptionsHistorial de canjes paginado por cursor para la integración con BI/almacén de datos. Autenticado mediante la clave de API de la institución.
Reportes — Liquidaciones
GET /api/v1/reporting/settlementsLibro mayor de liquidaciones paginado por cursor con el monto financiado por el comercio, los ingresos de Saldo y el pago a la institución.
Reportes — Embudo
GET /api/v1/reporting/funnelEmbudo de interacción para un período de fechas: vistas del widget, tarjetahabientes únicos, impresiones, adiciones y canjes.
Webhook de transacciones
El webhook de transacciones es la integración principal para las instituciones financieras. Publica los eventos de transacción a medida que ocurren y el motor de emparejamiento de Saldo.tech determinará si existe una oferta que califique.
POST /api/v1/transactions
Authorization: Bearer slk_<your-key>
{
"institution_id": "8f3e0b1c-...-uuid", // optional — derived from your key
"cardholder_token": "tok_ch_abc123",
"instrument_token": "tok_inst_xyz789", // card OR wallet/account token (card_token is the card-rail alias)
"instrument_type": "card", // card | wallet | account
"merchant_identifier": "CA1234567890", // preferred — the id your record carries
"merchant_identifier_type": "card_acceptor", // card_acceptor | pix_key | upi_vpa | …
"card_acceptor_id": "CA1234567890", // legacy alias (implies card_acceptor)
"mcc": "5411", // optional — reserved for enrichment
"merchant_descriptor": "SOLESTYLE #12", // optional — reserved for enrichment
"network": "visa", // optional
"merchant_id": "aaaaaaaa-...-uuid", // optional — only if you already resolved it
"amount": 225.00,
"transaction_ref": "txn_unique_id",
"transacted_at": "2025-03-15T14:30:00Z"
}Campos de la solicitud
institution_iduuidOpcional — la cuenta se deriva de tu clave de API. Inclúyelo solo si querés que el servidor rechace una discordancia.cardholder_tokenstringId opaco y ESTABLE por cliente generado por tu institución — p. ej. HMAC-SHA256 de una clave estable como el email del cliente o tu id de cliente interno, con un secreto que tú controlas (un HMAC CON CLAVE, no un hash simple — el email es de baja entropía y un hash simple es reidentificable). Mismo cliente → mismo token, en todas las ofertas y en el tiempo. Nunca envíes un email/id real; no lo rotes ni aleatorices por evento, o las transacciones no coincidirán con las inscripciones.card_tokenstringPAN tokenizado de la tarjeta usada (generado por la FI, nunca el número real). Riel de tarjeta; para QR/A2A usa instrument_token.instrument_tokenstringEl instrumento de pago, tokenizado — un token de tarjeta O un token de billetera/cuenta para consumidores QR/A2A sin tarjeta. Envía este o card_token.instrument_typestringTipo de instrumento: card | wallet | account. Opcional.merchant_identifierstringPreferido. El identificador de comercio que trae tu registro de transacción (un ID de aceptador de tarjeta, una clave PIX, un UPI VPA, …). Saldo lo resuelve al comercio.merchant_identifier_typestringTipo de merchant_identifier: card_acceptor | pix_key | upi_vpa | codi | psp_merchant_id. Predeterminado: card_acceptor.card_acceptor_idstringPreferido. El ID de aceptador de tarjeta de tu registro de transacción (campo 42 de ISO-8583). Saldo lo resuelve al comercio. Envía este o merchant_id.mccstringOpcional. Código de categoría de comercio (MCC). Reservado para enriquecimiento futuro; aún no se usa para la conciliación.merchant_descriptorstringOpcional. El descriptor del comercio de tu registro de transacción. Reservado para resolución de respaldo futura; aún no se concilia con él.networkstringOpcional. Red de tarjetas (p. ej. visa, mastercard).merchant_iduuidOpcional. UUID de comercio de Saldo.tech: envíalo solo si ya resolviste el comercio; de lo contrario, envía card_acceptor_id.amountnumberMonto de la transacción, en la moneda de la oferta.transaction_refstringTu referencia única para esta transacción. Se usa para idempotencia (única por institución).transacted_atstringMarca de tiempo ISO 8601 de cuándo ocurrió la transacción.Ingesta de transacciones por lote
Las instituciones heredadas o de alto volumen pueden enviar muchas transacciones en una sola solicitud firmada con HMAC en lugar de un webhook por evento. Cada ítem usa los mismos campos que el webhook individual.
POST /api/v1/transactions/batch
{
"transactions": [
{ "institution_id": "8f3e...uuid",
"cardholder_token": "v1_ia_kp4EZvf5J2KpiRymLtJfFJd98ItuF07g95--u5YI",
"card_token": "v1_or_44Zrluj8Iy3On_vABCdjpecpxLFo3_gE8BIp-iwQ",
"merchant_id": "aaaa...uuid",
"amount": 225.00, "transaction_ref": "txn_1",
"transacted_at": "2025-03-15T14:30:00Z" }
]
}
// 202 Accepted
{ "received": 1, "accepted": 1, "duplicates": 0, "invalid": [] }- Enviá un arreglo transactions de hasta 1000 ítems.
- La respuesta informa resultados por ítem — los ítems inválidos o duplicados se listan por índice sin hacer fallar todo el lote.
Carga de archivo por lote (CSV)
Las instituciones en planes Growth o Enterprise pueden subir un CSV diario de transacciones desde el Portal de Institución (Cargas por lote) en lugar de llamar al webhook por evento. El archivo se valida fila por fila, se deduplica por transaction_ref y pasa por el mismo emparejamiento; se genera un reporte de errores por fila para las líneas rechazadas.
Columnas (fila de encabezado obligatoria, en cualquier orden)
cardholder_token,card_token,card_acceptor_id,amount,transaction_ref,transacted_at tok_ch_abc123,tok_card_xyz789,CA1234567890,225.00,txn_1,2025-03-15T14:30:00Z
institution_id se toma de tu cuenta — nunca del archivo. Las líneas en blanco se omiten; las filas inválidas se informan por número de línea sin hacer fallar todo el archivo. Incluye card_acceptor_id (preferido: Saldo lo resuelve a tu comercio) o merchant_id.
Autenticación
Todos los endpoints se autentican con la API key Bearer de tu institución. Cada key tiene alcances (scopes) que deciden a qué endpoints puede llamar.
API key
Genérala desde el Portal de Instituciones en Dashboard → API Keys. El texto plano se muestra una sola vez al crearla; solo se almacena el hash SHA-256. Cada clave está limitada a su institución.
Authorization: Bearer slk_<random>Generar una clave →
Webhooks de transacciones
Los endpoints de transacciones y por lote usan la misma clave Bearer que el resto — sin secreto de firma aparte. Enviá Authorization: Bearer y la institución se toma de la clave.
Authorization: Bearer slk_<random>
Alcances de la key
Elige los alcances al generar una key y dale a cada una solo lo que necesita: una herramienta de BI solo necesita reporting. Llamar a un endpoint fuera de los alcances de la key devuelve 403. Las keys creadas antes de que existieran los alcances conservan los tres.
offers— feed de ofertas e inscripción (GET /api/v1/offers, POST /api/v1/offers/:id/add)transactions— webhook de transacciones, lote y simulaciónreporting— reportes de redenciones, liquidaciones y embudo
Vencimiento y rotación de claves
Las claves pueden tener fecha de vencimiento (un año por defecto). Saldo avisa a tu equipo 14 y 3 días antes del vencimiento y el mismo día; una clave vencida recibe 403 (Token expired). Para rotarla sin interrupciones: crea una clave nueva con los mismos alcances, despliégala, confirma que las solicitudes funcionan y luego revoca la anterior. Rota las claves al menos una vez al año, y de inmediato si una clave pudo quedar expuesta o si se va alguien que la tenía. La creación y revocación de claves queda registrada en tu Actividad de seguridad.
Feed de ofertas e inscripción
Obtené las ofertas que ve un tarjetahabiente y luego inscribilo. Ambos endpoints se autentican con tu clave de API de institución — la institución se deriva de la clave y todos los identificadores del tarjetahabiente están tokenizados.
GET/api/v1/offersDevuelve las ofertas activas y con presupuesto disponible para el tarjetahabiente, respetando el orden de tu programa y la elegibilidad por tarjetahabiente.
Parámetros de consulta
cardholder_tokenObligatorio. El token opaco del tarjetahabiente.localeOpcional. en, es o pt-BR — localiza el título y la descripción de cada oferta. Si tu programa no ofrece ese idioma, el feed usa el primer idioma admitido por tu programa.segmentOpcional. El código de segmento del tarjetahabiente según tus propios sistemas (p. ej. premium). Las ofertas que limitaste a segmentos solo aparecen si coincide; las ofertas sin restricción siempre aparecen. Se usa solo en esta solicitud: Saldo nunca guarda el segmento de un tarjetahabiente.limitOpcional. 1–100 (también limitado por la configuración de tu widget).personalizeOpcional. Poné true para ordenar el feed por afinidad del tarjetahabiente; agrega un reason a cada oferta.prefer_merchants,prefer_categoriesOpcional. prefer_merchants y prefer_categories aceptan pistas separadas por comas, usadas solo en memoria y nunca almacenadas.
curl "https://saldo-consumer-api-git-staging-kalantech.vercel.app/api/v1/offers?cardholder_token=tok_ch_abc123&locale=es&limit=20" \
-H "Authorization: Bearer slk_..."
{
"offers": [
{
"id": "0b1...",
"title": "Spend $200 at Acme, get $15 back",
"description": "Gasta $200 en Acme y recibe $15",
"merchant_id": "aaaa...",
"min_spend": 200.00,
"cashback_amount": 13.20,
"currency": "USD",
"starts_at": "2026-04-01T00:00:00Z",
"expires_at": "2026-06-30T00:00:00Z",
"added": false
}
],
"total": 12,
"personalized": false
}POST/api/v1/offers/{id}/addCrea el vínculo tarjetahabiente–oferta para que empiece el emparejamiento. Idempotente — reintentarlo devuelve already_added.
Cuerpo de la solicitud
curl -X POST "https://saldo-consumer-api-git-staging-kalantech.vercel.app/api/v1/offers/0b1.../add" \
-H "Authorization: Bearer slk_..." \
-H "Content-Type: application/json" \
-d '{ "cardholder_token": "tok_ch_abc123", "card_token": "tok_card_xyz789" }'
// 201 Created
{ "status": "added", "cardholder_offer_id": "c0f..." }
// 200 OK (idempotent re-add)
{ "status": "already_added", "cardholder_offer_id": "c0f..." }Envía el mismo segment al agregar una oferta limitada a segmentos (de lo contrario, 403 segment_not_eligible). Si el tarjetahabiente ya tiene el máximo de ofertas activas de tu programa, la solicitud devuelve 409 max_active_offers.
Webhook de redenciones (Saldo → tú)
Cuando una compra cumple los términos de una oferta, Saldo envía la redención por POST a la URL del webhook configurada en tu Portal de Institución para que acredites al tarjetahabiente.
- Firmado con X-Saldo-Signature: sha256= seguido del HMAC-SHA256 del cuerpo sin procesar usando tu secreto de firma. Cada entrega también lleva X-Saldo-Timestamp (segundos Unix) y X-Saldo-Signature-V2: el HMAC-SHA256 de "<timestamp>.<cuerpo sin procesar>". Verifica la V2 y rechaza marcas de tiempo de más de 5 minutos para que una entrega capturada no se pueda reenviar. Rota el secreto en Configuración; el nuevo valor se muestra una sola vez.
- cardholder_token es tu propio token completo, para que encuentres al cliente a acreditar; cardholder_token_masked es para mostrar y para registros.
- Una respuesta distinta de 2xx o un error de red se reintenta hasta 8 veces con espera exponencial (unas dos horas). Tras el último intento fallido, la bandeja de tu portal recibe una alerta.
- Cada intento (hora, estado HTTP, error y duración) aparece en Configuración → Entregas del webhook de redenciones.
POST https://your-bank.example/saldo/redemptions
X-Saldo-Signature: sha256=9f2c...
X-Saldo-Timestamp: 1791633600
X-Saldo-Signature-V2: sha256=4b7e...
{
"event": "redemption.completed",
"redemption_id": "r1a...",
"institution_id": "i9f...",
"offer_id": "0b1...",
"cardholder_token": "v1_ia_kp4E…(46 characters)…u5YI",
"cardholder_token_masked": "v1_i...u5YI",
"institution_payout_amount": 13.20,
"occurred_at": "2026-10-08T12:00:00.000Z"
}API de reportes
Extrae programáticamente los datos de canjes, liquidaciones e interacción de tu institución — para conciliación financiera, paneles de BI o herramientas internas personalizadas. Todos los endpoints devuelven JSON, están limitados a la institución propietaria de la clave de API y tienen un límite de 60 solicitudes por minuto por clave.
GET/api/v1/reporting/redemptionsLista de canjes paginada por cursor para la institución que realiza la llamada. Los tokens de tarjetahabiente se enmascaran a los primeros/últimos 4 caracteres.
Parámetros de consulta
from,to— marcas de tiempo ISO 8601 (opcional)cursor— valor opaco de la respuesta anterior (opcional)limit— de 1 a 1000 (predeterminado 100)
Ejemplo
curl https://saldo-consumer-api-git-staging-kalantech.vercel.app/api/v1/reporting/redemptions?limit=2 \
-H "Authorization: Bearer slk_..."
{
"data": [
{
"id": "8f3...",
"created_at": "2026-04-29T14:32:11.000Z",
"status": "settled",
"merchant_funded_amount": 15.00,
"institution_payout_amount": 13.20,
"offer": {
"id": "0b1...",
"title": "Spend $200 at Acme, get $15 back",
"merchant_name": "Acme Inc."
},
"cardholder_token_masked": "tok_...c123"
}
],
"pagination": {
"limit": 2,
"next_cursor": "2026-04-29T14:32:11.000Z|8f3..."
}
}GET/api/v1/reporting/settlementsEntradas del libro mayor de liquidaciones paginadas por cursor con el monto financiado por el comercio, los ingresos de la comisión de Saldo, el pago a la institución y el estado.
Parámetros de consulta
status—pending|settled|reversed(opcional)from,to,cursor,limit— misma semántica que los canjes
GET/api/v1/reporting/funnelEmbudo de interacción agregado para un período de fechas. De forma predeterminada usa los últimos 30 días cuando se omiten from / to .
{
"window": { "from": "...", "to": "..." },
"data": {
"widget_views": 12834,
"unique_cardholders": 4291,
"offer_impressions": 38420,
"offer_add_successes": 5102,
"redemptions": 612
}
}Paginación
Los endpoints de lista devuelven una cadena pagination.next_cursor cuando hay más filas disponibles. Pásala de vuelta como el parámetro de consulta cursor para obtener la siguiente página. El cursor es opaco — trátalo como una cadena arbitraria. Cuando next_cursor es null, has llegado al final.
¿Conectándote desde una herramienta de BI?
Recetas listas para copiar y pegar para cURL, Python, Node.js, Google Sheets, Power BI y Metabase.
Ver recetas de integración →Errores
401— token Bearer ausente o inválido403— token revocado, o la key no tiene el alcance reporting429— límite de tasa excedido (60 / minuto / clave)500— error en el servicio upstream; es seguro reintentar con backoff
Privacidad y manejo de datos
La API de Saldo.tech está diseñada en torno a identificadores tokenizados. Tu institución genera los valores cardholder_token y card_token usando tus propias claves criptográficas. Saldo.tech nunca recibe, procesa ni almacena PII de tarjetahabientes (nombres, correos electrónicos, direcciones o números de tarjeta reales). Consulta nuestra Política de Privacidad para obtener todos los detalles.
Entorno de desarrollo
Usa el endpoint de simulación para probar el emparejamiento de transacciones sin datos de pago reales:
POST /api/v1/transactions/simulate
Este endpoint acepta la misma carga útil que el webhook de transacciones de producción, pero omite el procesamiento de la liquidación. Úsalo para verificar que tu integración maneja correctamente las respuestas de coincidencia/no coincidencia.
¿Listo para integrar?
Contacta a nuestro equipo para obtener tus credenciales de API y comenzar a construir.