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.
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)
· 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).
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 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.
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).
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.
Siguiente: 3 · Decisión de acreditación.