Опирается на правила:
R-OAS-1..4+ сводка X-кодов из REST API Style Guide → раздел OpenAPI-метаданные и антипаттерны.
Важно знать
operationId— уникальный, camelCase, форматдействие+ресурс(createOrder,confirmOrder).tags— один на ресурс, множественное число с заглавной (Orders,Users).- Action-эндпоинты относятся к тегу родительского ресурса (
confirm→Orders).- Параметры пути в OpenAPI именуются уникально (
{orderId},{itemId}).- В дизайне URL —
{id}(контекст устраняет неоднозначность).summary— короткая фраза до 80 символов.description— если логика неочевидна.- Сводка антипаттернов из всех разделов гайда — единая checkin-таблица.
OpenAPI — машиночитаемый контракт REST API. Хорошо оформленный OpenAPI генерирует client SDK, Swagger UI, Postman collections. UCP формулирует минимальные метаданные, без которых эти инструменты работают плохо.
operationId
R-OAS-1: уникальный, camelCase, действие + ресурс.
/api/v1/orders:
get:
operationId: getOrders
post:
operationId: createOrder
/api/v1/orders/{id}:
get:
operationId: getOrder
put:
operationId: updateOrder
patch:
operationId: patchOrder
delete:
operationId: deleteOrder
/api/v1/orders/{id}/confirm:
post:
operationId: confirmOrder
/api/v1/orders/search:
post:
operationId: searchOrders
Почему это критично:
- Client SDK generators (openapi-generator) используют
operationIdкак имя метода:orderService.confirmOrder(orderId). - Без
operationId— генератор делает что-то странное (postOrdersOrderIdConfirm). - Уникальный — в client SDK не два метода с одним именем.
- camelCase — стандарт для имён методов в большинстве языков (Java, JS, Python).
Конвенция:
get{Resource}— single (getOrder).get{Resources}— list (getOrders).create{Resource}— POST для создания.update{Resource}— PUT для замены.patch{Resource}— PATCH.delete{Resource}— DELETE.{verb}{Resource}— action (confirmOrder,cancelOrder).search{Resources}—POST /search(см. Query).
tags
R-OAS-2: один тег на ресурс.
tags:
- name: Orders
description: 'Управление заказами'
- name: Users
description: 'Управление пользователями'
- name: Payments
description: 'Платежи и refund'
/api/v1/orders:
get:
tags: [Orders]
post:
tags: [Orders]
/api/v1/orders/{id}/confirm:
post:
tags: [Orders] # action к Orders
Тег:
- Имя — множественное число с заглавной (
Orders,Users). description— короткое объяснение группы.- Action-эндпоинты относятся к тегу родительского ресурса.
POST /orders/{id}/confirm→Orders, не отдельныйOrderActions.
В Swagger UI / Redoc — endpoints группируются по тегам. Без правильных тегов — flat-список 100+ эндпоинтов, невозможно ориентироваться.
Параметры пути в OpenAPI
R-OAS-3: уникальные имена.
/api/v1/orders/{orderId}/items/{itemId}:
get:
parameters:
- name: orderId
in: path
required: true
schema:
type: string
format: uuid
- name: itemId
in: path
required: true
schema:
type: string
format: uuid
Двойной стандарт с дизайном URL (URL и ресурсы R-NEST-4):
- В дизайне URL —
{id}(контекст ресурса устраняет неоднозначность). - В OpenAPI — уникальные (
{orderId},{itemId}).
Причина: Swagger UI и Redoc не работают с одинаковыми именами параметров в одном пути. Это требование инструмента, не семантика.
summary и description
R-OAS-4:
/api/v1/orders/{id}/confirm:
post:
operationId: confirmOrder
tags: [Orders]
summary: 'Подтвердить заказ'
description: |
Переводит заказ из статуса CREATED в CONFIRMED.
Заказ должен содержать хотя бы одну позицию.
После подтверждения изменение состава заказа невозможно.
summary— короткая фраза (до 80 символов). Отображается в Swagger UI рядом с endpoint.description— Markdown, многострочный. Только если логика неочевидна; пустой description — лучше отсутствия.
Сводка антипаттернов
Единая таблица из всех разделов гайда. Используется как checklist на ревью.
URL
| Антипаттерн | Правило | Корректно |
|---|---|---|
| Глагол в URL для CRUD | R-URL-X4 | POST /api/v1/orders |
| CamelCase в пути | R-URL-X1 | /order-items |
| snake_case в пути | R-URL-X1 | /order-items |
| Завершающий слеш | R-URL-X2 | /api/v1/orders |
| Расширение файла в пути | R-URL-X3 | /api/v1/orders |
| ID в теле вместо пути | R-NEST-X2 | PUT /orders/{id} |
| Глубокая вложенность | R-NEST-X1 | /comments?itemId={id} |
| Mix единственного/множественного | R-RES-X2 | /orders/{id}/items |
| GET с побочным эффектом | R-MTH-X1 | POST /orders/{id}/cancel |
Версионирование
| Антипаттерн | Правило | Корректно |
|---|---|---|
| Версия в query | R-VER-X2 | /api/v1/orders |
| Минорная версия | R-VER-X1 | /api/v1/... |
Дата-версия /api/2026/ | R-VER-X1 | v1, v2 |
Endpoint без /api | R-VER-X3 | /api/v1/... |
| Новая версия для optional поля | R-VER-X4 | в текущей |
Query
| Антипаттерн | Правило | Корректно |
|---|---|---|
Бизнес-логика в query (?action=cancel) | R-QRY-X4 | POST /orders/{id}/cancel |
| Comma-separated массивы | R-QRY-X3 | повтор параметра |
page=0 в публичном контракте | R-QRY-X2 | page=1 |
| snake_case в параметрах | R-QRY-X1 | camelCase |
| Парсинг cursor на клиенте | R-QRY-X5 | opaque token |
JSON и ответы
| Антипаттерн | Правило | Корректно |
|---|---|---|
Envelope { success, data } | R-RSP-X4 | плоский ресурс |
null в успешном ответе | R-RSP-X1 | отсутствие поля |
"" для отсутствия | R-RSP-X2 | отсутствие поля |
nullable: true в OpenAPI | R-RSP-X3 | required или отсутствие |
Заголовки
| Антипаттерн | Правило | Корректно |
|---|---|---|
Префикс X- в кастомных headers | R-HDR-X1 | доменный префикс (Shop-) |
Ошибки
| Антипаттерн | Правило | Корректно |
|---|---|---|
application/json для ошибок | R-ERR-X1 | application/problem+json |
type: "about:blank" | R-ERR-X2 | URN urn:problem:<service>:<code> |
| HTTP-код вне списка (418, 422, 451) | R-ERR-X3 | стандартные |
| Stack traces в 500 | R-ERR-X4 | code + общий detail |
Rate limiting и deprecation
| Антипаттерн | Правило | Корректно |
|---|---|---|
| 429 без headers | R-RATE-X1 | Retry-After + RateLimit-* |
Deprecation без Sunset | R-DEP-X1 | заголовок с датой |
Alias и actions
| Антипаттерн | Правило | Корректно |
|---|---|---|
me для собственных ресурсов | R-ALIAS-X1 | контекст из токена |
me без users/ префикса | R-ALIAS-X2 | /users/me |
| HATEOAS-ссылки в теле | R-PRIN-X1 | OpenAPI описывает навигацию |
Существительное в action (/confirmation) | R-ACT-X1 | /confirm |
| Любой метод кроме POST для action | R-ACT-X2 | POST /orders/{id}/confirm |
Локализация
| Антипаттерн | Правило | Корректно |
|---|---|---|
Локализация code enum | R-LOC-X1 | английский |
Локализация title | R-LOC-X1 | стандартное HTTP-название |
| Локализация JSON-полей | R-LOC-X1 | английский |
Куда дальше
- REST API → OpenAPI и антипаттерны (нормативно) — формулировки.
- URL и ресурсы —
R-NEST-4{id}vs{orderId}. - Alias и Action-эндпоинты — action operationId.
- Версионирование — v1/v2 в OpenAPI.
- Ошибки RFC 9457 — ProblemDetails схема.
- Resilience → OpenAPI generator binding — client SDK generation.
- Use Case Pattern — UseCase соответствует operationId.