> ## Documentation Index
> Fetch the complete documentation index at: https://docs.lerian.studio/llms.txt
> Use this file to discover all available pages before exploring further.

# Guía de integración

> Integra Tracer con tu sistema de autorización: envía payloads completos, gestiona las decisiones ALLOW, DENY y REVIEW, y mantente dentro de un presupuesto de latencia de 80ms.

export const GMetadata = ({children}) => <Tooltip headline="Metadatos" tip="Información adicional de clave-valor asociada a entidades como cuentas o transacciones, como IDs externos, números de referencia o códigos de departamento." cta="Ver glosario" href="/es/start-here/glossary">
    {children}
  </Tooltip>;

Integrar Tracer implica decidir en qué punto de tu flujo de autorización haces la llamada de validación, qué datos envías y cómo gestionas las tres decisiones posibles. El patrón es corto: tu sistema reúne el contexto completo de la transacción, llama a `POST /v1/validations`, actúa según ALLOW / DENY / REVIEW y continúa. Tracer nunca vuelve a entrar en tu stack. No hay webhooks ni callbacks, y la integración termina con la respuesta.

**Qué cambia en tu operación:** la toma de decisiones pasa de una lógica en proceso a una llamada externa. La llamada es síncrona (solicitud/respuesta, sin webhooks), así que queda en la ruta crítica de la transacción. Bien implementada, agrega menos de 80ms p99 y te da un punto único para las políticas y el historial de validación. Mal implementada (sin timeout, sin estrategia de reintento, sin fallback), se convierte en un punto único de falla.

**Trade-off del que hay que ser honesto:** estás agregando un salto de red. La buena noticia es que el contrato es simple: idempotente por `requestId`, sin callbacks, respuesta determinista de tres estados. La mala noticia es que debes pensar en los timeouts, los reintentos y qué hacer si Tracer es inaccesible. La mayor parte de esta guía trata sobre eso.

<Tip>
  **¿Para quién es esta guía?** Ingenieros de integración que escriben la solicitud desde tu sistema hacia Tracer, y arquitectos que deciden en qué punto del flujo va la llamada. Los analistas de riesgo y fraude que escriben reglas pueden ir directamente a la [guía del motor de reglas](./rule-engine.mdx). El equipo de compliance puede leer en su lugar la [guía de auditoría y compliance](./audit-compliance.mdx).
</Tip>

Esta guía cubre los requisitos del payload, el flujo de integración y las prácticas que mantienen la llamada de validación dentro de tu presupuesto de latencia.

Tracer se ubica **fuera** de tu ledger: nunca llama a Midaz. Tu aplicación orquesta ambos. Llama a Tracer para validar y envía la transacción a Midaz solo si la decisión es `ALLOW`. Tracer evalúa tus **políticas y límites** configurados contra el contexto que envías, no contra los saldos de las cuentas. El ledger sigue siendo la fuente de verdad de lo que tiene una cuenta.

<Note>
  Midaz también puede llamar a Tracer mediante un seam de reserva opcional por ledger. Sigue siendo unidireccional, Ledger → Tracer. El resto de esta guía cubre el patrón HTTP orquestado por la aplicación. El contrato del seam aparece más abajo.
</Note>

## Resumen de la integración

***

Tracer espera llamadas de **sistemas de autorización** (gateways de pago, orquestadores de workflow o procesadores de transacciones) que necesitan decisiones de validación en tiempo real. La integración sigue un patrón simple de solicitud-respuesta:

<Frame caption="Figura 1. Resumen de la integración con Tracer">
  <img src="https://mintcdn.com/lerian-49cb71fc/RAVxFNT8MNA4GWjO/images/es/d2/integration-overview-tracer.svg?fit=max&auto=format&n=RAVxFNT8MNA4GWjO&q=85&s=19c66ed13c603bcbe1c64bffa2fdb540" alt="Integración de solicitud-respuesta en la que un sistema de autorización llama a Tracer para obtener una decisión de validación y solo envía la transacción a Midaz cuando la decisión es ALLOW" width="1015" height="284" data-path="images/es/d2/integration-overview-tracer.svg" />
</Frame>

