Resumen #
Cuando un consumidor solicita uno de tus productos a través de
Prosperas, vos procesás esa solicitud de tu lado (la aprobás,
desembolsás los fondos o la rechazás). Un postback es
la forma en que le contás a Prosperas qué pasó, casi en tiempo real,
para que podamos actualizar el estado del lead, conciliar el revenue y
mantener sincronizada la experiencia del consumidor.
La integración es deliberadamente chica: un endpoint, una
credencial, un formato de payload.
| Propiedad | Valor |
|---|---|
| Dirección | Vos → Prosperas (vos nos llamás) |
| Endpoint | POST {BASE_URL}/client_app/webhook/lender/loan-status |
| Autenticación | Header X-API-KEY (recomendado) o IPallowlist |
| Formato del body | JSON, snake_case |
| Eventos | application, approval,disbursement, rejected |
| Éxito | 200 OK con un acknowledgement en JSON |
| Reintentos | Vos reintentás ante 5xx / errores dered (nosotros no te reintentamos) |
{BASE_URL}es la URL base de Prosperas para tu mercado
(Colombia / México). Prosperas te va a dar las URLs exactas de staging y
producción durante el onboarding.
Autenticación #
Todo postback tiene que autenticarse. Prosperas revisa primero la
API key, y después la IP de origen. Si
ninguna de las dos coincide con una credencial registrada, la solicitud
se rechaza con 403.
API key (recomendado) #
Enviá tu key en el header HTTP:
X-API-KEY: <tu-key>
- El nombre del header no distingue
mayúsculas/minúsculas (X-API-KEY,
x-api-key,X-Api-Keyfuncionan igual). - La key se valida por coincidencia exacta de string.
Sin prefijo, sinBearer, sin encoding.
IP allowlist (alternativa) #
Si te provisionaron por IP, no hace falta ningún header — leemos tu
IP de origen desde X-Forwarded-For, después
X-Real-IP, y por último el socket peer.
- La coincidencia es por string exacto contra la IP
que registramos. - No soportamos rangos CIDR / subnets. Cada IP de
salida individual que uses tiene que estar registrada. Si tu
infraestructura rota IPs, usá el método de API key en su lugar.
La regla del “el lead
tiene que existir” #
La autenticación no depende solo de la credencial — también está
atada a un lead real. Una solicitud es exitosa solo cuando se cumplen
todas estas condiciones:
- Tu credencial (key o IP) coincide con un origen de lender
registrado, y - el
click_idde la solicitud resuelve a un lead,
y - ese lead pertenece a un producto que es de tu
cuenta de lender.
Si tu credencial es válida pero el click_id no resuelve
a uno de tus leads, igual vas a recibir
403 (no 404). En la práctica
esto significa: un click_id incorrecto, desconocido
o ajeno devuelve 403.
Nota de seguridad: este endpoint no tiene firma
HMAC. Protegé tu API key como cualquier otro secreto: guardala en un
secrets manager, nunca la commitees, nunca la envíes en texto plano, y
pedile a Prosperas que la rote si alguna vez quedó expuesta.
El identificador de
tracking (click_id) #
click_id es el identificador único que conecta el
journey del consumidor entre Prosperas y tus sistemas.
- Prosperas lo genera y te lo entrega en el momento en que redirige al
consumidor hacia vos (como identificador de tracking/click en la URL de
handoff). - Tenés que guardarlo y devolverlo exactamente igual
en cada postback de esa solicitud. - No contiene datos personales; es una referencia opaca.
Formatos aceptados:
| Formato | Ejemplo | Notas |
|---|---|---|
| UUID simple | 7e1c2f1f-9b4d-4c1d-9f6c-2f3c1a2b4d5e |
|
orgname_UUID |
claro_7e1c2f1f-9b4d-4c1d-9f6c-2f3c1a2b4d5e |
Exactamente un guion bajo |
Más de un guion bajo, o un UUID que no se pueda parsear, devuelve
400.
Contrato de la solicitud #
Método: POST (recomendado). Existe una
variante GET con los mismos campos como query parameters,
pero POST con body JSON es el método server-to-server soportado.
Headers:
Content-Type: application/json
X-API-KEY: <tu-key>
Body (JSON, snake_case):
{
"click_id": "claro_7e1c2f1f-9b4d-4c1d-9f6c-2f3c1a2b4d5e",
"event": "approval",
"occurred_at": "2026-07-01T12:34:56Z",
"data": {
"provider": "tu-marca",
"client": {
"email": "consumidor@example.com",
"fullName": "Ana Gomez",
"firstName": "Ana",
"lastName": "Gomez",
"idNumber": "1234567890",
"phoneNumber": "3001234567",
"returningCustomer": false
}
}
}
Referencia de campos #
| Campo | Tipo | Requerido | Notas |
|---|---|---|---|
click_id |
string | Sí | El identificador de tracking. Devolvelo exactamente igual. |
event |
string | Sí | Uno de application, approval,disbursement, rejected. Solominúsculas — en mayúsculas se rechaza con 422. |
occurred_at |
string | — | Timestamp ISO-8601 de cuándo ocurrió el evento de tu lado (ej.2026-07-01T12:34:56Z). |
data |
object | — | Blob de auditoría opcional. Claves reconocidas:provider (string) y client (object, verabajo). |
data.client |
object | — | Datos opcionales del consumidor. Ver sección siguiente. |
El objeto
data.client (opcional) #
data.client te permite enriquecer el registro del
consumidor. Todos los campos son opcionales.
| Campo | Tipo | Notas |
|---|---|---|
email |
string | |
firstName |
string | Se usa solo si fullName no está presente. |
lastName |
string | Se usa solo si fullName no está presente. |
fullName |
string | Tiene prioridad: primer token → nombre, resto → apellido. |
idNumber |
string | Número de documento / cédula. |
phoneNumber |
string | |
returningCustomer |
boolean | Por defecto es false si se omite. Ver la advertenciaabajo. |
Importante — nunca sobrescribimos datos que ya ingresó el
consumidor.data.clientsolo completa campos que
están actualmente vacíos en el registro del consumidor.
Cualquier dato que el consumidor ya haya provisto en el flujo de
Prosperas prevalece. Esto protege la información que el consumidor
ingresó explícitamente.
Cuidado —
returningCustomerno es
persistente. Si omitísreturningCustomeren un
postback, se trata comofalse. Si dependés de este flag,
enviálo explícitamente en cada postback donde deba ser
true.
Eventos y ciclo de vida #
Enviá un postback por cada transición de estado, usando el evento que
corresponda a lo que pasó:
event |
Significado | ¿Requerido? |
|---|---|---|
application |
Se recibió / inició la solicitud del consumidor de tu lado. | Opcional |
approval |
La solicitud fue aprobada. | Sí |
disbursement |
Se desembolsaron los fondos. | Sí |
rejected |
La solicitud fue rechazada. | Sí |
application se acepta pero es opcional — enviálo si
tenés un hito significativo de “solicitud recibida”; si no, los tres
resultados terminales (approval, disbursement,
rejected) son lo que más importa.
Enviá los eventos en el orden en que ocurren.
Prosperas tolera eventos que llegan desordenados, pero la entrega en
orden mantiene limpio el historial del lead.
Respuestas y códigos de
estado #
Body de éxito (200 OK):
{
"ok": true,
"lead_id": 12345,
"status": "APPROVAL",
"user_id": 6789
}
ok— siempretrueen caso de éxito.lead_id— el lead de Prosperas contra el cual se
registró el evento.status— el estado interno al que mapeó tu evento
(APPLICATION/APPROVAL/
DISBURSEMENT/REJECTED).user_id— el id del registro del consumidor, cuando
está disponible.
Códigos de estado:
| Código | Significado | Qué hacer |
|---|---|---|
200 |
Evento registrado. | Listo. |
400 |
click_id mal formado (UUID inválido o demasiadosguiones bajos). |
Corregí el click_id; no reintentes sincambios. |
403 |
Falló la autenticación o el click_idno resuelve a uno de tus leads. |
Revisá tu key/IP y que estés devolviendo el click_idcorrecto. No reintentes a ciegas. |
404 |
Sesión no encontrada (caso raro, ocurre después de que la autenticación fue exitosa). |
Verificá el click_id; contactá a Prosperas sipersiste. |
422 |
Error de validación — ej. clickId en camelCase, eventoen mayúsculas, tipos incorrectos. |
Corregí la forma del payload (ver sección de errores comunes). No reintentes sin cambios. |
5xx |
Error transitorio del lado de Prosperas. | Reintentá con backoff exponencial (ver sección de reintentos). |
Errores comunes (leé
esto antes de integrar) #
Estos cuatro errores explican casi todas las integraciones fallidas
en su primer intento. Evitalos:
| ❌ No hagas esto | ✅ Hacé esto |
|---|---|
Usar clickId en camelCase en el body |
Usá snake_case click_id — camelCase →422 |
Enviar event: "APPROVAL" (mayúsculas) |
Enviá minúsculas approval — mayúsculas→ 422 |
| Asumir que el endpoint es público / sin auth | Enviá X-API-KEY (o llamá desde una IPen la allowlist) — si no, 403 |
| Poner la API key en un query string o esperar que un pixel se autentique |
Enviá la key en el header X-API-KEY enun POST |
Reintentos y garantías de
entrega #
- Los reintentos son tu responsabilidad. Prosperas no
te reintenta. Ante un5xxo un error de red, reintentá el
postback con backoff exponencial (ej. 1s, 2s, 4s, 8s…),
hasta un límite razonable. - No reintentes ante
4xx. Un
400,403o422significa que la
solicitud está mal — corregila y enviá una solicitud corregida en lugar
de insistir con el mismo payload. - El endpoint no es idempotente. Cada postback
aceptado registra un evento nuevo. Si reintentás después de una
solicitud que en realidad tuvo éxito (pero cuya respuesta no recibiste),
podés generar un evento duplicado. Mantené los reintentos acotados y
priorizá reintentar solo ante fallas confirmadas. - Cada solicitud queda registrada de nuestro lado
(con tu API key enmascarada) para soporte y conciliación.
Ejemplos prácticos #
Caso exitoso — aprobación
(POST) #
curl -X POST "{BASE_URL}/client_app/webhook/lender/loan-status" \
-H "Content-Type: application/json" \
-H "X-API-KEY: <tu-key>" \
-d '{
"click_id": "claro_7e1c2f1f-9b4d-4c1d-9f6c-2f3c1a2b4d5e",
"event": "approval",
"occurred_at": "2026-07-01T12:34:56Z",
"data": { "provider": "tu-marca" }
}'
Respuesta — 200 OK:
{ "ok": true, "lead_id": 12345, "status": "APPROVAL", "user_id": 6789 }
Desembolso
con enriquecimiento de datos del consumidor (POST) #
curl -X POST "{BASE_URL}/client_app/webhook/lender/loan-status" \
-H "Content-Type: application/json" \
-H "X-API-KEY: <tu-key>" \
-d '{
"click_id": "7e1c2f1f-9b4d-4c1d-9f6c-2f3c1a2b4d5e",
"event": "disbursement",
"occurred_at": "2026-07-01T15:00:00Z",
"data": {
"provider": "tu-marca",
"client": { "fullName": "Ana Gomez", "idNumber": "1234567890" }
}
}'
Error — campo en camelCase
(422) #
# INCORRECTO: "clickId" (camelCase) en lugar de "click_id"
curl -X POST "{BASE_URL}/client_app/webhook/lender/loan-status" \
-H "Content-Type: application/json" \
-H "X-API-KEY: <tu-key>" \
-d '{ "clickId": "7e1c2f1f-...", "event": "approval" }'
# → 422 Unprocessable Entity (el campo "click_id" es requerido)
Error — credencial
faltante o incorrecta (403) #
# Sin header X-API-KEY y con una IP que no está en la allowlist → 403
curl -X POST "{BASE_URL}/client_app/webhook/lender/loan-status" \
-H "Content-Type: application/json" \
-d '{ "click_id": "7e1c2f1f-...", "event": "approval" }'
# → 403 Forbidden
Referencia rápida #
| Endpoint | POST {BASE_URL}/client_app/webhook/lender/loan-status |
| Header de auth | X-API-KEY: <tu-key> (no distinguemayúsculas/minúsculas) |
| Campos requeridos del body | click_id (snake_case), event(minúsculas) |
| Eventos | application · approval ·disbursement · rejected |
| Campos opcionales del body | occurred_at (ISO-8601), data,data.client |
| Éxito | 200 →{ ok, lead_id, status, user_id } |
| Errores del cliente | 400 click_id inválido · 403 auth/lead ·404 sesión · 422 validación |
| Reintentar ante | Solo 5xx / red, con backoff exponencial |
| Firma | Ninguna (sin HMAC) — protegé la API key |
Notas importantes #
Casing: los campos de nivel superior son
snake_case(click_id,occurred_at). El objeto anidadodata.clientusacamelCase(fullName,idNumber,returningCustomer) — es intencional, no un error.
Respuesta: enviás
eventen minúscula (approval); la respuesta te devuelvestatusen MAYÚSCULA (APPROVAL). Es lo esperado.
Idempotencia y reintentos: el endpoint no es idempotente y Prosperas no te reintenta. Si un timeout te deja sin respuesta después de que registramos el evento, un reintento crea un evento duplicado. Recomendación: reintentá solo ante
5xxo errores de red, con backoff exponencial (1s, 2s, 4s…, máx. 3 intentos), y deduplicá de tu lado porclick_id+event+occurred_at. (Ojo: tu API de decisión/submission del Flujo embebido SÍ debe ser idempotente por tracking ID — esa dirección la reintentamos nosotros.)
Última verificación: 2026-07-01 · v1.1 · coincide con
Lender-Postback-Integration-Guide.md
