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

# POST /analyze

> Scoring de una transacción en tiempo real

```
POST {API_BASE}/v1/transactions/analyze
```

`{API_BASE}` es `https://sandbox-api.fraudeg.com/api` o `https://api.fraudeg.com/api`, según
tu [entorno](/entornos). En producción:

```
POST https://api.fraudeg.com/api/v1/transactions/analyze
```

Scorea una transacción en vivo y devuelve una decisión. Esta ruta **sí** trata la llamada
como tráfico live.

Para ver la respuesta del modelo maduro **sin** tratarla como live —en producción o en
pre-official-integration— usa [`/analyze/sandbox`](/referencia/analyze-sandbox). Ese path
es un modo, no el host sandbox.

## Headers

| Header              | Obligatorio | Descripción                                                              |
| ------------------- | ----------- | ------------------------------------------------------------------------ |
| `X-Api-Key`         | Sí          | Scope `TRANSACTIONS_WRITE`. Ver [Autenticación](/integrar/autenticacion) |
| `X-Idempotency-Key` | Sí          | 16–128 caracteres url-safe. Ver [Idempotencia](/integrar/idempotencia)   |
| `Content-Type`      | Sí          | `application/json`                                                       |

## Request

Campos obligatorios:

| Campo                | Tipo   | Alias de wire aceptado  |
| -------------------- | ------ | ----------------------- |
| `order_id`           | string | —                       |
| `user_id`            | string | —                       |
| `transaction_amount` | number | `total_value_usd`       |
| `payment_method`     | string | `paymentInstrumentType` |

El nombre canónico es `payment_method`. `paymentInstrumentType` es el mismo campo con otro
nombre en el JSON. Ver [Métodos de pago y rieles](/referencia/metodos-de-pago).

Todos los demás campos son opcionales. La lista completa está en [Campos](/integrar/campos).

```json theme={null}
{
  "order_id": "8788426783",
  "user_id": "usr_48213",
  "transaction_amount": 129.90,
  "payment_method": "card",
  "cavv_result": "failed",
  "device_id": "dvc_a91f",
  "ip_address": "190.12.4.55"
}
```

## Response

```json theme={null}
{
  "data": {
    "transaction_id": "01e6efd4-c884-5bc0-af43-68b3fac8d0f8",
    "order_id": "8788426783",
    "risk_score": 29.07,
    "risk_level": "medium",
    "flags": [
      {
        "code": "AUTH_3DS_FAILED",
        "category": "authentication",
        "severity": "high",
        "description": "3DS authentication explicitly failed"
      }
    ],
    "recommendation": "…",
    "decision": {
      "type": "BLOCK",
      "reason": ["AUTH_3DS_FAILED"],
      "confidence": 0.89,
      "conditions": []
    },
    "transaction_state": "BLOCKED"
  },
  "timestamp": "2026-07-29T16:43:36.22",
  "status": "OK"
}
```

Campo por campo: [Formato de respuesta](/referencia/respuesta). En particular:

* [`decision.type`](/conceptos/decisiones) es el único campo accionable — nunca actúes
  sobre `risk_score`.
* El catálogo de `flags[].code` vive en [Catálogo de flags](/referencia/flags), no aquí.
* `recommendation` es una frase en el idioma de la compañía. No ramifiques sobre ella.

## Errores

El envelope de error de la API pública es:

```json theme={null}
{
  "error_code": "DATA_CONFLICT",
  "message": "There is a conflict with the provided information.",
  "details": "A request with this X-Idempotency-Key is already in progress",
  "timestamp": "2026-07-29T16:43:36.22"
}
```

`error_code` es el catálogo de [códigos de error](/referencia/codigos-de-error). El texto
que distingue un caso de otro está en **`details`**, no en `message` (`message` es la prosa
genérica del código).

### HTTP de este endpoint

| HTTP  | `error_code` típico        | Cuándo                                                                                |
| ----- | -------------------------- | ------------------------------------------------------------------------------------- |
| `400` | `BAD_REQUEST`              | Header `X-Idempotency-Key` ausente o con formato inválido (16–128, alfabeto url-safe) |
| `403` | `INSUFFICIENT_PERMISSIONS` | La key no tiene `TRANSACTIONS_WRITE`, o se usa en una ruta que no acepta API keys     |
| `409` | `DATA_CONFLICT`            | **Dos casos**, distinguibles por `details`. Ver abajo                                 |
| `422` | `VALIDATION_ERROR`         | Payload inválido, o la misma `X-Idempotency-Key` se usó con un payload distinto       |
| `429` | `TOO_MANY_REQUESTS`        | Límite de tasa                                                                        |
| `503` | `SERVICE_UNAVAILABLE`      | Scoring no disponible; reintenta                                                      |

### Los dos `409`

Misma key HTTP, distinto `details`:

| `details` (extracto)                                                                                                         | Qué pasó                                                                          | Qué hacer                                                                     |
| ---------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------- | ----------------------------------------------------------------------------- |
| `A request with this X-Idempotency-Key is already in progress`                                                               | Hay una petición **en curso** con esa clave                                       | Reintenta más tarde **con la misma clave**                                    |
| `The response stored for this X-Idempotency-Key was produced by an earlier version of the API and can no longer be replayed` | La transacción **sí se scoreó**, pero la respuesta guardada ya no se puede releer | Reintenta con una **clave nueva**. Ver [Idempotencia](/integrar/idempotencia) |

Un `400`, `403` o `422` significa que la petición no llegó a scorear: no se persistió nada.
Un `409` es distinto: la transacción puede estar scoreada y guardada ya.