**Principio clave:** Tracer no busca datos externos durante la validación. Tu sistema debe proporcionar todo el contexto necesario para la evaluación de las reglas.

***

<h2 id="midaz-ledger-reservation-seam">
  Seam de reserva de Midaz Ledger
</h2>

***

Este seam opcional pertenece a **Ledger HTTP v2**, no a Tracer HTTP v2. Ledger HTTP v1 nunca lo invoca. La API HTTP pública de Tracer sigue siendo solo v1, incluidas sus operaciones de reserva bajo `/v1`. El servicio gRPC `lerian.midaz.reservation.v1.ReservationService` es un transporte interno de servicio a servicio, no una API v2 pública.

Define `TRACER_BASE_URL` para inyectar el seam. Cuando no está definida, Ledger no hace ninguna llamada de reserva. Ledger llama al cliente inyectado solo cuando el `tracer.mode` por ledger es `advisory` o `enforce`. Un modo no definido o `off` sigue omitiendo las reservas incluso cuando defines `TRACER_BASE_URL`. Un skip por llamada respetado también evita el seam.

gRPC es el transporte predeterminado: configura `TRACER_GRPC_PORT` en Tracer y apunta `TRACER_BASE_URL` a ese listener gRPC. Con `TRACER_TRANSPORT=rest`, apunta en su lugar al listener HTTP de Tracer. Ambos transportes usan el mismo servicio de reserva y las mismas cinco transiciones:

| Transición             | Acción de Ledger                                                                                                                                                  |
| ---------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `Reserve`              | Retiene capacidad de límite antes de que la transacción se confirme. Los reintentos son idempotentes en el grano `(transactionId, limitId, scopeKey, periodKey)`. |
| `ConfirmByTransaction` | Confirma cada hold de una transacción; reintentar después del estado terminal no hace nada y puede devolver `flipped=0`.                                          |
| `ReleaseByTransaction` | Libera cada hold de una transacción; reintentar después del estado terminal no hace nada y puede devolver `flipped=0`.                                            |
| `Confirm`              | Confirma un hold; reintentar una reserva terminal no hace nada.                                                                                                   |
| `Release`              | Libera un hold; reintentar una reserva terminal no hace nada.                                                                                                     |

En las llamadas multi-tenant, REST reenvía el tenant en el header `X-Tenant-Id` y gRPC lo reenvía como metadatos `x-tenant-id`. Ninguno de los dos transportes lo coloca en el mensaje de reserva.

El listener solo puede confiar en este valor mediante mTLS directo o detrás de un sidecar de service mesh verificado. Con `TRACER_TLS_MODE=mtls`, cada lado presenta y verifica certificados. Los modos de TLS `mesh` y vacío requieren un sidecar que exija mTLS. Sin uno, la conexión entre el proceso y el listener es en texto plano y un llamador no confiable puede falsificar el tenant. Tracer habilita su listener gRPC solo cuando defines `TRACER_GRPC_PORT`.

La semántica de fallas es explícita. Una denegación de reserva es una respuesta exitosa, no un error de transporte. El modo `advisory` registra el resultado y continúa. El modo `enforce` rechaza la transacción antes de cualquier movimiento de saldo, sin importar `failPosture`. La configuración `failPosture` se aplica a cualquier error de llamada de reserva: `closed` rechaza y `open` continúa sin una reserva.

Las fallas de confirmación y liberación son operaciones de nivel de advertencia, no bloqueantes. El reaper de TTL de Tracer concilia una transición terminal perdida.

## Patrón Payload-Complete

***

Tracer usa el **Patrón Payload-Complete**. Cada solicitud debe llevar todo el contexto necesario para la validación. Este diseño garantiza:

| Beneficio               | Descripción                                                                                        |
| ----------------------- | -------------------------------------------------------------------------------------------------- |
| **Latencia predecible** | Sin llamadas externas durante la validación; el tiempo de respuesta se mantiene por debajo de 80ms |
| **Simplicidad**         | Una sola solicitud contiene todo lo necesario para la decisión                                     |
| **Confiabilidad**       | Sin dependencia de servicios externos durante la validación                                        |
| **Flexibilidad**        | Tu sistema controla la actualidad de los datos y la lógica de enriquecimiento                      |

