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

Коды ошибок и обработка ошибок API Lamoda

Обзор

Документация описывает коды ошибок и рекомендации по их обработке для всех трех API систем Lamoda:

  1. B2B Platform API (REST) - использует HTTP коды статуса
  2. Seller JSON-RPC API - использует JSON-RPC 2.0 коды ошибок
  3. Seller REST API - использует HTTP коды статуса

Все три API системы возвращают структурированные ответы об ошибках с подробным описанием проблемы.


1. B2B Platform API (REST) - Коды ошибок

HTTP Коды статуса

КодНазваниеОписаниеЧастые причины
400Bad RequestОшибка валидации данныхНеверные параметры, невалидный JSON
401UnauthorizedОшибка авторизацииОтсутствует или неверный токен
403ForbiddenДоступ запрещёнНедостаточно прав доступа
404Not FoundРесурс не найденНеверный URL или отсутствует ресурс
429Too Many RequestsПревышен Rate LimitСлишком много запросов
500Internal Server ErrorВнутренняя ошибка сервераОшибка на стороне сервера

Структура ошибки

Ответ для 400 (Bad Request)

{
"code": 0,
"description": "This value is not valid.",
"errors": [
{
"field": "field_name",
"message": "Error description"
}
]
}

Ответ для 401 (Unauthorized)

{
"code": 0,
"description": "Ошибка авторизации",
"errors": []
}

Ответ для 403 (Forbidden)

{
"code": 0,
"description": "Доступ запрещён",
"errors": []
}

Ответ для 404 (Not Found)

{
"code": 0,
"description": "Ресурс не найден",
"errors": []
}

Ответ для 429 (Rate Limit)

{
"code": 0,
"description": "Rate limit has been reached",
"message": "Ошибка по достижении RateLimit",
"errors": []
}

Особенности кода 429:

  • Встречается на endpoint: POST /api/v1/notifications/resend
  • Появляется при попытке переотправки уведомлений, которые уже в обработке
  • Рекомендуется использовать экспоненциальную задержку (exponential backoff)

Ответ для 500 (Internal Server Error)

{
"code": 0,
"description": "Внутренняя ошибка сервера",
"errors": []
}

Специфические коды ошибок

Подарочные сертификаты (GiftCard.Error)

Специальная структура ошибок для работы с подарочными сертификатами:

{
"code": 32700,
"message": "Error description",
"description": "Additional information",
"errors": ["error1", "error2"]
}

Коды ошибок подарочных сертификатов:

КодОписание
32700Ошибка парсинга JSON
32600Неверный запрос
32601Ответ не найден
32602Неверные параметры
32603Внутренняя ошибка
32000Ошибка сервера
1Ошибка не определена
0 - 32000Ошибка бизнес-логики

2. Seller JSON-RPC API - Коды ошибок

JSON-RPC 2.0 Стандартные коды

КодНазваниеОписание
-32700Parse errorОшибка парсинга JSON
-32600Invalid RequestНеверный запрос
-32601Method not foundМетод не найден
-32602Invalid paramsНеверные параметры
-32603Internal errorВнутренняя ошибка сервера

Структура ошибки JSON-RPC

{
"jsonrpc": "2.0",
"id": "request_id",
"error": {
"code": -32600,
"message": "Something went wrong",
"data": {
"additional": "error data"
}
}
}

Поля ошибки:

  • code (integer, required) - Код ошибки
  • message (string, required) - Человекочитаемое описание ошибки (для отладки)
  • data (object, optional) - Дополнительные данные об ошибке

Бизнес-логика ошибки

Коды от 0 до 32000 зарезервированы для ошибок бизнес-логики.

Ошибки обновления номенклатуры (NomenclatureUpdateError)

При массовом обновлении товаров может вернуться список ошибок:

{
"jsonrpc": "2.0",
"id": "request_id",
"result": {
"error_count": 2,
"errors": [
{
"warehouse_code": "WAREHOUSE1",
"barcode": "1234567890",
"error": {
"code": 400,
"message": "Validation error"
}
},
{
"warehouse_code": "WAREHOUSE2",
"barcode": "0987654321",
"error": {
"code": 404,
"message": "Product not found"
}
}
]
}
}

