Manejo de Errores
Aprende a manejar los errores de la API de forma efectiva y proporcionar una buena experiencia a tus usuarios.
Formato de errores
Cuando ocurre un error, la API retorna una respuesta JSON con la siguiente estructura:
{
"success": false,
"error": {
"code": "ERROR_CODE",
"message": "Descripción legible del error",
"details": {}
}
}
| Campo | Tipo | Descripción |
|---|---|---|
success |
boolean | Siempre false en errores |
error.code |
string | Código de error único para identificar el tipo de error |
error.message |
string | Mensaje descriptivo del error |
error.details |
object | Información adicional específica del error (opcional) |
Códigos HTTP
La API usa códigos de estado HTTP estándar:
| Código | Significado | Cuándo ocurre |
|---|---|---|
200 |
OK | Solicitud exitosa (GET) |
201 |
Created | Recurso creado exitosamente (POST) |
400 |
Bad Request | Parámetros inválidos o faltantes |
401 |
Unauthorized | Credenciales inválidas o faltantes |
404 |
Not Found | Orden no encontrada |
429 |
Too Many Requests | Límite de solicitudes excedido |
500 |
Internal Server Error | Error interno del servidor |
Errores de Autenticación (401)
| Código | Descripción | Solución |
|---|---|---|
MISSING_CREDENTIALS |
Faltan los headers X-Api-Key o X-Api-Secret | Incluye ambos headers en la solicitud |
INVALID_CREDENTIALS |
API Key o Secret inválidos | Verifica que las credenciales sean correctas |
MERCHANT_NOT_ACTIVE |
La cuenta del merchant no está activa | Contacta a soporte para verificar el estado de tu cuenta |
Ejemplo
{
"success": false,
"error": {
"code": "INVALID_CREDENTIALS",
"message": "Invalid API credentials",
"details": {}
}
}
Errores de Validación (400)
| Código | Descripción | Solución |
|---|---|---|
INVALID_AMOUNT |
El monto es inválido o menor al mínimo | El monto debe ser un número mayor o igual a 1,000 COP |
INVALID_REFERENCE |
La referencia es inválida o muy larga | Usa una referencia string de máximo 100 caracteres |
INVALID_EMAIL |
El email del cliente no es válido | Verifica el formato del email |
INVALID_DOC_TYPE |
Tipo de documento no válido | Usa: CC, CE, NIT, o PP |
MISSING_REQUIRED_FIELD |
Falta un campo requerido | Revisa que incluyas todos los campos requeridos |
NO_VALID_PAYMENT_METHODS |
No hay métodos de pago válidos | Verifica que tu cuenta tenga métodos de pago habilitados |
Ejemplo
{
"success": false,
"error": {
"code": "INVALID_AMOUNT",
"message": "Amount must be at least 1000 COP",
"details": {
"field": "amount",
"value": 500,
"minimum": 1000
}
}
}
Errores de Orden (400, 404)
| Código | HTTP | Descripción |
|---|---|---|
ORDER_NOT_FOUND |
404 | La orden no existe o no pertenece a tu cuenta |
ORDER_EXPIRED |
400 | La orden ya expiró |
INVALID_ORDER_STATUS |
400 | La orden no está en un estado válido para esta operación |
Ejemplo
{
"success": false,
"error": {
"code": "ORDER_NOT_FOUND",
"message": "Collect order not found",
"details": {}
}
}
Errores de Rate Limit (429)
Si excedes el límite de solicitudes, recibirás este error:
{
"success": false,
"error": {
"code": "RATE_LIMIT_EXCEEDED",
"message": "Too many requests. Please try again later.",
"details": {
"retryAfter": 60
}
}
}
Los headers de respuesta incluyen información sobre el límite:
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1705323600
Manejo de Errores en tu Código
Recomendamos implementar un manejo de errores robusto:
async function createCollectOrder(orderData) {
try {
const response = await fetch('https://api.prod.niiopay.com/api/v1/collect', {
method: 'POST',
headers: {
'X-Api-Key': process.env.NIIO_API_KEY,
'X-Api-Secret': process.env.NIIO_API_SECRET,
'Content-Type': 'application/json',
},
body: JSON.stringify(orderData),
});
const data = await response.json();
if (!data.success) {
// Manejar error según el código
switch (data.error.code) {
case 'INVALID_CREDENTIALS':
console.error('Error de autenticación');
throw new Error('Error de configuración');
case 'RATE_LIMIT_EXCEEDED':
// Esperar y reintentar
const retryAfter = data.error.details?.retryAfter || 60;
await new Promise(r => setTimeout(r, retryAfter * 1000));
return createCollectOrder(orderData);
default:
throw new Error(data.error.message);
}
}
return data.data;
} catch (error) {
console.error('Error al crear orden:', error);
throw error;
}
}
import requests
import time
import os
def create_collect_order(order_data):
try:
response = requests.post(
'https://api.prod.niiopay.com/api/v1/collect',
headers={
'X-Api-Key': os.environ['NIIO_API_KEY'],
'X-Api-Secret': os.environ['NIIO_API_SECRET'],
'Content-Type': 'application/json',
},
json=order_data,
timeout=30
)
data = response.json()
if not data.get('success'):
error_code = data.get('error', {}).get('code')
if error_code == 'INVALID_CREDENTIALS':
raise Exception('Error de configuración')
elif error_code == 'RATE_LIMIT_EXCEEDED':
retry_after = data['error'].get('details', {}).get('retryAfter', 60)
time.sleep(retry_after)
return create_collect_order(order_data)
else:
raise Exception(data['error']['message'])
return data['data']
except requests.exceptions.RequestException as e:
print(f'Error de conexión: {e}')
raise
Mensajes para el Usuario
Muestra mensajes amigables a tus usuarios según el tipo de error:
| Tipo de Error | Mensaje Sugerido |
|---|---|
| Validación (400) | "Por favor verifica los datos ingresados" |
| No encontrado (404) | "La orden de pago no existe o ya expiró" |
| Rate limit (429) | "Demasiados intentos. Espera un momento" |
| Error servidor (500) | "Error temporal. Intenta de nuevo en unos minutos" |
No expongas detalles técnicos
Nunca muestres códigos de error o detalles técnicos a los usuarios finales. Loguéalos internamente para debugging.