### Tus responsabilidades

Como sistema que se integra, eres responsable de:

1. **Enriquecer el payload** con datos de cuenta, segmento, portafolio y comercio antes de llamar a Tracer
2. **Proporcionar contexto preciso** para la evaluación de reglas y límites. Tracer no puede obtener datos faltantes
3. **Gestionar la decisión** (ALLOW, DENY o REVIEW) de forma adecuada en tu workflow
4. **Implementar lógica de reintento** si Tracer no está disponible temporalmente
5. **Gestionar los workflows de revisión** cuando Tracer devuelve `REVIEW`. Tracer no incluye gestión de casos

<Warning>
  Tracer valida lo que envías. Si tu payload carece de contexto (por ejemplo, estado de la cuenta, membresía de segmento), las reglas que dependen de esos datos no pueden evaluarse correctamente. Confirma siempre que los payloads estén completos antes de enviarlos.
</Warning>

### Responsabilidades de Tracer

Tracer es responsable de:

1. **Evaluar las reglas** según el contexto proporcionado
2. **Verificar los límites** según el uso actual
3. **Almacenar el historial de validación** para investigación e informes
4. **Devolver la decisión** con información detallada

***

## Flujo de integración

***

Sigue estos pasos para integrar tu sistema con Tracer.

### Paso 1: Preparar el contexto de la transacción

Antes de llamar a Tracer, reúne todos los datos relevantes de tus sistemas:

<Frame caption="Figura 2. Preparación del contexto de la transacción">
  <img src="https://mintcdn.com/lerian-49cb71fc/RAVxFNT8MNA4GWjO/images/es/d2/integration-flow-tracer.svg?fit=max&auto=format&n=RAVxFNT8MNA4GWjO&q=85&s=a872ac9255dad64cfa86390f6006a02c" alt="Pasos para preparar el contexto de la transacción y llamar a Tracer, desde reunir los datos en tus sistemas hasta actuar según la decisión devuelta" width="1768" height="700" data-path="images/es/d2/integration-flow-tracer.svg" />
</Frame>

### Paso 2: Llamar a la API de Tracer

Envía una solicitud POST a `/v1/validations` con el contexto completo de la transacción, incluyendo:

* Detalles de la transacción (type, subType, amount, asset, timestamp)
* Información de la cuenta (obligatorio)
* Opcional: segmento, portafolio, comercio y <GMetadata>metadatos</GMetadata> personalizados

Para ver la estructura completa del payload y el detalle de los campos, consulta la [referencia de la API](/es/reference/products/tracer/validate-transaction).

### Paso 3: Gestionar la respuesta

Procesa la decisión que devuelve Tracer:

| Decisión | Acción                                                              |
| -------- | ------------------------------------------------------------------- |
| `ALLOW`  | Continúa con la transacción                                         |
| `DENY`   | Rechaza la transacción; muestra el motivo al usuario si corresponde |
| `REVIEW` | Ponla en cola para revisión manual en tu sistema de revisión        |

La respuesta incluye el `validationId` para correlacionar con el historial de validación, detalles sobre qué reglas coincidieron e información sobre el uso actual de los límites.

### Uso de metadatos

Los metadatos permiten pasar campos personalizados que tus reglas pueden evaluar. Úsalos para contexto como el canal, la información del dispositivo, el nivel del cliente o cualquier atributo específico del negocio.

<Note>
  Las claves de metadatos deben ser alfanuméricas, con guiones bajos como único carácter adicional permitido, y un máximo de 64 caracteres. Máximo de 50 entradas por solicitud.
</Note>

***

## Idempotencia de la solicitud

***

Las solicitudes de validación son **idempotentes** según el campo `requestId`. Si envías el mismo `requestId` dos veces, Tracer devuelve el resultado en caché de la primera solicitud en lugar de reprocesarla.

| Código de respuesta | Significado                                                      |
| ------------------- | ---------------------------------------------------------------- |
| `201 Created`       | Nueva validación procesada                                       |
| `200 OK`            | Solicitud duplicada detectada; se devuelve el resultado en caché |