Поля NomenclatureUpdateError:

  • lamodaSku (string) - SKU товара Lamoda
  • code (integer) - Код ошибки
  • messages (array of string) - Список сообщений об ошибках

Частые сценарии ошибок JSON-RPC

1. Ошибка аутентификации

{
"jsonrpc": "2.0",
"id": "1",
"error": {
"code": 401,
"message": "Unauthorized",
"data": {
"details": "Token expired or invalid"
}
}
}

Решение: Получите новый токен через v1.tokens.create

2. Неверные параметры

{
"jsonrpc": "2.0",
"id": "2",
"error": {
"code": -32602,
"message": "Invalid params",
"data": {
"parameter": "sku",
"reason": "Required field missing"
}
}
}

Решение: Проверьте, что все обязательные параметры переданы и имеют верный тип

3. Товар не найден

{
"jsonrpc": "2.0",
"id": "3",
"error": {
"code": 404,
"message": "Product not found",
"data": {
"sku": "INVALID_SKU"
}
}
}

Решение: Проверьте корректность SKU, используйте v1.nomenclatures.list для поиска


3. Seller REST API - Коды ошибок

HTTP Коды статуса

КодНазваниеКод ошибкиОписание
400Bad RequestVALIDATION_FAILEDОшибка валидации данных
401UnauthorizedUNAUTHORIZEDТокен отсутствует или невалиден
403ForbiddenFORBIDDENДоступ запрещён
404Not FoundNOT_FOUNDРесурс не найден
503Service UnavailableSERVICE_UNAVAILABLEСервис временно недоступен

Структура ошибки REST API

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

{
"error": {
"code": "ERROR_CODE",
"message": "Человекочитаемое сообщение",
"details": [
{
"field": "field_name",
"issue": "описание проблемы"
}
]
}
}

Примеры ошибок

400 Bad Request - Ошибка валидации

{
"error": {
"code": "VALIDATION_FAILED",
"message": "Проверьте переданные данные",
"details": [
{
"field": "sellerId",
"issue": "Обязательное поле"
},
{
"field": "images[0].order",
"issue": "Должно быть положительным числом"
},
{
"field": "images",
"issue": "Список изображений не может быть пустым"
}
]
}
}

Частые причины:

  • Отсутствуют обязательные поля
  • Неверный тип данных
  • Значения вне допустимого диапазона
  • Неверный формат даты/времени

401 Unauthorized - Ошибка авторизации

{
"error": {
"code": "UNAUTHORIZED",
"message": "Токен отсутствует или невалиден"
}
}

Частые причины:

  • Токен истёк (15 минут для Seller API)
  • Токен не передан в заголовке Authorization
  • Неверный формат токена

Решение: Получите новый токен через JSON-RPC API: v1.tokens.create

403 Forbidden - Доступ запрещён

{
"error": {
"code": "FORBIDDEN",
"message": "Доступ запрещён"
}
}

Частые причины:

  • Попытка доступа к чужим данным (другой sellerId)
  • Недостаточно прав для операции

404 Not Found - Ресурс не найден

{
"error": {
"code": "NOT_FOUND",
"message": "Ресурс не найден"
}
}

Частые причины:

  • Неверный идентификатор (ID короба, товара и т.д.)
  • Ресурс был удален

503 Service Unavailable - Сервис недоступен

{
"error": {
"code": "SERVICE_UNAVAILABLE",
"message": "Сервис временно недоступен"
}
}

Решение: Повторите запрос с экспоненциальной задержкой


4. Общие сценарии ошибок

4.1 Ошибки аутентификации

Симптомы: Код 401 во всех API системах

Причины:

  1. Токен истёк
    • B2B Platform API: 24 часа
    • Seller APIs: 15 минут
  2. Токен не передан в заголовке Authorization
  3. Неверный формат токена (отсутствует префикс "Bearer ")

Решение:

# Проверьте наличие и формат токена
headers = {
"Authorization": f"Bearer {access_token}"
}

# Реализуйте автоматическое обновление токена
if response.status_code == 401:
new_token = get_new_token()
retry_request_with_new_token(new_token)

4.2 Ошибки валидации (400)

Симптомы: Код 400 с детализацией полей

