Skip to main content

Estructura de Errores

Todos los errores siguen esta estructura:
{
  "error": "VALIDATION_ERROR",
  "message": "Invalid currency code",
  "details": {
    "field": "currency",
    "value": "INVALID",
    "allowed": ["USD", "VES", "COP", "MXN"]
  },
  "requestId": "req_abc123"
}
CampoDescripción
errorCódigo de error (para lógica)
messageMensaje legible
detailsInformación adicional
requestIdID para soporte

Códigos HTTP

4xx - Errores del Cliente

CódigoErrorDescripción
400INVALID_REQUESTParámetros inválidos
401UNAUTHORIZEDAPI Key inválida
403FORBIDDENSin permisos
404NOT_FOUNDRecurso no existe
409CONFLICTConflicto de estado
422VALIDATION_ERRORError de validación
429RATE_LIMITEDDemasiadas solicitudes

5xx - Errores del Servidor

CódigoErrorDescripción
500INTERNAL_ERRORError interno
502BAD_GATEWAYError de gateway
503SERVICE_UNAVAILABLEServicio no disponible

Errores Comunes

UNAUTHORIZED (401)

{
  "error": "UNAUTHORIZED",
  "message": "Invalid or missing API key"
}
Causas:
  • API Key faltante
  • API Key inválida
  • API Key de ambiente incorrecto
Solución:
# Verificar que el header esté presente
curl -v -X GET "https://sandbox-api.cobrix.co/api/..." \
  -H "Authorization: Bearer tu_access_token"

PRODUCT_NOT_FOUND (404)

{
  "error": "PRODUCT_NOT_FOUND",
  "message": "No product found with SKU: PROD-001"
}
Solución: Es normal si el producto no existe. Créalo:
// Si no existe, crear
try {
  product = await client.get(`/product/sku/${sku}`);
} catch (error) {
  if (error.response?.status === 404) {
    product = await client.post('/checkout/product', data);
  }
}

VALIDATION_ERROR (422)

{
  "error": "VALIDATION_ERROR",
  "message": "Invalid currency code",
  "details": {
    "field": "currency",
    "value": "INVALID",
    "allowed": ["USD", "VES", "COP", "MXN"]
  }
}
Solución: Revisar el campo indicado en details.field y usar un valor válido.

RATE_LIMITED (429)

{
  "error": "RATE_LIMITED",
  "message": "Too many requests",
  "retryAfter": 60
}
Headers:
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1706023860
Retry-After: 60
Solución: Implementar backoff exponencial:
async function requestWithRetry(fn, maxRetries = 3) {
  for (let i = 0; i < maxRetries; i++) {
    try {
      return await fn();
    } catch (error) {
      if (error.response?.status === 429) {
        const wait = error.response.headers['retry-after'] || 60;
        await new Promise(r => setTimeout(r, wait * 1000));
      } else {
        throw error;
      }
    }
  }
}

SESSION_EXPIRED (409)

{
  "error": "SESSION_EXPIRED",
  "message": "Checkout session has expired"
}
Solución: Crear una nueva sesión de checkout.

Errores de Webhook

Firma Inválida

Síntoma: Tu endpoint retorna 401 Checklist:
¿Estás usando el raw body (sin parsear)?
¿El webhook secret es correcto?
¿El timestamp no es muy antiguo (>5 min)?
Express.js correcto:
// ✅ Correcto
app.post('/webhooks/cobrix',
  express.raw({ type: 'application/json' }),
  (req, res) => {
    const rawBody = req.body.toString();
    // ...
  }
);

// ❌ Incorrecto - body ya parseado
app.use(express.json());

Manejo de Errores

Ejemplo Completo

async function cobrixRequest(fn) {
  try {
    return await fn();
  } catch (error) {
    const { status, data } = error.response || {};
    
    switch (status) {
      case 401:
        console.error('API Key inválida');
        throw new Error('Authentication failed');
        
      case 404:
        // Puede ser normal (producto no existe)
        return null;
        
      case 422:
        console.error('Validación fallida:', data.details);
        throw new Error(`Validation: ${data.message}`);
        
      case 429:
        const wait = error.response.headers['retry-after'];
        console.log(`Rate limited, esperando ${wait}s`);
        await sleep(wait * 1000);
        return cobrixRequest(fn); // Reintentar
        
      case 500:
      case 502:
      case 503:
        console.error('Error del servidor, reintentando...');
        await sleep(5000);
        return cobrixRequest(fn);
        
      default:
        throw error;
    }
  }
}

Contactar Soporte

Si el error persiste, contacta soporte con:
  • Request ID (del error)
  • Timestamp
  • Endpoint
  • Request/Response (sin datos sensibles)
  • Ambiente (Sandbox/Producción)
📧 [email protected]