El cuerpo de la respuesta es idéntico en ambos casos. Se recomienda que tu cliente trate ambos códigos de estado como éxito.

**Por qué importa:** los timeouts de red y los reintentos pueden causar solicitudes duplicadas. Sin idempotencia, una solicitud reintentada podría contarse dos veces contra los límites o crear registros de validación duplicados. El `requestId` garantiza una semántica de procesamiento exactamente una vez.

**Contrato de idempotencia:**

* Mismo `requestId` → Misma respuesta (garantizado)
* `requestId` diferente → Procesamiento independiente (incluso si los datos de la transacción son idénticos)

<Warning>
  Genera siempre un `requestId` único (UUID) para cada transacción nueva. Reutilizar un `requestId` de una transacción anterior devolverá el resultado antiguo, no procesará la transacción nueva.
</Warning>

***

## Autenticación

***

Tracer admite dos modos de autenticación. Puedes usarlos de forma independiente o juntos.

### Autenticación por clave de API

La opción más simple. Envía tu clave de API en el header `X-API-Key` con cada solicitud.

| Variable de entorno               | Descripción                                                                           |
| --------------------------------- | ------------------------------------------------------------------------------------- |
| `API_KEY_ENABLED`                 | Habilita la autenticación por clave de API (predeterminado: `false`)                  |
| `API_KEY`                         | El valor de la clave secreta                                                          |
| `API_KEY_ENABLED_ONLY_VALIDATION` | Usa la clave de API solo para el endpoint `/v1/validations` (predeterminado: `false`) |

### Autenticación por plugin (Access Manager)

Para despliegues empresariales, Tracer puede delegar la autenticación al [Lerian Access Manager](/es/platform/access-manager/auth-plugin). Esto permite la autenticación centralizada en todos los servicios de Lerian.

| Variable de entorno   | Descripción                                                                 |
| --------------------- | --------------------------------------------------------------------------- |
| `PLUGIN_AUTH_ENABLED` | Habilita la autenticación por plugin (predeterminado: `false`)              |
| `PLUGIN_AUTH_ADDRESS` | URL del servicio de autenticación (predeterminado: `http://localhost:4000`) |

### Prioridad de autenticación

Cuando habilitas ambos modos, Tracer usa esta prioridad:

1. Si `PLUGIN_AUTH_ENABLED=true` y el endpoint no tiene la flag de solo clave de API → autenticación por plugin
2. Si `API_KEY_ENABLED=true` o el endpoint lleva la flag de solo clave de API → autenticación por clave de API

Los endpoints de infraestructura (health checks, sondeo de versión, especificación de OpenAPI) omiten la autenticación y no forman parte de la superficie pública de la API `/v1/*` documentada en esta referencia.

<Note>
  Puedes configurar el endpoint `/v1/validations` para autenticación de solo clave de API mediante `API_KEY_ENABLED_ONLY_VALIDATION=true`. Esto resulta útil en escenarios de alto rendimiento donde la autenticación por plugin agrega una latencia inaceptable. **Esta flag es incompatible con el modo multi-tenant** (`MULTI_TENANT_ENABLED=true`). El servicio falla al iniciar con el código de error `0458`.
</Note>

### Autenticación multi-tenant

Cuando `MULTI_TENANT_ENABLED=true`, Tracer se ejecuta en modo multi-tenant y el modelo de autenticación cambia:

* **La autenticación por plugin es obligatoria.** El servicio falla al iniciar con el código de error `0457` si `PLUGIN_AUTH_ENABLED=false`.
* **Cada solicitud a `/v1/*` debe llevar un token bearer JWT** emitido por [Access Manager](/es/platform/access-manager): `Authorization: Bearer <jwt>`.
* **`tenantId` proviene del claim del JWT**, no de un header, path, body, metadatos o alcance de regla. No existe un header `X-Tenant-ID`. El identificador del tenant no tiene efecto en ningún otro lugar más allá del claim del token.
* Cada tenant opera en su propia base de datos PostgreSQL. El servicio de plataforma de multi-tenancy resuelve la conexión específica del tenant en el momento de la solicitud.
* **Los endpoints públicos (`/health`, `/readyz`, `/metrics`, `/version`) siguen sin autenticación** también en modo multi-tenant. El requisito del token bearer se aplica solo a `/v1/*`.