Частые причины:

  1. Обязательные поля отсутствуют
  2. Неверный тип данных (строка вместо числа)
  3. Значения вне диапазона (отрицательная цена)
  4. Неверный формат даты

Решение:

# Проверьте ответ на детали ошибок
if response.status_code == 400:
error_data = response.json()
if "details" in error_data.get("error", {}):
for detail in error_data["error"]["details"]:
print(f"Поле: {detail['field']}, Проблема: {detail['issue']}")

4.3 Превышение Rate Limit (429)

Симптомы: Код 429 в B2B Platform API

Где встречается:

  • POST /api/v1/notifications/resend - переотправка уведомлений

Решение:

import time
import random

def request_with_backoff(url, headers, max_retries=5):
for attempt in range(max_retries):
response = requests.get(url, headers=headers)

if response.status_code != 429:
return response

# Экспоненциальная задержка с jitter
delay = (2 ** attempt) + random.uniform(0, 1)
print(f"Rate limited. Waiting {delay:.2f}s...")
time.sleep(delay)

return response # Последняя попытка

4.4 Ресурс не найден (404)

Симптомы: Код 404

Частые причины:

  1. Неверный идентификатор товара/заказа/короба
  2. Ресурс был удален
  3. Ресурс принадлежит другому продавцу

Решение:

# Проверьте существование ресурса перед операцией
def check_resource_exists(resource_id):
response = get_resource(resource_id)
if response.status_code == 404:
print(f"Ресурс {resource_id} не найден")
return False
return True

4.5 Внутренняя ошибка сервера (500)

Симптомы: Код 500

Причины:

  • Временная проблема на сервере Lamoda
  • Некорректные данные, которые не прошли валидацию на сервере

Решение:

# Повторите запрос с задержкой
if response.status_code == 500:
time.sleep(5) # Подождите 5 секунд
response = retry_request()

5. Лучшие практики обработки ошибок

5.1 Всегда проверяйте HTTP код статуса

response = requests.get(url, headers=headers)

if not response.ok:
handle_error(response)
else:
data = response.json()

5.2 Логируйте все ошибки

import logging

logger = logging.getLogger(__name__)

if response.status_code != 200:
logger.error(
f"API Error: {response.status_code} - {response.text}",
extra={
"url": url,
"status_code": response.status_code,
"response": response.text
}
)

5.3 Реализуйте повторные попытки с backoff

from tenacity import retry, stop_after_attempt, wait_exponential

@retry(
stop=stop_after_attempt(3),
wait=wait_exponential(multiplier=1, min=1, max=10)
)
def api_request(url, headers, data):
response = requests.post(url, headers=headers, json=data)
response.raise_for_status()
return response.json()

5.4 Используйте типизированные исключения

class LamodaAPIError(Exception):
"""Базовый класс для ошибок Lamoda API"""
pass

class LamodaAuthError(LamodaAPIError):
"""Ошибка аутентификации (401)"""
pass

class LamodaValidationError(LamodaAPIError):
"""Ошибка валидации (400)"""
pass

class LamodaNotFoundError(LamodaAPIError):
"""Ресурс не найден (404)"""
pass

class LamodaRateLimitError(LamodaAPIError):
"""Превышен rate limit (429)"""
pass

def handle_response(response):
if response.status_code == 401:
raise LamodaAuthError("Unauthorized")
elif response.status_code == 400:
raise LamodaValidationError(response.json())
elif response.status_code == 404:
raise LamodaNotFoundError("Resource not found")
elif response.status_code == 429:
raise LamodaRateLimitError("Rate limit exceeded")
elif response.status_code >= 500:
raise LamodaAPIError(f"Server error: {response.status_code}")

5.5 Парсите детали ошибок валидации

def parse_validation_errors(error_response):
"""Извлекает детали ошибок валидации из ответа"""
errors = []

if "details" in error_response.get("error", {}):
for detail in error_response["error"]["details"]:
errors.append({
"field": detail.get("field"),
"issue": detail.get("issue")
})

return errors

5.6 Обновляйте токен автоматически

class LamodaClient:
def __init__(self, client_id, client_secret):
self.client_id = client_id
self.client_secret = client_secret
self.token = None
self.token_expires_at = None

