REST API Style Guide: Batch, async, локализация
REST API: batch-эндпоинты, асинхронные операции с polling/webhook, локализация ответов, обработка timezone и валют — практические примеры.
REST API batch async: 17. Batch-операции
17.1. Эндпоинт
REST API batch async — массовые операции оформляются как POST /resources/batch:
POST /api/v1/orders/batch
POST /api/v1/notifications/batch/send
17.2. Формат запроса
Тело содержит массив элементов:
{
"items": [
{ "productId": "aaa", "quantity": 2 },
{ "productId": "bbb", "quantity": 1 },
{ "productId": "ccc", "quantity": 5 }
]
}
17.3. Ответ с частичными ошибками
Код 200 OK (даже если часть элементов не прошла). Тело содержит результат по каждому элементу:
{
"results": [
{ "index": 0, "status": "SUCCESS", "orderId": "..." },
{ "index": 1, "status": "ERROR", "error": { "code": "INSUFFICIENT_STOCK", "detail": "Товар bbb отсутствует на складе" } },
{ "index": 2, "status": "SUCCESS", "orderId": "..." }
],
"summary": {
"total": 3,
"succeeded": 2,
"failed": 1
}
}
index-- позиция элемента в исходном массиве (0-based)status--SUCCESSилиERROR- При
ERROR-- объектerrorсcodeиdetail(упрощённый формат, не полный ProblemDetails, т.к. ошибка относится к элементу batch, а не к HTTP-запросу) summary-- агрегация:total(всего элементов),succeeded(успешных),failed(с ошибкой)
17.4. Ограничения
- Максимальный размер batch указывается в документации (например, 100 элементов)
- При превышении --
400 Bad Requestсcode: BATCH_SIZE_EXCEEDED
18. Длительные операции (async)
18.1. Паттерн polling
Для операций, которые не могут завершиться за время HTTP-запроса:
- Клиент отправляет запрос
- Сервер возвращает
202 Acceptedс ссылкой на задачу - Клиент периодически опрашивает задачу до завершения
POST /api/v1/reports/generate
Content-Type: application/json
{ "dateFrom": "2025-01-01", "dateTo": "2025-12-31" }
Ответ:
HTTP/1.1 202 Accepted
Location: /api/v1/tasks/550e8400-e29b-41d4-a716-446655440000
{
"taskId": "550e8400-e29b-41d4-a716-446655440000",
"status": "PENDING",
"createdAt": "2025-03-15T10:30:00Z",
"statusUrl": "/api/v1/tasks/550e8400-e29b-41d4-a716-446655440000"
}
18.2. Опрос статуса задачи
GET /api/v1/tasks/{id}
Пока задача выполняется:
{
"taskId": "550e8400-e29b-41d4-a716-446655440000",
"status": "PROCESSING",
"progress": 45,
"createdAt": "2025-03-15T10:30:00Z"
}
После завершения:
{
"taskId": "550e8400-e29b-41d4-a716-446655440000",
"status": "COMPLETED",
"progress": 100,
"createdAt": "2025-03-15T10:30:00Z",
"completedAt": "2025-03-15T10:35:00Z",
"resultUrl": "/api/v1/reports/550e8400-e29b-41d4-a716-446655440000"
}
При ошибке:
{
"taskId": "550e8400-e29b-41d4-a716-446655440000",
"status": "FAILED",
"createdAt": "2025-03-15T10:30:00Z",
"completedAt": "2025-03-15T10:32:00Z",
"error": {
"code": "REPORT_GENERATION_FAILED",
"detail": "Не удалось сформировать отчет: данные за период отсутствуют"
}
}
18.3. Статусы задачи
PENDING-- задача создана, ожидает обработкиPROCESSING-- выполняетсяCOMPLETED-- завершена, результат доступен поresultUrlFAILED-- завершена с ошибкой, подробности вerror
19. Локализация
19.1. Заголовок Accept-Language
Клиент указывает предпочитаемый язык для человекочитаемых сообщений (detail в ошибках, message в violations):
GET /api/v1/orders/{id}
Accept-Language: ru
19.2. Язык по умолчанию
Если Accept-Language не указан -- сервер использует язык по умолчанию, определённый для проекта (например, ru).
19.3. Что локализуется
detailв ProblemDetailsmessageвviolations
19.4. Что НЕ локализуется
code-- enum, всегда на английском (ORDER_EMPTY, неЗАКАЗ_ПУСТОЙ)title-- стандартное название HTTP-статуса на английском (Bad Request,Not Found)type-- URI, всегда на английском- Имена полей в JSON (
orderId, неидЗаказа)