Si el JWT está ausente, malformado o expirado, la solicitud devuelve HTTP 401 con `"code": "Unauthenticated"`. Las claves de API faltantes devuelven el mismo código, sin un código TRC independiente.

Hay un caso distinto. Un token que **se analiza correctamente pero no lleva el claim `sub`** devuelve HTTP 401 y el código de error `0474` de inmediato. El claim `sub` es lo que el escritor de auditoría usa para atribuir la acción a un principal. Tracer falla de forma explícita en lugar de registrar el cambio contra un actor de sistema genérico. Confirma que tus tokens de Access Manager siempre lo lleven.

Si el despliegue multi-tenant alcanza su límite de tenants por instancia, las solicitudes para tenants fríos devuelven HTTP 503 con el código de error `0466` y un header `Retry-After`. Se recomienda que el cliente aplique backoff y reintente. El límite se restablece automáticamente a medida que el pool LRU expulsa a los tenants fríos.

Consulta [Multi-tenancy](/es/platform/multi-tenancy) para conocer el modelo de tenants en toda la plataforma.

***

## Consideraciones de rendimiento

***

Optimiza tu integración para baja latencia y alta confiabilidad.

### Presupuesto de timeout

Tracer apunta a responder en menos de **80ms (p99)**. Configura el timeout de tu cliente en consecuencia:

| Configuración       | Valor recomendado |
| ------------------- | ----------------- |
| Timeout del cliente | 100ms             |
| Timeout de conexión | 50ms              |
| Timeout de lectura  | 100ms             |

### Estrategia de reintento

Implementa lógica de reintento para fallas transitorias:

```
On 5xx error or timeout:
  - Wait 10ms
  - Retry once
  - If still failing, apply fallback policy
```

<Warning>
  No reintentes en errores 4xx. Estos indican solicitudes inválidas que fallarán de nuevo. Para los reintentos en 5xx/timeout, reutiliza el mismo requestId para aprovechar la idempotencia.
</Warning>

### Comportamiento de fallback

Decide qué sucede cuando Tracer no está disponible:

| Estrategia           | Cuándo usarla                                                            |
| -------------------- | ------------------------------------------------------------------------ |
| **Fail-open**        | Permite la transacción si Tracer está caído (prioriza la disponibilidad) |
| **Fail-closed**      | Deniega la transacción si Tracer está caído (prioriza la seguridad)      |
| **Queue for review** | Pone la transacción en cola para revisión manual                         |

Tu elección depende de tu tolerancia al riesgo y de los requisitos del negocio.

<Warning>
  **Errores comunes de integración:**

  * **"Mi reintento creó una validación duplicada."** Reutiliza el mismo `requestId` en los reintentos. Tracer deduplica por ese campo. La segunda llamada devuelve el resultado en caché (HTTP 200) sin crear otra validación. Si generas un UUID nuevo en cada reintento, anulas la idempotencia.
  * **"Mi cliente hace timeout a los 30 segundos, pero Tracer sigue procesando."** Tracer respeta sus propios plazos (meta de \~80ms p99). Si tu cliente abandona la llamada, Tracer de todas formas invierte ese trabajo en una respuesta. Configura el timeout del cliente de forma agresiva (100ms) y confía en la ruta de reintento.
  * **"Tracer rechaza mi validación con el código de error `0421` (timestamp demasiado antiguo) en transacciones legítimas."** La tolerancia predeterminada es de 24 horas. Verifica el reloj de tu servidor y el `transactionTimestamp` que envías. Si procesas por lotes con retraso, define el timestamp en el momento real de la transacción, no en el momento en que llamas a Tracer.
  * **"Las transacciones de prueba aparecen en el historial de validación de producción."** Tracer registra cada validación, incluidas las de entornos de prueba o staging que llaman a la misma instancia de Tracer. Usa `metadata.environment` (o algo similar) para etiquetar y filtrar el tráfico de prueba si compartes Tracer entre entornos.
</Warning>

***

## Actualidad de los datos

***