def get_token(self):
# Если токен истекает в ближайшие 5 минут, обновляем его
if not self.token or (
self.token_expires_at and
datetime.now() + timedelta(minutes=5) >= self.token_expires_at
):
self.refresh_token()

return self.token

def refresh_token(self):
# Запрос нового токена
response = requests.post(
"https://public-api-seller.lamoda.ru/jsonrpc",
json={
"jsonrpc": "2.0",
"id": "1",
"method": "v1.tokens.create",
"params": {
"client_id": self.client_id,
"client_secret": self.client_secret
}
}
)

data = response.json()
self.token = data["result"]["access_token"]
expires_in = data["result"]["expires_in"]
self.token_expires_at = datetime.now() + timedelta(seconds=expires_in)

5.7 Обрабатывайте ошибки пакетных операций

def batch_update_products(products):
"""Обновляет товары пакетом и обрабатывает ошибки"""
response = call_api("v1.nomenclatures.store", products)

if "error" in response:
# Ошибка всего запроса
logger.error(f"Batch error: {response['error']}")
return {"success": 0, "failed": len(products)}

result = response.get("result", {})

# Проверяем наличие ошибок в ответе
if "error_count" in result and result["error_count"] > 0:
errors = result.get("errors", [])

for error in errors:
sku = error.get("lamodaSku")
error_code = error.get("error", {}).get("code")
messages = error.get("messages", [])

logger.error(
f"Product update failed: SKU={sku}, Code={error_code}",
extra={"messages": messages}
)

return {
"success": len(products) - result["error_count"],
"failed": result["error_count"],
"errors": errors
}

return {"success": len(products), "failed": 0}

6. Мониторинг и алерты

6.1 Метрики для отслеживания

from collections import defaultdict

class LamodaAPIMonitor:
def __init__(self):
self.metrics = defaultdict(lambda: {
"count": 0,
"errors": {
"400": 0,
"401": 0,
"403": 0,
"404": 0,
"429": 0,
"500": 0
}
})

def record_request(self, endpoint, status_code):
self.metrics[endpoint]["count"] += 1

if str(status_code) in self.metrics[endpoint]["errors"]:
self.metrics[endpoint]["errors"][str(status_code)] += 1

def get_report(self):
report = []
for endpoint, data in self.metrics.items():
total_errors = sum(data["errors"].values())
error_rate = total_errors / data["count"] if data["count"] > 0 else 0

report.append({
"endpoint": endpoint,
"total_requests": data["count"],
"total_errors": total_errors,
"error_rate": f"{error_rate:.2%}",
"errors_by_code": data["errors"]
})

return report

6.2 Алерты на критические ошибки

def check_and_alert(metrics):
"""Проверяет метрики и отправляет алерты"""
report = metrics.get_report()

for endpoint_data in report:
error_rate = float(endpoint_data["error_rate"].rstrip("%"))

# Алерт если error rate > 10%
if error_rate > 0.1:
send_alert(
f"High error rate on {endpoint_data['endpoint']}: {error_rate:.2%}"
)

# Алерт если много 401 (проблемы с токеном)
if endpoint_data["errors_by_code"]["401"] > 10:
send_alert(
f"Too many 401 errors on {endpoint_data['endpoint']}"
)

# Алерт если есть 429 (rate limit)
if endpoint_data["errors_by_code"]["429"] > 0:
send_alert(
f"Rate limit hit on {endpoint_data['endpoint']}"
)

7. Примеры обработки ошибок на практике

7.1 Полный пример клиента с обработкой ошибок

import requests
import logging
from datetime import datetime, timedelta
from typing import Optional, Dict, Any

logger = logging.getLogger(__name__)

class LamodaAPIClient:
def __init__(self, client_id: str, client_secret: str):
self.client_id = client_id
self.client_secret = client_secret
self.token: Optional[str] = None
self.token_expires_at: Optional[datetime] = None
self.base_url = "https://api-b2b.lamoda.ru/api/v1"
self.jsonrpc_url = "https://public-api-seller.lamoda.ru/jsonrpc"

def get_headers(self) -> Dict[str, str]:
"""Возвращает заголовки с токеном авторизации"""
token = self.get_valid_token()
return {
"Authorization": f"Bearer {token}",
"Content-Type": "application/json"
}

