Все ошибки API возвращаются в едином формате с HTTP-кодами.
{
"statusCode": 400,
"message": "Invalid QR code format",
"error": "Bad Request"
}Или с массивом ошибок валидации:
{
"statusCode": 400,
"message": [
"qrCode must be a string",
"qrCode should not be empty"
],
"error": "Bad Request"
}| Код | Описание |
|---|---|
| 200 | OK — запрос выполнен |
| 201 | Created — ресурс создан |
| Код | Описание | Действие |
|---|---|---|
| 400 | Bad Request | Проверьте параметры запроса |
| 401 | Unauthorized | Проверьте API-ключ |
| 403 | Forbidden | IP не в whitelist или компания отключена |
| 404 | Not Found | Ресурс не найден |
| 409 | Conflict | Ресурс уже существует |
| 422 | Unprocessable Entity | Валидация не пройдена |
| 429 | Too Many Requests | Rate limit превышен |
| Код | Описание | Действие |
|---|---|---|
| 500 | Internal Server Error | Повторите позже, свяжитесь с поддержкой |
| 502 | Bad Gateway | Проблема с upstream сервисом |
| 503 | Service Unavailable | Сервис временно недоступен |
| 504 | Gateway Timeout | Таймаут внешнего сервиса |
{
"statusCode": 401,
"message": "Invalid API key",
"error": "Unauthorized"
}Причины:
- Неверный API-ключ
- Ключ был ротирован
- Ключ отозван
Решение: Получите актуальный ключ через /auth/company/login
{
"statusCode": 403,
"message": "IP address not whitelisted",
"error": "Forbidden"
}Решение: Добавьте IP через менеджера
{
"statusCode": 400,
"message": "Quote expired",
"error": "Bad Request"
}Причина: TTL котировки 30 секунд
Решение: Создайте новую котировку через /orders/prepare
{
"statusCode": 400,
"message": "Insufficient balance",
"error": "Bad Request"
}Решение: Пополните баланс через депозит
{
"statusCode": 429,
"message": "Too many requests",
"error": "Too Many Requests"
}Решение: Уменьшите частоту запросов, используйте exponential backoff
| Код | Retry? | Стратегия |
|---|---|---|
| 400 | ❌ | Исправьте запрос |
| 401 | ❌ | Обновите ключ |
| 403 | ❌ | Свяжитесь с поддержкой |
| 404 | ❌ | Проверьте ID ресурса |
| 429 | ✅ | Exponential backoff |
| 500 | ✅ | Exponential backoff |
| 502 | ✅ | Подождите 30-60 секунд |
| 503 | ✅ | Exponential backoff |
| 504 | ✅ | Exponential backoff |
async function fetchWithRetry(url, options, maxRetries = 3) {
for (let attempt = 0; attempt < maxRetries; attempt++) {
try {
const response = await fetch(url, options);
if (response.ok) {
return response.json();
}
if (response.status < 500 && response.status !== 429) {
// Ошибка клиента — не повторяем
throw new Error(`Client error: ${response.status}`);
}
// Серверная ошибка или rate limit — повторяем
const delay = Math.min(1000 * Math.pow(2, attempt), 10000);
await new Promise(resolve => setTimeout(resolve, delay));
} catch (error) {
if (attempt === maxRetries - 1) throw error;
}
}
}Рекомендуем логировать:
function logApiError(response, requestId) {
console.error({
timestamp: new Date().toISOString(),
requestId,
statusCode: response.statusCode,
message: response.message,
error: response.error
});
}Отслеживайте:
- Частоту ошибок 4xx/5xx
- Время ответа API
- Rate limit hits (429)
- Webhook delivery failures
При постоянных ошибках 5xx свяжитесь с поддержкой:
- Telegram: @lumo_support_bot
- Укажите:
requestId, время, endpoint, payload