Logo
Overview

AI для проектирования REST API: генерация контрактов OpenAPI, валидация и ревью через LLM

July 22, 2026
7 min read

Проектирование REST API — это не только выбор между PUT и PATCH. Это десятки ручек, сотни параметров и бесконечное «ой, мы забыли описать ошибку 409». LLM не напишет за вас идеальную спецификацию с первой попытки (спойлер: человек тоже). Но она способна превратить User Story в черновик OpenAPI за минуты, проверить его на соответствие REST-принципам и ткнуть носом в ручки с названиями уровня POST /api/v1/getUserDataByIdActive. Что, согласитесь, уже неплохо.

Если вы только знакомитесь со Swagger и OpenAPI — там разобран фундамент. А здесь — конкретно про AI-ускорение: промпты, pipeline, валидация.

Зачем вообще гонять требования через LLM перед написанием спеки

Стандартный процесс выглядит так: аналитик пишет ТЗ → отдаёт разработчику → разработчик пишет код и попутно придумывает контракт → через месяц тестировщик обнаруживает, что поле userId в одном ответе называется user_id, а в другом — clientId, и никто не помнит почему. Документация API появляется постфактум, если вообще появляется.

LLM меняет порядок: требования → черновик OpenAPI → обсуждение → код. Не «заменили аналитика», а сдвинули контракт на шаг раньше. До того, как разработчик уйдёт в трёхнедельный спринт с непроверенной моделью данных.

Вот как выглядит полный цикл:

100%
graph TD
  A["Требования к API (User Story, ТЗ)"] --> B["LLM-промпт с контекстом"]
  B --> C["Генерация OpenAPI-спецификации"]
  C --> D["Валидация: проверка REST-принципов"]
  D --> E["Проверка названий ручек и методов"]
  E --> F["Финальная OpenAPI-спецификация"]
  C --> G["Обратная связь: доработка промпта"]
  G --> B
  D --> H["Отчёт об ошибках REST-дизайна"]
  E --> I["Рекомендации по неймингу"]
  style A fill:#4a90d9,stroke:#2c5f8a,color:#fff
  style B fill:#f0a500,stroke:#c88400,color:#fff
  style C fill:#7b68ee,stroke:#5a4db2,color:#fff
  style D fill:#50c878,stroke:#3a9a5c,color:#fff
  style E fill:#50c878,stroke:#3a9a5c,color:#fff
  style F fill:#4a90d9,stroke:#2c5f8a,color:#fff
  style G fill:#e0e0e0,stroke:#999,color:#333
  style H fill:#e0e0e0,stroke:#999,color:#333
  style I fill:#e0e0e0,stroke:#999,color:#333

Схема процесса: требования попадают в LLM-промпт, модель генерирует черновик OpenAPI, затем две параллельные ветки валидации — проверка REST-принципов и проверка нейминга ручек. При обнаружении проблем промпт дорабатывается (обратная связь), и цикл повторяется. На выходе — спецификация, которую не стыдно показать на ревью.

Шаг 1: промпт для генерации OpenAPI из требований

Самый частый сценарий: у вас есть User Story в Jira или пара абзацев из ТЗ, и нужно превратить это в спецификацию. Промпт не обязан быть гигантским. Обязательным он должен быть структурированным.

Ты — senior backend-разработчик. Сгенерируй OpenAPI 3.0-спецификацию
на основе требований ниже.
Требования:
{вставьте текст User Story или фрагмент ТЗ}
Правила:
1. Используй семантически правильные HTTP-методы:
GET для чтения, POST для создания, PUT/PATCH для обновления,
DELETE для удаления.
2. Названия ручек — существительные во множественном числе,
kebab-case в path-параметрах.
3. Для каждой ручки опиши success-ответ (2xx), типовые ошибки
(400, 404, 409) и схему тела запроса/ответа.
4. Поля в camelCase.
5. Не выдумывай ручки, которых нет в требованиях.
6. Если требование допускает неоднозначную трактовку —
отметь это комментарием # AMBIGUITY в yaml.

На реальных требованиях модель выдаёт спецификацию, где уже прописаны схемы, status codes и даже example-значения. Не идеально, но процентов 70–80 работы сделано. Оставшиеся 20% — как раз то, что отличает Senior-аналитика от «я попросил ChatGPT и скопировал».

Шаг 2: валидация — ищем ошибки до того, как они попадут в код

LLM-сгенерированная спека — это сырой драфт. Следующий промпт — валидатор:

Ты — ревьюер API-контрактов. Проверь OpenAPI-спецификацию ниже
на соответствие REST-принципам и лучшим практикам.
Чек-лист проверки:
1. Методы соответствуют семантике операции.
2. Нет GET-запросов, изменяющих состояние сервера.
3. POST не используется для чтения.
4. PUT — полное обновление, PATCH — частичное.
Если перепутаны — это ошибка.
5. Коды ответов адекватны методу:
POST → 201 Created + Location-заголовок,
PUT/PATCH → 200 или 204 No Content,
DELETE → 204 No Content,
GET → 200 или 404.
6. Нет ручек вроде GET /getUsers или POST /createOrder
(глаголы в URL).
7. Все поля схем описаны, типы указаны.
8. Есть описание для каждого эндпоинта и параметра.
Формат ответа:
- Сначала список ошибок (каждая — номер правила + цитата из спеки).
- Затем исправленная версия спеки.

Стоит отметить: модель не проверяет бизнес-логику. Она проверяет форму. Но 80% проблем с API-контрактами — это именно проблемы формы, а не логики. Так что этот шаг закрывает львиную долю багов, которые обычно всплывают на интеграционном тестировании через три спринта.