def get_valid_token(self) -> str:
"""Получает или обновляет токен"""
if not self.token or not self.token_expires_at:
self.refresh_token()
elif datetime.now() + timedelta(minutes=5) >= self.token_expires_at:
self.refresh_token()

return self.token

def refresh_token(self):
"""Обновляет токен авторизации"""
try:
response = requests.post(
self.jsonrpc_url,
json={
"jsonrpc": "2.0",
"id": "1",
"method": "v1.tokens.create",
"params": {
"client_id": self.client_id,
"client_secret": self.client_secret
}
}
)

if response.status_code != 200:
raise LamodaAuthError(f"Failed to get token: {response.status_code}")

data = response.json()

if "error" in data:
raise LamodaAuthError(data["error"]["message"])

self.token = data["result"]["access_token"]
expires_in = data["result"]["expires_in"]
self.token_expires_at = datetime.now() + timedelta(seconds=expires_in)

logger.info("Token refreshed successfully")

except Exception as e:
logger.error(f"Failed to refresh token: {e}")
raise

def request(
self,
method: str,
url: str,
json_data: Optional[Dict[str, Any]] = None,
retry_on_auth_error: bool = True
) -> Dict[str, Any]:
"""Выполняет запрос с обработкой ошибок"""
headers = self.get_headers()

try:
response = requests.request(
method,
url,
headers=headers,
json=json_data
)

# Обработка ошибок авторизации
if response.status_code == 401 and retry_on_auth_error:
logger.warning("Got 401, refreshing token and retrying...")
self.refresh_token()
return self.request(method, url, json_data, retry_on_auth_error=False)

# Обработка других ошибок
if not response.ok:
self.handle_error_response(response)

return response.json()

except requests.exceptions.RequestException as e:
logger.error(f"Request failed: {e}")
raise LamodaAPIError(f"Request failed: {e}")

def handle_error_response(self, response: requests.Response):
"""Обрабатывает ошибочный ответ"""
try:
error_data = response.json()
except ValueError:
error_data = {"message": response.text}

# Логируем ошибку
logger.error(
f"API Error: {response.status_code}",
extra={
"status_code": response.status_code,
"response": error_data,
"url": response.url
}
)

# Генерируем соответствующее исключение
if response.status_code == 400:
raise LamodaValidationError(error_data)
elif response.status_code == 403:
raise LamodaAPIError("Access forbidden")
elif response.status_code == 404:
raise LamodaNotFoundError("Resource not found")
elif response.status_code == 429:
raise LamodaRateLimitError("Rate limit exceeded")
elif response.status_code >= 500:
raise LamodaAPIError(f"Server error: {response.status_code}")
else:
raise LamodaAPIError(f"Unexpected error: {response.status_code}")

def get_orders(self, page: int = 1, limit: int = 50):
"""Получает список заказов"""
url = f"{self.base_url}/orders"
params = {"page": page, "limit": limit}

try:
response = requests.get(
url,
headers=self.get_headers(),
params=params
)

if not response.ok:
self.handle_error_response(response)

return response.json()

except LamodaAPIError as e:
logger.error(f"Failed to get orders: {e}")
raise

7.2 Пример обработки ошибок пакетного обновления

def batch_update_prices(price_updates):
"""
Обновляет цены пакетом с подробной обработкой ошибок

Args:
price_updates: Список обновлений цен
[{"sku": "SKU1", "price": 1000}, ...]

Returns:
Dict с результатами обновления
"""
client = LamodaAPIClient(client_id, client_secret)

results = {
"total": len(price_updates),
"success": 0,
"failed": 0,
"errors": []
}

try:
response = client.request(
"POST",
f"{client.jsonrpc_url}",
json_data={
"jsonrpc": "2.0",
"id": "1",
"method": "v1.nomenclatures.set-prices",
"params": {
"prices": price_updates
}
}
)

# Проверяем наличие ошибок в ответе
if "error" in response:
logger.error(f"Batch update failed: {response['error']}")
results["failed"] = len(price_updates)
results["errors"].append(response["error"])
return results

result_data = response.get("result", {})

