Skip to main content

Documentation Index

Fetch the complete documentation index at: https://developer.mouvlatam.com/llms.txt

Use this file to discover all available pages before exploring further.

Estructura de errores

Todas las respuestas de error tienen este shape:
{
  "error": "CODIGO_MAYUSCULAS_SNAKE_CASE",
  "message": "Descripción human-readable en español",
  "details": { /* opcional, contextual */ }
}
StatusSignificadoAcción recomendada
400Body inválidoCorregir request
401API key inválida o no presenteVerificar header Authorization
403Scope insuficiente o cuenta inactivaRegenerar llave con scope correcto
404Recurso no encontradoVerificar ID
422Validación lógica fallóMensaje propio del error
429Rate limit excedidoEsperar Retry-After segundos
502Error del proveedor upstreamReintento con backoff exponencial
503Servicio temporalmente no disponibleReintento con backoff

Errores comunes

CódigoStatusSignificado
AUTH_REQUIRED401Falta header Authorization
INVALID_API_KEY401Llave inválida o revocada
COMPANY_INACTIVE401Cuenta suspendida — contactar soporte
INSUFFICIENT_SCOPE403Llave READ intentando operación WRITE
API_KEY_AUTH_NOT_ALLOWED403Operación requiere sesión dashboard (no API key)
RATE_LIMIT_EXCEEDED429Demasiadas requests — esperar Retry-After
INVALID_REQUEST400Body o query parameters inválidos

Saldos

CódigoStatusSignificado
WALLET_NOT_PROVISIONED404La empresa aún no tiene wallet aprovisionada
FAST_WALLET_MISSING404Schema invariant defensivo — contactar soporte

Retiros BREB

CódigoStatusSignificado
BREB_DIRECTORY_LOOKUP_FAILED503Red Bre-B no responde — reintento con backoff
INVALID_KEY422Llave Bre-B malformada
KEY_INACTIVE422Llave existe pero no está activa en Bre-B
INSUFFICIENT_BALANCE422Saldo BREB no alcanza para monto + fee + IVA
TARGET_DOCUMENT_REQUIRED422Falta targetDocument (compliance SARLAFT)
AMOUNT_EXCEEDS_BREB_CAP422Bre-B individual cap es $12M COP
NAME_MISMATCH422Nombre cargado no coincide con titular Bre-B

Retiros ACH

CódigoStatusSignificado
ACH_RAIL_UNAVAILABLE503Rail ACH temporalmente caído
INVALID_BANK_ACCOUNT422Validación de cuenta falló (formato o titular)
INSUFFICIENT_BALANCE422Saldo ACH no alcanza
AMOUNT_EXCEEDS_ACH_CAP422ACH individual cap es $2.000M COP
DESTINATION_REJECTED400Banco / cuenta rechazado por reglas internas

Recaudos PSE

CódigoStatusSignificado
PSE_PROVIDER_NOT_CONFIGURED503Operator misconfig — contactar soporte
PSE_INFLOW_DISABLED503PSE temporalmente bloqueado por incident response
PSE_PROVIDER_ERROR502Proveedor PSE upstream falló — reintentar
FEE_EXCEEDS_AMOUNT422FeeConfig produce fee+IVA >= monto del depósito
RECIPIENT_BLACKLISTED422El pagador está en lista AML — bloqueado por compliance

Multi-sig

CódigoStatusSignificado
AWAITING_APPROVAL200 (body)Transferencia espera firmas (no es error técnico)
APPROVAL_EXPIRED422TTL 24h expirado, transferencia revertida
INVALID_TOTP_CODE401Código 2FA inválido al firmar

AML / Counterparty limits

CódigoStatusSignificado
COUNTERPARTY_DAILY_LIMIT_EXCEEDED422Tope diario por tercero excedido
COUNTERPARTY_MONTHLY_LIMIT_EXCEEDED422Tope mensual por tercero excedido

Estrategia de reintentos recomendada

async function mouvRequestWithRetry(url, options, maxRetries = 3) {
  for (let i = 0; i < maxRetries; i++) {
    const res = await fetch(url, options);

    // Éxito
    if (res.ok) return res.json();

    const body = await res.json();

    // Errores que NO se reintenan
    if (res.status === 400 || res.status === 401 || res.status === 403 || res.status === 422) {
      throw new Error(body.error);
    }

    // Rate limit: respect Retry-After
    if (res.status === 429) {
      const wait = parseInt(res.headers.get('Retry-After') || '1') * 1000;
      await new Promise(r => setTimeout(r, wait));
      continue;
    }

    // 5xx: backoff exponencial
    if (res.status >= 500) {
      const wait = Math.pow(2, i) * 1000; // 1s, 2s, 4s
      await new Promise(r => setTimeout(r, wait));
      continue;
    }
  }
  throw new Error('MAX_RETRIES_EXCEEDED');
}

Idempotencia

Para operaciones financieras, el campo reference del request body actúa como idempotency key opcional. Si reenviás la misma request con el mismo reference dentro de los próximos 60s, recibís la transacción original en lugar de duplicar.
curl -X POST https://consola.mouvlatam.com/api/transfers/send \
  -H "Authorization: Bearer mvk_..." \
  -d '{ "amount": 100000, ..., "reference": "factura-001-2026" }'
Si la primera request 5xx-falló y reintentas con el mismo reference, Mouv resuelve el conflicto:
  • Si la operación original SÍ se dispatchó upstream → response original
  • Si NO se dispatchó → procesa la nueva request normalmente