Перейти к содержимому

Обработка ошибок

UnoAPI использует стандартные HTTP-коды ответов и возвращает детальную информацию об ошибках в JSON-формате.

Все ошибки возвращаются в едином формате:

{
"error": "error_code",
"message": "Human-readable description of the error"
}
ПолеТипОписание
errorstringМашиночитаемый код ошибки (snake_case)
messagestringОписание ошибки для разработчика
КодОписание
200Запрос выполнен успешно
201Ресурс создан
204Запрос выполнен, тело ответа пустое
КодОшибкаОписание
400bad_requestНеверные параметры запроса
401unauthorizedОтсутствует или неверный API-ключ
403forbiddenДоступ запрещён (план, IP, ресурс)
404not_foundРесурс не найден
408timeoutТаймаут выполнения запроса
422validation_errorОшибка валидации данных
429rate_limitПревышен лимит запросов
КодОшибкаОписание
500internal_errorВнутренняя ошибка сервера
502bad_gatewayОшибка upstream-сервиса
503service_unavailableСервис временно недоступен
504gateway_timeoutТаймаут upstream-сервиса

При превышении лимита запросов возвращается код 429 с дополнительными заголовками:

HTTP/1.1 429 Too Many Requests
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1706745600
Retry-After: 60
ЗаголовокОписание
X-RateLimit-LimitМаксимум запросов в текущем окне
X-RateLimit-RemainingОставшиеся запросы
X-RateLimit-ResetUnix timestamp сброса лимита
Retry-AfterСекунды до возможности повтора
interface UnoAPIError {
error: string;
message: string;
}
async function callAPI(path: string) {
const response = await fetch(`https://proxy.unoapi.ru${path}`, {
headers: { 'Authorization': `Bearer ${process.env.UNOAPI_KEY}` }
});
if (!response.ok) {
const error: UnoAPIError = await response.json();
switch (response.status) {
case 401:
throw new Error('Invalid API key');
case 429:
const retryAfter = response.headers.get('Retry-After');
throw new Error(`Rate limited. Retry after ${retryAfter}s`);
case 500:
case 502:
case 503:
throw new Error(`Server error: ${error.message}`);
default:
throw new Error(`API error: ${error.message}`);
}
}
return response.json();
}
// Использование с retry
async function callAPIWithRetry(path: string, maxRetries = 3) {
for (let i = 0; i < maxRetries; i++) {
try {
return await callAPI(path);
} catch (err) {
if (i === maxRetries - 1) throw err;
await new Promise(r => setTimeout(r, Math.pow(2, i) * 1000));
}
}
}

Рекомендуемая стратегия повторных запросов:

КодRetry?Стратегия
400, 401, 403, 404❌ НетИсправьте запрос
408✅ ДаНемедленный retry (1-2 раза)
429✅ ДаПодождите Retry-After секунд
500, 502, 503✅ ДаExponential backoff (1s, 2s, 4s…)
504✅ ДаExponential backoff + увеличьте timeout

Формула задержки между retry:

delay = min(base_delay * 2^attempt + random_jitter, max_delay)

Типичные значения:

  • base_delay: 1 секунда
  • max_delay: 30 секунд
  • random_jitter: 0-1 секунда
  • max_attempts: 3-5
{
"error": "invalid_ip",
"message": "Invalid IP address format"
}

Решение: Проверьте формат IP-адреса (IPv4 или IPv6)

{
"error": "private_ip",
"message": "Private IP addresses are not supported"
}

Решение: Используйте публичный IP-адрес

{
"error": "invalid_url",
"message": "URL must be a valid HTTP or HTTPS URL"
}

Решение: URL должен начинаться с http:// или https://

{
"error": "batch_too_large",
"message": "Batch size exceeds maximum of 100"
}

Решение: Разбейте запрос на части по 100 элементов

Рекомендуем логировать все ошибки API для анализа. Обращайте внимание на:

  • Частые 400 — проблемы с валидацией на клиенте
  • Рост 429 — пора увеличить тарифный план
  • Всплески 5xx — проблемы на стороне API

При систематических ошибках 5xx проверьте статус-страницу или напишите в поддержку.