Обработка ошибок
Коды ошибок MetalAPI и соответствующие им HTTP-статусы, а также обработка неудачных запросов и стратегия повторных попыток с примерами кода.
Формат ответа с ошибкой
Если запрос завершается неудачей, API отвечает HTTP-статусом ошибки и телом JSON с success: false. Объект error содержит числовой code, машиночитаемый type и понятное человеку сообщение info:
{
"success": false,
"error": {
"code": 101,
"type": "no_api_key",
"info": "User did not supply an API Key"
}
}Ориентируйтесь на code или type, а не на текст info, который может меняться. Коды совпадают с кодами прежних версий MetalAPI, поэтому существующие интеграции продолжают работать.
Ошибки аутентификации и аккаунта
101no_api_key(401): в запросе нет ключа API.102invalid_api_key(401): ключ неизвестен или отозван.103account_inactive(403): аккаунт неактивен. Обратитесь в поддержку.107origin_not_allowed(403): ключ с ограничением по доменам использован на сайте, которого нет в списке разрешённых.
Ошибки лимитов и тарифа
104too_many_requests(429): достигнут поминутный лимит. Подождите столько секунд, сколько указано в заголовкеRetry-After.105quota_exceeded(429): месячная квота исчерпана до 1-го числа следующего месяца (UTC).106plan_restriction(403): эндпоинт или параметр не входит в ваш тариф, например/caratна Free илиXAU-BIDна тарифах ниже Standard.
Ошибки валидации
Эти ошибки возвращаются с HTTP-статусом 400 и означают, что нужно исправить сам запрос:
201invalid_base: неизвестный символbase.202invalid_fromи203invalid_to: неизвестный символfromилиtoв/convert.204invalid_amount:amountне указан или не является числом.205invalid_date: дата в неверном формате или дата в будущем.206invalid_timeframe: не указанstart_dateилиend_dateлибо начало периода позже его конца.207timeframe_too_long: период длиннее, чем допускает ваш тариф (30 дней на Free, 365 на платных тарифах).208invalid_symbols: ни один из запрошенных символов не существует.209invalid_unit: неподдерживаемое значениеunit.210invalid_carat: неподдерживаемое значение каратов.
Неизвестные символы в currencies пропускаются, если хотя бы один символ корректен.
Другие ошибки
300no_results(404): запрос корректен, но данных нет — например, для даты раньше начала истории символа.404invalid_function(404): неизвестный эндпоинт. Проверьте URL.500server_error(500): непредвиденная ошибка на нашей стороне.503service_unavailable(503): данные о ценах временно недоступны.
Обработка ошибок в коде
Проверяйте success в каждом ответе и превращайте сбои в ошибки, которые ваш код может проанализировать. Эта вспомогательная функция также справляется с ответами не в формате JSON от прокси-серверов:
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;
}Стратегия повторных попыток
Повторяйте только те запросы, которые могут завершиться успешно со второй попытки:
104: подождитеRetry-Afterсекунд и повторите запрос.500,503и сетевые ошибки: повторяйте с экспоненциальной задержкой (1 с, 2 с, 4 с) и прекращайте после трёх повторов.- Всё остальное (с
101по103, с105по107, коды валидации2xx,300,404): не повторяйте. Вместо этого исправьте запрос, ключ или тариф.
Повтор запросов с ошибками 104 и 5xx ничего не стоит, потому что такие неудачные запросы не тарифицируются.
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" }));Похожие руководства
Готовы начать разработку?
Создайте бесплатный аккаунт, чтобы получить ключ API, или изучите все эндпоинты в справочнике API.