Шаг 3: нейминг ручек — та самая боль, которую LLM видит лучше человека

Отдельный зверь — названия эндпоинтов. Человек привыкает к своему неймингу и через неделю работы искренне считает POST /api/v1/processUserDataTransaction нормальной ручкой. LLM — нет.

Специфическая проверка:

Проверь названия ручек в спецификации ниже на соответствие
правилам REST-нейминга. Основные правила:
- Существительные, а не глаголы: /users, а не /getUsers.
- Множественное число для коллекций: /orders, а не /order.
- Иерархия через вложенность: /users/{id}/orders.
- Фильтрация, сортировка, пагинация — через query-параметры,
не через path: /users?role=admin, а не /users/admins.
- Конечный слеш не ставим.
- Никаких /api/getSomethingByFilter.
Выведи список нарушений в формате:
Проблемная ручка | Нарушение | Исправленный вариант

Если тема нейминга для вас новая — держите подробный разбор правил названий ручек. А здесь сфокусируемся на AI-части.

Практический пример: генерация спеки для сущности «Заказ»

Возьмём типовую User Story из e-commerce:

Как пользователь интернет-магазина, я хочу создать заказ, просматривать историю своих заказов, отменять заказ до подтверждения, видеть детали конкретного заказа и отслеживать его статус.

Запускаем промпт из шага 1. На выходе получаем такую структуру (сокращённый вариант того, что генерирует LLM):

openapi: 3.0.3
info:
title: Order Management API
version: 1.0.0
paths:
/orders:
post:
summary: Создать заказ
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/CreateOrderRequest'
responses:
'201':
description: Заказ создан
headers:
Location:
schema:
type: string
content:
application/json:
schema:
$ref: '#/components/schemas/Order'
'400':
description: Некорректные данные заказа
get:
summary: Список заказов пользователя
parameters:
- name: status
in: query
schema:
type: string
- name: page
in: query
schema:
type: integer
default: 1
responses:
'200':
description: Список заказов
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/Order'
/orders/{orderId}:
get:
summary: Детали заказа
responses:
'200':
description: Детали заказа
'404':
description: Заказ не найден
delete:
summary: Отменить заказ
responses:
'204':
description: Заказ отменён
'409':
description: Заказ уже нельзя отменить

Примечательно, что модель сама догадалась добавить Location-заголовок к 201, пагинацию через query-параметры и 409 Conflict для бизнес-ограничения «нельзя отменить подтверждённый заказ». Ни в одном промпте я этого явно не просил. LLM достраивает REST-контракт из контекста задачи — и делает это на удивление адекватно.

Дальше прогоняем валидацию. Ошибки типовые: в delete-ручке для отмены нет схемы ошибки 409 (модель указала код, но без content), и в GET /orders не хватает описания для query-параметра status. Пять минут правок — и спека готова к ревью.

Ограничения: что LLM пока не умеет

На первый взгляд — магия. Но есть четыре принципиальных ограничения, о которых надо знать заранее:

  1. LLM не понимает бизнес-контекст. Она не знает, что «отмена заказа» в вашей компании — это не DELETE, а POST /orders/{id}/cancel с компенсационным документом в теле ответа. Бизнес-логику диктуете вы.
  2. Спеки для сложных микросервисных ландшафтов модель генерирует изолированно. Для каждого сервиса — отдельно. Стыковку контрактов между сервисами придётся проверять вручную или писать отдельный оркестрирующий промпт.
  3. Аутентификация и авторизация. Модель может описать securitySchemes (Bearer, OAuth2), но расставить permission на уровне ручек (кто имеет доступ к /admin/orders vs /my/orders) — это по-прежнему задача архитектора.
  4. Версионирование API. LLM не предложит вам стратегию /v1 vs /v2, не предупредит о breaking changes и не спроектирует обратную совместимость. Это зона архитектурных решений, а не генерации.

Оговорка: это не серебряная пуля. LLM — инструмент ускорения, а не замена инженерного мышления. Если вы ждали кнопку «сделать хорошо» — её нет. Но кнопка «сделать 80% работы за 5 минут» — вот она, и грех её не нажимать.

Когда имеет смысл использовать этот подход

СитуацияПодходЭкономия
Новый микросервис с 5–15 ручкамиГенерация спеки из User Story1–2 часа вместо 4–6
Рефакторинг старого API без документацииГенерация из кода + валидация3–4 часа вместо 1–2 дней
Ревью контракта перед ревью кодаВалидация и нейминг-проверкаЭкономия на переписывании после ревью
Микросервисный ландшафт из 5+ сервисовГенерация посегментно + ручная стыковка~30% времени проектирования
Быстрый прототип / PoCГенерация без глубокой валидации5 минут вместо часа

Важно: если у вас простая CRUD-ручка на три эндпоинта — не надо гонять LLM. Напишите руками. Инструмент должен решать проблему, а не создавать новую — ощущение, что «процесс стал AI-powered, значит круто» без реальной экономии времени.

Заключение

LLM не проектирует API за вас. Она делает черновую работу: переводит текст требований в структурированный контракт, проверяет его на грубые ошибки и не ленится перечитать названия всех ручек, даже если их сорок шесть. Человек же делает то, что человеку удаётся лучше всего: принимает решения.

И да, если вы никогда не писали промпт для генерации OpenAPI — попробуйте. Прямо сейчас. Возьмите любую User Story из бэклога и скормите модели. Результат, скорее всего, будет не идеальным. Но вы удивитесь, сколько рутины модель берёт на себя с первой же попытки.

P.S. Если модель сгенерировала POST /api/v1/getOrderHistory — вы забыли добавить правила нейминга в промпт. Не вините инструмент, вините промпт.