Manejo de errores
Códigos de error de MetalAPI, sus códigos de estado HTTP y cómo gestionar y reintentar las solicitudes fallidas, con ejemplos de código en JavaScript.
Formato de las respuestas de error
Cuando una solicitud falla, la API responde con un código de estado HTTP de error y un cuerpo JSON con success: false. El objeto error contiene un code numérico, un type legible por máquinas y un mensaje info legible por personas:
{
"success": false,
"error": {
"code": 101,
"type": "no_api_key",
"info": "User did not supply an API Key"
}
}Basa tu lógica en code o type, no en el texto de info, que puede cambiar. Los códigos son los mismos que en versiones anteriores de MetalAPI, así que las integraciones existentes siguen funcionando.
Errores de autenticación y de cuenta
101no_api_key(401): la solicitud no incluye ninguna clave API.102invalid_api_key(401): la clave es desconocida o ha sido revocada.103account_inactive(403): la cuenta no está activa. Contacta con el soporte.107origin_not_allowed(403): se usó una clave restringida por dominio desde un sitio web que no está en su lista de dominios permitidos.
Errores de límites y de plan
104too_many_requests(429): se alcanzó el límite por minuto. Espera el número de segundos indicado en la cabeceraRetry-After.105quota_exceeded(429): la cuota mensual está agotada hasta el día 1 del mes siguiente (UTC).106plan_restriction(403): el endpoint o el parámetro no está incluido en tu plan, como/caraten Free oXAU-BIDpor debajo de Standard.
Errores de validación
Devuelven el código de estado HTTP 400 y significan que hay que corregir la propia solicitud:
201invalid_base: símbolobasedesconocido.202invalid_fromy203invalid_to: símbolofromotodesconocido en/convert.204invalid_amount: faltaamounto no es un número.205invalid_date: fecha con formato incorrecto o fecha futura.206invalid_timeframe: faltastart_dateoend_date, o el inicio es posterior al final.207timeframe_too_long: el rango es más largo de lo que permite tu plan (30 días en Free, 365 en los planes de pago).208invalid_symbols: no existe ninguno de los símbolos solicitados.209invalid_unit:unitno admitida.210invalid_carat: quilate no admitido.
En currencies, los símbolos desconocidos se omiten siempre que al menos un símbolo sea válido.
Otros errores
300no_results(404): la consulta es válida pero no hay datos, por ejemplo, una fecha anterior al inicio del historial de un símbolo.404invalid_function(404): endpoint desconocido. Revisa la URL.500server_error(500): un error inesperado por nuestra parte.503service_unavailable(503): los datos de precios no están disponibles temporalmente.
Gestionar los errores en el código
Comprueba success en cada respuesta y convierte los fallos en errores que tu código pueda inspeccionar. Esta función auxiliar también gestiona las respuestas que no son JSON procedentes de proxies:
async function metalapi(path, params = {}) {
const url = new URL(`https://metalapi.com/api/v1/${path}`);
for (const [key, value] of Object.entries(params)) url.searchParams.set(key, value);
const res = await fetch(url, { headers: { "X-API-Key": process.env.METALAPI_KEY } });
const data = await res.json().catch(() => ({
success: false,
error: { code: res.status, type: "http_error", info: res.statusText },
}));
if (!data.success) {
const err = new Error(`MetalAPI ${data.error.code} (${data.error.type}): ${data.error.info}`);
err.code = data.error.code;
err.retryAfter = Number(res.headers.get("Retry-After")) || undefined;
throw err;
}
return data;
}Estrategia de reintentos
Reintenta solo los errores que pueden tener éxito en un segundo intento:
104: esperaRetry-Aftersegundos y vuelve a intentarlo.500,503y errores de red: reintenta con backoff exponencial (1 s, 2 s, 4 s) y desiste después de tres reintentos.- Todo lo demás (
101a103,105a107, los códigos de validación2xx,300,404): no lo reintentes. Corrige la solicitud, la clave o el plan.
Reintentar los errores 104 y 5xx no cuesta nada, porque esas solicitudes fallidas no se facturan.
async function withRetry(fn, retries = 3) {
for (let attempt = 0; ; attempt++) {
try {
return await fn();
} catch (err) {
const retryable = err.code === undefined || err.code === 104 || err.code >= 500;
if (!retryable || attempt >= retries) throw err;
const delay = err.retryAfter ? err.retryAfter * 1000 : 1000 * 2 ** attempt;
await new Promise((resolve) => setTimeout(resolve, delay));
}
}
}
const data = await withRetry(() => metalapi("latest", { currencies: "XAU,XAG" }));Guías relacionadas
¿Listo para empezar a desarrollar?
Crea una cuenta gratuita para obtener tu clave API o explora todos los endpoints en la referencia de la API.