> ## 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.

# Tu primera transacción

> Un curl contra /analyze/sandbox, y en qué se distingue del host sandbox

Con tu API key ya generada, manda tu primera transacción al **modo sandbox** del scoring:
mismo modelo que producción, la transacción queda etiquetada y no cuenta como tráfico live.

Elige el [host de API](/entornos) de tu entorno. El ejemplo de abajo usa
pre-official-integration. Si ya estás en producción y solo quieres probar una llamada sin
mezclarla con el tráfico live, cambia el host a `https://api.fraudeg.com/api` y **deja**
el path `/analyze/sandbox`.

## `/analyze` vs `/analyze/sandbox`

| Ruta                                    | Qué hace                                                  |
| --------------------------------------- | --------------------------------------------------------- |
| `POST /v1/transactions/analyze`         | Scoring live: la transacción entra al historial operativo |
| `POST /v1/transactions/analyze/sandbox` | Misma evaluación; no se trata como tráfico live           |

Las dos existen en las dos APIs. `/analyze/sandbox` **no** es `sandbox.fraudeg.com` ni
`sandbox-api.fraudeg.com`. Ver [Entornos](/entornos).

## Request

Dos headers son obligatorios:

| Header              | Obligatorio | Detalle                                                                |
| ------------------- | ----------- | ---------------------------------------------------------------------- |
| `X-Api-Key`         | Sí          | Tu API key de **ese** entorno, con `TRANSACTIONS_WRITE`                |
| `X-Idempotency-Key` | Sí          | 16 a 128 caracteres url-safe, generados por ti, únicos por transacción |

```bash theme={null}
curl -X POST https://sandbox-api.fraudeg.com/api/v1/transactions/analyze/sandbox \
  -H "X-Api-Key: tu_api_key" \
  -H "X-Idempotency-Key: 3f9a2b7e-6c1d-4e2a-9f31-8a0c5d2b7e41" \
  -H "Content-Type: application/json" \
  -d '{
    "order_id": "8788426783",
    "user_id": "user-4471",
    "transaction_amount": 129.90,
    "payment_method": "card",
    "cavv_result": "failed"
  }'
```

`order_id`, `user_id`, `transaction_amount` y `payment_method` son obligatorios. El nombre
canónico es `payment_method` (se acepta el alias `paymentInstrumentType`).

## Respuesta

```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"
}
```

<Warning>
  En el ejemplo, `risk_score` es `29.07` — banda `medium` — pero la decisión es `BLOCK`.
  **Actúa siempre sobre `decision.type`, nunca sobre el score.** Ver
  [Score de riesgo](/conceptos/score-y-decision).
</Warning>

Para esta prueba puedes reusar la misma `X-Idempotency-Key` en reintentos: vas a recibir la
misma respuesta. Antes de pasar a producción, revisa [cómo generar una key real por
transacción](/integrar/produccion).

Siguiente paso: [Autenticación](/integrar/autenticacion).