Como tú controlas el enriquecimiento del payload, la actualidad de los datos es tu responsabilidad. Tracer confía en los datos que proporcionas y no puede detectar información desactualizada.

| Tipo de dato             | Recomendación de actualidad                              | Riesgo si está desactualizado                                   |
| ------------------------ | -------------------------------------------------------- | --------------------------------------------------------------- |
| Estado de la cuenta      | Tiempo real o casi en tiempo real                        | Se pueden permitir transacciones en cuentas suspendidas         |
| Membresía de segmento    | Se puede almacenar en caché (cambia con poca frecuencia) | Se pueden aplicar límites o reglas incorrectos                  |
| Asignación de portafolio | Se puede almacenar en caché (cambia con poca frecuencia) | Coincidencia de alcance incorrecta                              |
| Datos del comercio       | Se puede almacenar en caché con actualización periódica  | Es posible que las reglas de riesgo no se activen correctamente |

<Warning>
  Los datos desactualizados generan decisiones incorrectas. Si suspendiste una cuenta pero tu caché la muestra como activa, Tracer permitirá transacciones que se recomienda denegar. Tu capa de enriquecimiento es la fuente de verdad para Tracer.
</Warning>

***

## Formato de fecha y hora

***

Todos los campos de fecha y hora deben usar el **formato RFC3339** con zona horaria obligatoria:

**Formatos válidos:**

```
2026-01-30T10:30:00Z           (UTC)
2026-01-30T10:30:00-03:00      (São Paulo timezone)
2026-01-30T00:00:00+00:00      (UTC explicit)
```

**Formatos inválidos:**

```
2026-01-30                     (date only - rejected)
2026-01-30T10:30:00            (missing timezone - rejected)
```

***

## Lista de verificación de integración

***

Antes de pasar a producción, verifica lo siguiente:

* [ ] Tu clave de API está lista y protegida
* [ ] Cada solicitud incluye un requestId único (UUID)
* [ ] El cliente trata las respuestas 201 y 200 como éxito
* [ ] El timeout de tu cliente es de 100ms
* [ ] Tu lógica de reintento cubre los errores 5xx
* [ ] Elegiste un comportamiento de fallback
* [ ] Tu payload lleva todos los campos obligatorios
* [ ] Los timestamps usan el formato RFC3339 con zona horaria
* [ ] Los códigos de activo están en ISO 4217 en mayúsculas
* [ ] Tu sistema gestiona cada decisión (ALLOW/DENY/REVIEW)
* [ ] Tu sistema registra los IDs de validación para correlacionarlos con el historial de validación

***

## Ejemplo de integración (pseudocódigo)

***

```python theme={null}
def validate_transaction(transaction):
    # Step 1: Enrich payload
    payload = {
        "requestId": generate_uuid(),
        "transactionType": transaction.type,
        "amount": transaction.amount,
        "asset": transaction.asset.upper(),
        "transactionTimestamp": now_rfc3339(),
        "account": get_account_context(transaction.account_id),
        "segment": get_segment_context(transaction.segment_id),
        "merchant": get_merchant_context(transaction.merchant_id),
        "metadata": transaction.custom_fields
    }

    # Step 2: Call Tracer
    try:
        response = http_post(
            url="https://tracer.example.com/v1/validations",
            headers={"X-API-Key": API_KEY},
            json=payload,
            timeout_ms=100
        )
    except Timeout:
        return apply_fallback_policy()
    except ServerError:
        return retry_once_or_fallback()

    # Step 3: Handle decision
    if response.decision == "ALLOW":
        return proceed_with_transaction()
    elif response.decision == "DENY":
        return reject_transaction(response.reason)
    elif response.decision == "REVIEW":
        return queue_for_manual_review(response.validationId)
```

***

## Próximos pasos

***

* **[Motor de reglas](./rule-engine.mdx)** - Crea reglas que evalúen el contexto que proporcionas
* **[Límites de gasto](./spending-limits.mdx)** - Configura límites que se apliquen a los alcances de tus transacciones
* **[Historial de validación y compliance](./audit-compliance.mdx)** - Consulta el historial de validación y úsalo en tus procesos de compliance
