Skip to content

Errores y reintentos

La forma

Toda respuesta tiene el mismo sobre, salga bien o mal:

json
{
  "success": false,
  "message": "La cotización ya no es válida",
  "data": null,
  "code": "orders.quote_expired",
  "timestamp": "2026-08-02T21:14:03.221Z",
  "traceId": "01J9…"
}

Ramifica por code, nunca por message

El mensaje está traducido y puede reescribirse; el código es parte del contrato. Manda x-lang: en si prefieres leer inglés mientras desarrollas.

traceId identifica esa llamada exacta en los registros de la plataforma. Citarlo en una solicitud de soporte es la diferencia entre un diagnóstico y una conversación.

Qué reintentar

La única pregunta que importa es si repetir la llamada podría cambiar la respuesta.

Estado¿Reintentar?Por qué
408, 429, 502, 503, 504, con espera crecienteTransitorio. El mercado o la red, no tú.
500Una vez, y luego alertarAlgo va mal que un reintento no arregla.
400, 422NoLa petición está mal o el mundo dice que no. Misma entrada, misma respuesta.
401NoVer autenticación. Reintentar una credencial mala es cómo te limitan.
403NoFalta un alcance. Nadie lo concede porque se lo pidan dos veces.
404, 409, 410NoEl estado es el que es. Léelo antes de volver a actuar.

Espera exponencial con jitter, y un techo. Un bucle de reintentos sin techo contra un endpoint que retiene un saldo es cómo una integración atascada se convierte en un incidente.

Códigos que conviene manejar aparte

quotes.quote_below_executable_rate (422) — el precio ofrecido quedaría por debajo de lo que cuesta ejecutar la operación, así que la plataforma se niega a entregarte una pérdida. No es transitorio y no es un fallo. Se resuelve cuando el mercado se mueve o cuando Vectrakpital reprecia el corredor. Muéstralo como «sin precio en este momento», no como un error.

orders.quote_expired (410) — una cotización sostiene un precio durante una ventana corta y esa ventana se cerró. Pide una nueva; no reintentes el mismo quoteId, nunca.

deposits.declaration_already_open (409) — tienes una declaración abierta. Lee GET /api/v1/deposits/open-declaration y úsala o cancélala. Dos declaraciones abiertas de una misma organización harían ambigua una llegada, que es lo único por lo que vale la pena negarse.

clients.client_cannot_operate (403) — la organización no está activa, o no tiene límites cargados. Las cotizaciones siguen funcionando; nada más. Esto es una conversación con Vectrakpital, no algo de lo que tu código se recupere.

ledger.ledger_not_reconciled (409) — los libros de la plataforma y el saldo del mercado no coinciden, así que ha dejado de tomar decisiones hasta que una persona lo mire. Nada de lo que envíes va a pasar, y tu petición no tiene nada malo. Alerta y espera.

Llamar dos veces

Las lecturas son seguras. Repítelas cuanto quieras.

Las escrituras no son uniformemente idempotentes todavía, y es mejor decirlo que insinuar lo contrario.

  • Declarar un depósito está protegido de por sí: una declaración abierta por organización, así que repetir responde 409 en vez de crear una segunda.
  • Aceptar una cotización la consume. Repetir con el mismo quoteId falla; no creará dos cambios.
  • Pedir un retiro es el que hay que cuidar. Una llamada reintentada tras un tiempo de espera puede crear una segunda solicitud. Las dos necesitan que una persona las apruebe, así que nada se mueve dos veces sin que alguien vea dos filas idénticas — pero no te apoyes en eso. Lee GET /api/v1/withdrawals antes de reintentar una solicitud cuya respuesta nunca recibiste.

Si un tiempo de espera te deja con la duda, lee antes de volver a escribir

Cada endpoint que crea algo tiene uno de listado al lado, exactamente para esto.

Límites de tasa

Se aplican límites compartidos por dirección. Un 429 significa espera; no significa que la llave tenga nada malo. Si tu integración consulta periódicamente, hazlo con un horario y no en bucle: los saldos cambian cuando se mueve dinero, y el dinero se mueve cuando una persona aprueba, que no es algo que ocurra cada segundo.