# 2 · Reporte de depósito

Fase 2 del flujo. Felix envía USDC a la billetera de custodia BitGo de Nexa.
Tesser tiene las llaves de esa billetera, observa la llegada de los fondos y
**se la reporta** a Nexa junto con los resultados de la evaluación de riesgo
de la plataforma principal de Tesser.

<Mermaid
  chart={`sequenceDiagram
    autonumber
    participant T as Tesser (orquestador)
    participant N as Banco Nexa

    Note over T,N: Fase 2 · Depósito de USDC (Felix → BitGo, observado por Tesser)
    T->>N: POST /v1/quotes/{tesser_quote_id}/deposits [N]<br/>(usdc_amount, evaluación de riesgo, hashes de transacción)
    N-->>T: 200 DEPOSIT_REPORTED (solo acuse de recibo)`}
/>

## Paso 3 · Reportar el depósito de USDC <N />

**Operación:** [`POST /v1/quotes/{tesser_quote_id}/deposits`: Reportar depósito de USDC (op 3)](/api-nexa/deposits#report-usdc-deposit-op-3)
· lo aloja **Nexa**, lo llama **Tesser**.

**Esto es un reporte, no una solicitud.** Tesser deja constancia de hechos:
llegó USDC, por este monto, mediante estas transacciones y con estos
resultados de evaluación de riesgo. Solo Nexa decide qué hacer con el reporte
(acreditar, solicitar fondos adicionales o rechazar), y esa decisión llega
**de forma asíncrona por webhook**
([fase 3](/es/flow-nexa/credit-decision)).

En consecuencia, este endpoint **no devuelve errores síncronos de riesgo ni
de monto**. Un 2xx significa "reporte registrado", nada más. No significa que
Nexa haya aceptado el monto, ni que el resultado de riesgo haya sido
satisfactorio.

**Tesser siempre reporta todo depósito que observa, incluso cuando la
evaluación de riesgo lo rechaza.** El resultado de cumplimiento viaja dentro
del contenido del reporte; nunca suprime el reporte.

### El contenido del reporte

| Campo | Notas |
| --- | --- |
| `tesser_deposit_id` | UUIDv4 generado por Tesser; llave de idempotencia de *este reporte*. |
| `usdc_amount` | Lo que efectivamente llegó en este reporte, que no necesariamente es el `usdc_amount` cotizado. |
| `risk_status` | Enum de la API principal de Tesser, textual: `unchecked`, `awaiting_decision`, `automatically_approved`, `manually_approved`, `automatically_rejected`, `manually_rejected`. |
| `risk_status_reasons` | Objetos `RiskStatusReason` de la API principal de Tesser, textuales. `risk_status_reason_type` es uno de `ENTITY`, `ACCOUNT`, `OWNERSHIP`, `COUNTERPARTY`, `INDIRECT`, `BEHAVIORAL`, `ERROR`, más una categoría y un mensaje. |
| `transaction_hashes` | La transacción o transacciones en cadena. Este es el campo con el que ambos equipos de operaciones concilian contra la cadena cuando algo no cuadra. |

Esos dos campos son tipos de la API principal de Tesser usados de forma
textual, de modo que existe un único diccionario de cumplimiento compartido
por las dos empresas.

### Repetible por diseño

Cada reporte es un subrecurso nuevo, así que una cotización puede acumular
varios. Eso es lo que hace funcionar el flujo de fondos adicionales. El campo
`usdc_total_reported` de la respuesta es la suma de todos los reportes de la
cotización.

**Los reportes tardíos** (un reporte que llega cuando la cotización ya está
en `CREDIT_SENT`, `CREDIT_CONFIRMED` o `PAYMENT_*`, por ejemplo cuando Felix
envía fondos extra después de la acreditación) devuelven `200`, se registran
sin cambio de estado, aparecen en el arreglo `deposits` del
[GET de la cotización](/api-nexa/quotes#get-quote-optional-op-8) y quedan
marcados para revisión de operaciones en ambos lados. La regla de reportar
siempre no tiene excepción, así que este caso tiene una semántica de éxito
definida. Lo que Nexa *hace* con los fondos tardíos es parte de la
[pregunta abierta 3](/es/open-questions).

### El rechazo no deshace nada

El USDC ya se movió en cadena antes de que este endpoint llegue siquiera a
invocarse. Una decisión posterior de `quote.rejected` significa "Nexa no
acreditará los GTQ", no "el depósito no ocurrió". Qué se hace con el USDC
recibido (¿devolverlo?, ¿retenerlo a la espera de una revisión?) es un asunto
operativo y fuera de banda para el POC
([pregunta abierta 4](/es/open-questions)).

<div className="what-can-go-wrong">

**Qué puede salir mal: reportar el depósito de USDC**

| `error_code` | HTTP | Cuándo |
| --- | --- | --- |
| `VALIDATION_ERROR` | 400 | Monto mal formado, UUID inválido, campos de riesgo ausentes. |
| `UNAUTHENTICATED` | 401 | Falta el certificado de cliente o la llave de API del cliente, o son inválidos. |
| `QUOTE_NOT_FOUND` | 404 | No existe ninguna cotización con este `tesser_quote_id`. |
| `QUOTE_NOT_ACCEPTED` | 409 | La cotización sigue en `CREATED`. Primero hay que aceptarla. |
| `QUOTE_EXPIRED` | 409 | La cotización llegó a `EXPIRED` antes de que se reportara algún depósito. |
| `QUOTE_REJECTED` | 409 | La cotización está en `REJECTED`. La vía de recuperación es una cotización nueva. |
| `DEPOSIT_CONFLICT` | 409 | Mismo `tesser_deposit_id`, cuerpo distinto. |
| `INTERNAL_ERROR` | 500 | Falla inesperada del lado de Nexa. |

Aquí, de forma deliberada, **no** existe un error de rechazo por riesgo **ni**
un error por discrepancia de monto. Ambos son decisiones, y las decisiones
llegan por webhook.

</div>

**Siguiente:** [3 · Decisión de acreditación](/es/flow-nexa/credit-decision).