# Если есть ошибки при обновлении отдельных товаров
if "error_count" in result_data and result_data["error_count"] > 0:
errors = result_data.get("errors", [])

for error_info in errors:
sku = error_info.get("lamodaSku")
error = error_info.get("error", {})
messages = error.get("messages", [])

error_record = {
"sku": sku,
"code": error.get("code"),
"messages": messages
}
results["errors"].append(error_record)

logger.error(
f"Failed to update price for SKU={sku}: {messages}"
)

results["success"] = len(price_updates) - result_data["error_count"]
results["failed"] = result_data["error_count"]
else:
# Все успешно обновлено
results["success"] = len(price_updates)

return results

except LamodaValidationError as e:
logger.error(f"Validation error: {e}")
results["failed"] = len(price_updates)
results["errors"].append({"validation": str(e)})
return results

except LamodaAuthError as e:
logger.error(f"Authentication error: {e}")
results["failed"] = len(price_updates)
results["errors"].append({"auth": str(e)})
return results

except LamodaAPIError as e:
logger.error(f"API error: {e}")
results["failed"] = len(price_updates)
results["errors"].append({"api": str(e)})
return results

7.3 Пример повторных попыток с backoff

import time
import random

def request_with_retry(
client,
method: str,
url: str,
max_retries: int = 5,
base_delay: float = 1.0
):
"""
Выполняет запрос с повторными попытками и экспоненциальной задержкой

Args:
client: Клиент API
method: HTTP метод
url: URL запроса
max_retries: Максимальное количество попыток
base_delay: Базовая задержка в секундах
"""
for attempt in range(max_retries):
try:
response = client.request(method, url)

# Если успешно, возвращаем результат
return response

except LamodaRateLimitError as e:
# Rate limit - используем экспоненциальную задержку
if attempt < max_retries - 1:
delay = base_delay * (2 ** attempt) + random.uniform(0, 1)
logger.warning(
f"Rate limited. Attempt {attempt + 1}/{max_retries}. "
f"Waiting {delay:.2f}s..."
)
time.sleep(delay)
else:
logger.error("Max retries reached for rate limit")
raise

except LamodaAPIError as e:
# Другие ошибки API - пробуем еще пару раз
if attempt < 2:
delay = base_delay * (attempt + 1)
logger.warning(
f"API error: {e}. Attempt {attempt + 1}/{max_retries}. "
f"Retrying in {delay}s..."
)
time.sleep(delay)
else:
raise

# Если все попытки исчерпаны
raise LamodaAPIError("Max retries reached")

8. Справочник по устранению проблем

Проблема: Постоянно получаю 401 Unauthorized

Возможные причины:

  1. Токен истекает раньше чем вы обновляете его
  2. Неверный client_id или client_secret
  3. Токен не передается в заголовке Authorization

Решения:

# 1. Проверьте credentials перед использованием
def verify_credentials(client_id, client_secret):
response = requests.post(
"https://public-api-seller.lamoda.ru/jsonrpc",
json={
"jsonrpc": "2.0",
"id": "1",
"method": "v1.tokens.create",
"params": {
"client_id": client_id,
"client_secret": client_secret
}
}
)

if "error" in response.json():
print("Неверные credentials!")
return False

print("Credentials верны")
return True

# 2. Обновляйте токен за 2-3 минуты до истечения
# (см. пример в разделе 5.6)

# 3. Проверьте формат заголовка Authorization
headers = {
"Authorization": f"Bearer {token}" # Правильно
# Не: f"BearerToken {token}" или f"{token}"
}

Проблема: Много ошибок 400 при создании товаров

Возможные причины:

  1. Отсутствуют обязательные поля
  2. Неверный формат данных
  3. Значения вне допустимого диапазона

Решения:

# 1. Проверьте наличие всех обязательных полей
required_fields = ["sku", "brand", "category", "price", ...]
for field in required_fields:
if field not in product_data:
print(f"Отсутствует обязательное поле: {field}")

# 2. Проверьте типы данных
if not isinstance(price, (int, float)):
print("Цена должна быть числом")

# 3. Проверьте диапазоны значений
if price <= 0:
print("Цена должна быть положительной")

# 4. Используйте пример из документации как шаблон

Проблема: Ошибки 404 при получении заказов

Возможные причины:

  1. Неверный ID заказа
  2. Заказ принадлежит другому продавцу
  3. Заказ был удален

Решения:

# 1. Проверьте формат ID заказа
order_id = "LM140101-123456" # Правильный формат

# 2. Сначала получите список заказов, потом детали
orders = client.get_orders()
if order_id not in [o["id"] for o in orders["data"]]:
print(f"Заказ {order_id} не найден в списке ваших заказов")

# 3. Проверьте что используете правильный seller_id

Проблема: Ошибки 429 Rate Limit

Возможные причины:

  1. Слишком много запросов за короткое время
  2. Параллельные запросы без задержки

Решения:

# 1. Используйте экспоненциальный backoff (см. пример выше)

# 2. Ограничьте количество параллельных запросов
from concurrent.futures import ThreadPoolExecutor

MAX_WORKERS = 3 # Не более 3 параллельных запросов

with ThreadPoolExecutor(max_workers=MAX_WORKERS) as executor:
futures = [executor.submit(make_request, url) for url in urls]
results = [f.result() for f in futures]

# 3. Используйте несколько токенов для параллельных запросов
tokens = [get_token() for _ in range(5)] # 5 токенов

def request_with_token(url, token):
return requests.get(url, headers={"Authorization": f"Bearer {token}"})

# Распределяйте запросы по токенам

Проблема: Медленная работа API

Возможные причины:

  1. Слишком много запросов в цикле
  2. Не используется пагинация
  3. Запрашиваются лишние данные

Решения:

# 1. Используйте пагинацию правильно
def get_all_orders():
all_orders = []
page = 1

while True:
response = client.get_orders(page=page, limit=100)
orders = response["data"]

if not orders:
break

all_orders.extend(orders)
page += 1

return all_orders

# 2. Кэшируйте редко меняющиеся данные
from functools import lru_cache

@lru_cache(maxsize=100)
def get_product_info(sku):
# Кэширует результаты, чтобы не повторять запросы
return client.get_product(sku)

# 3. Используйте фильтры для получения только нужных данных
orders = client.get_orders(
status="New", # Только новые заказы
date_from="2025-01-01" # Только с определенной даты
)

9. Краткая сводка

HTTP коды статуса (B2B Platform API, Seller REST API)

КодЗначениеДействие
400Ошибка валидацииПроверьте параметры запроса
401Не авторизованОбновите токен
403Доступ запрещенПроверьте права доступа
404Не найденоПроверьте ID ресурса
429Rate limitИспользуйте backoff
500Ошибка сервераПовторите запрос позже

JSON-RPC коды ошибок (Seller JSON-RPC API)

КодЗначениеДействие
-32700Parse errorПроверьте JSON формат
-32600Invalid RequestПроверьте структуру запроса
-32601Method not foundПроверьте название метода
-32602Invalid paramsПроверьте параметры
-32603Internal errorПовторите запрос
0-32000Business logicЧитайте message

Время жизни токенов

APIВремя токенаКогда обновлять
B2B Platform API24 часаЗа 1 час до истечения
Seller JSON-RPC API15 минутЗа 2-3 минуты до истечения
Seller REST API~15 минутЗа 2-3 минуты до истечения

Контакты для поддержки

При возникновении проблем с API:

Полезные ресурсы


Заключение

Понимание кодов ошибок и правильная обработка ошибок критически важны для надежной интеграции с API Lamoda.

Ключевые рекомендации:

  1. ✅ Всегда проверяйте HTTP код статуса
  2. ✅ Логируйте все ошибки с деталями
  3. ✅ Реализуйте автоматическое обновление токенов
  4. ✅ Используйте экспоненциальный backoff для 429
  5. ✅ Парсите детали ошибок валидации
  6. ✅ Обрабатывайте ошибки пакетных операций
  7. ✅ Мониторьте error rate и настраивайте алерты
  8. ✅ Используйте retry для временных ошибок
  9. ✅ Кэшируйте редко меняющиеся данные
  10. ✅ Обращайтесь в поддержку при повторяющихся проблемах

Следуя этим рекомендациям, вы создадите надежную и устойчивую интеграцию с API Lamoda.