
OpenAPI — это открытая спецификация для описания REST API. Изначально она называлась Swagger, но в 2016 году была переименована в OpenAPI Specification и передана под управление OpenAPI Initiative. На данный момент Swagger — это набор инструментов для работы со спецификацией OpenAPI (Swagger UI, Editor, Codegen).
В OpenAPI определяются пути, параметры, тела запросов и ответов, коды статусов, схемы данных, типы аутентификации. В статье мы рассмотрим спецификацию OpenAPI версии 3.0: разберем из каких обязательных блоков она состоит и как правильно описывать типы данных и параметры запросов.
Создаем первый эндпоинт
Для начала создадим пример, на котором изучим базовые концепции. Ниже представлен yaml-файл с одной точкой API:
openapi: 3.0.3
info:
title: API
version: 0.1.0
servers:
- url: http://localhost:4010
paths:
/test:
get:
summary: Test
tags: [test]
responses:
'200':
description: OK
content:
application/json:
schema:
type: array
items:
type: object
required: [id, title]
properties:
id:
type: string
description: Unique todo identifier
title:
type: string
description: Human readable title
Файл спецификации содержит описание единственного эндпоинта /test, который возвращает массив объектов. Для демонстрации его функциональности мы используем два инструмента: Prism (для развертывания мок-сервера) и Swagger UI (для визуализации документации и интерактивного тестирования).
docker-compose
services:
prism:
image: stoplight/prism:latest
command: >-
mock -h 0.0.0.0 -p 4010 --cors --errors --dynamic /spec/${SPEC_PATH:-openapi/openapi.yaml}
ports:
- "${PRISM_PORT:-4010}:4010"
volumes:
- ./docs:/spec:ro
restart: unless-stopped
swagger:
image: swaggerapi/swagger-ui
environment:
SWAGGER_JSON: /spec/${SPEC_PATH:-openapi/openapi.yaml}
ports:
- "${SWAGGER_PORT:-8080}:8080"
volumes:
- ./docs:/spec:ro
depends_on:
- prism
restart: unless-stopped
Далее запускаем контейнеры при помощи команды SPEC_PATH=basic.yaml docker compose up -d, затем переходим по ссылке http://localhost:8080/. Если всё правильно работает, то в интерфейсе появится роут test.

Затем раскрываем его и нажимаем кнопки "Try it out" и "execute". После чего увидим примерно такой ответ:

Практический пример документирования API
В этом разделе мы создадим API-документацию для блога, чтобы наглядно понять концепции OpenAPI. В примере подробно разберем, как документировать эндпоинты.
Структура спецификации
Так как полный файл спецификации достаточно объемный, то в статье рассматриваются только его ключевые элементы. Полная версия файла и инструкция по запуску находится тут. Спецификация OpenAPI состоит из восьми корневых элементов:
openapi (обязательный)
Версия спецификации OpenAPI всегда указывается первой строкой:
openapi: 3.0.3
info (обязательный)
Раздел метаданных API. Обязательно указываются название (title) и версия (version). Опционально добавляются описание (description), контакты (contact) и лицензия (license). Описание можно форматировать через Markdown.
info:
title: Blog API
description: |
**Простое API блога** для изучения OpenAPI 3.0
version: 1.0.0
contact:
name: Blog API Support
email: support@blog.com
license:
name: MIT
servers
В этом разделе указывается список серверов, на которые могут отправляться запросы. URL формируются относительно базового адреса (например, https://api.blog.com/v1). В разделе variables можно настроить динамические параметры, которые будут подставляться в URL.
paths (обязательный)
В этом разделе описываются эндпоинты API: пути, HTTP-методы, параметры, тела запросов и форматы ответов, эти поля детально рассмотрим в статье позже.
paths:
/auth/login:
post:
summary: Вход в систему
tags: [Auth]
# ... детали операции
/posts:
get:
summary: Получить список постов
tags: [Posts]
# ... параметры и ответы
post:
summary: Создать новый пост
tags: [Posts]
# ... тело запроса и ответы
/posts/{postId}:
get:
summary: Получить пост по ID
parameters:
- name: postId
in: path
required: true
schema:
type: integer
# ...
components
Стандарт OpenAPI позволяет нам создавать необходимые компоненты один раз и затем переиспользовать их при необходимости.
Основные типы компонентов:
schemas — модели данных (User, Post, Error),
securitySchemes — способы аутентификации,
responses — общие ответы (404, 401 и т. д.),
parameters — переиспользуемые параметры.
components:
securitySchemes:
BearerAuth:
type: http
scheme: bearer
bearerFormat: JWT
schemas:
User:
type: object
required: [id, email, name]
properties:
id: { type: integer }
email: { type: string, format: email }
name: { type: string }
# ...
responses:
NotFoundError:
description: Ресурс не найден
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
security
Объект security определяет метод аутентификации по умолчанию для всех эндпоинтов:
security:
- BearerAuth: []
В OpenAPI поддерживаются 4 типа аутентификации, которые описаны в комментариях примера:
components:
securitySchemes:
# 1. API Key (в header, query или cookie)
ApiKeyAuth:
type: apiKey
name: X-API-Key
in: header
# 2. HTTP аутентификация (Basic, Bearer)
BearerAuth:
type: http
scheme: bearer
# 3. OAuth 2.0
OAuth2:
type: oauth2
flows:
authorizationCode:
authorizationUrl: https://api.example.com/oauth/authorize
tokenUrl: https://api.example.com/oauth/token
# 4. OpenID Connect
OpenID:
type: openIdConnect
openIdConnectUrl: https://api.example.com/.well-known/openid-configuration
Для отдельных операций можно изменить настройки безопасности:
/public:
get:
security: [] # Публичный доступ
/secure:
get:
security:
- BearerAuth: [] # Требует JWT токен
tags
Объект tags позволяет логически группировать эндпоинты API по разделам, благодаря чему становится проще ориентироваться в документации. Теги объявляются в корне файла спецификации OpenAPI:
tags:
- name: Пользователи
description: Управление пользователями блога
- name: Статьи
description: Операции с публикациями
- name: Комментарии
description: Работа с комментариями
- name: Категории
description: Управление категориями статей
После того, как мы распределим роуты, страничка документации будет выглядеть примерно так:

Каждый эндпоинт отдельно помечается соответствующими тегами:
paths:
/users:
get:
tags: ["Пользователи"]
summary: Получить список пользователей
post:
tags: ["Пользователи"]
summary: Создать нового пользователя
/posts:
get:
tags: ["Статьи"]
summary: Получить список статей
post:
tags: ["Статьи"]
summary: Создать новую статью
/posts/{postId}/comments:
get:
tags: ["Статьи", "Комментарии"]
summary: Получить комментарии к статье
post:
tags: ["Статьи", "Комментарии"]
summary: Добавить комментарий к статье
externalDocs
Объект externalDocs предоставляет ссылки на дополнительную документацию, которая может быть полезной для пользователей API. Изначально его можно использовать на корневом уровне:
yaml
externalDocs:
description: Полная документация API блога
url: https://docs.example.com/api/blog
Но при необходимости можно добавлять ссылки к конкретным эндпоинтам для уточняющей информации:
yaml
paths:
/posts/{postId}/comments:
get:
summary: Получить комментарии к статье
externalDocs:
description: Руководство по работе с комментариями
url: https://docs.example.com/guides/comments
Структура эндпоинтов и HTTP-методов
Рассмотрим детализацию документации для конкретных эндпоинтов API на примере работы со статьями блога. В данном примере описана спецификация для эндпоинтов /posts и /posts/{postId}, где для каждого определены соответствующие HTTP-методы: GET, POST, PUT, DELETE, PATCH.
yaml
paths:
/posts:
get: # Получить список постов
summary: Получить список постов
tags: [Статьи]
security: [] # Публичный endpoint
parameters:
- name: page
in: query
schema: { type: integer, default: 1 }
responses:
'200':
description: Список постов
# ...
post: # Создать новый пост
summary: Создать новый пост
tags: [Статьи]
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/PostCreate'
responses:
'201':
description: Пост создан
# ...
/posts/{postId}:
get: # Получить пост по ID
# ...
put: # Обновить пост
# ...
delete: # Удалить пост
# ...
Важные параметры HTTP-методов:
summary — краткое описание операции,
tags — группировка эндпоинтов (например, [Статьи]),
security — настройки доступа ([] для публичных эндпоинтов),
parameters — параметры запроса (query, path, header),
responses — описание возможных ответов (200, 201, 400, etc.),
requestBody — тело запроса для POST/PUT операций.
Обратите внимание на то, как описывается параметр в GET-методе у /posts.
Параметр page является query-параметром целочисленного типа со значением по умолчанию 1. В запросе он передается через строку запроса: /posts?page=2.
В методе POST для /posts используется ссылка $ref: '#/components/schemas/PostCreate'. Конструкция $ref представляет собой ссылку на переиспользуемую схему данных PostCreate, определенную в разделе components/schemas. Такой подход позволяет избежать дублирования кода, централизованно управлять схемами данных и упростить поддержку и обновление спецификаций.
Параметры
В OpenAPI существует четыре варианта передачи параметров: path, query, header и cookie. Каждый тип имеет свою область применения.
Path-параметры — обязательные параметры, встроенные в URL-путь. Используются для идентификации конкретного ресурса:
paths:
/posts/{postId}:
get:
parameters:
- name: postId
in: path
required: true
schema:
type: integer
minimum: 1
Query-параметры — необязательные параметры, передаваемые после знака ? в URL. Применяются для фильтрации, сортировки и пагинации:
paths:
/posts:
get:
parameters:
- name: page
in: query
description: Номер страницы
schema:
type: integer
minimum: 1
default: 1
- name: published
in: query
schema:
type: boolean
default: true
Header-параметры — передаются в HTTP заголовках запроса. Используются для метаданных, версионирования API и авторизации:
paths:
/status:
get:
parameters:
- name: X-API-Version
in: header
description: Версия API
schema:
type: string
enum: [v1, v2]
default: v1
Cookie-параметры — передаются через HTTP cookies. Применяются для сессий, настроек пользователя и состояния:
paths:
/cart:
get:
parameters:
- name: session_id
in: cookie
description: Идентификатор сессии
schema:
type: string
minLength: 1
После описания параметров в спецификации они автоматически появляются в интерфейсе Swagger UI. Параметры группируются по типам и отображаются с описаниями и примерами:

Path-параметры обязательны, Query-, Header- и Cookie-параметры опциональны по умолчанию. Для пояснения параметров используйте поле description. Валидацию определяйте через schema (тип, ограничения, значения по умолчанию)
Request Body
В этом разделе описывается тело запроса для методов, у которых есть payload (обычно POST/PUT/PATCH). Обязательно указывайте content с медиатипами (например, application/json) и схему (schema) — часто через $ref на components/schemas. Флаг required: true означает, что тело запроса обязательно.
paths:
/posts:
post:
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/PostCreate'
example:
title: "Изучаем OpenAPI"
content: "В этой статье разберем основы..."
published: false
Responses
Раздел ответов описывает возможные результаты выполнения операции по HTTP статус-кодам. Для каждого ответа указывайте description, а при наличии тела ответа — content и schema (например через $ref). Стандартные ответы об ошибках удобно выносить в components/responses и переиспользовать.
Компоненты и схемы
Компоненты размещаются в объекте components и позволяют переиспользовать общие элементы спецификации через поле $ref. При создании моделей данных стоит использовать следующие поля:
type — указывает тип данных, в нашем примере это объект JSON
properties — определяет все поля объекта с их типами и ограничениями
required: [...] — массив обязательных полей, которые должны присутствовать
example — примеры значений для полей, упрощают понимание и тестирование
components:
schemas:
User:
type: object
required: [id, email, name]
properties:
id: { type: integer, readOnly: true, example: 1 }
email: { type: string, format: email, example: "john@blog.com" }
name: { type: string, maxLength: 100, example: "John Doe" }
Post:
type: object
required: [id, title, content]
properties:
id: { type: integer, readOnly: true, example: 42 }
title: { type: string, maxLength: 200 }
content: { type: string }
author: { $ref: '#/components/schemas/User' }
Также дополнительно можно использовать следующие поля:
nullable: true — позволяет принимать значение null
oneOf/anyOf/allOf — логические операции для схем данных
- oneOf — значение должно соответствовать одной из схем (варианты)
- anyOf — может соответствовать любой из схем (объединение)
- allOf — должно соответствовать всем схемам (наследование/расширение)additionalProperties — разрешает объекту иметь поля, не описанные в properties (true — любые поля разрешены, false — разрешены только указанные)
uniqueItems: true — для массивов, гарантирует уникальность элементов
securitySchemes
Схемы аутентификации определяются один раз, после чего они подключаются к любым эндпоинтам через security.
components:
securitySchemes:
BearerAuth:
type: http
scheme: bearer
bearerFormat: JWT
Переиспользуемые компоненты
В разделе components есть 4 объекта:
parameters — переиспользуемые параметры (postId, page),
headers — общие заголовки (X-Total-Count, X-RateLimit),
responses — стандартные ответы (ошибки 404, 400),
securitySchemes — схемы аутентификации (Bearer, API Key).
Все подключаются через $ref: '#/components/тип/название'.
parameters
Переиспользуемые параметры для нескольких эндпоинтов. Гарантирует единообразие типов и описаний.
parameters:
PostIdParam:
name: postId
in: path
required: true
description: ID поста
schema:
type: integer
minimum: 1
example: 42
PostIdParam — параметр для переиспользования:
name: postId — имя параметра,
in: path — параметр в пути URL (/posts/{postId}),
required: true — обязательный,
schema — целое число от 1,
example: 42 — пример значения.
Использование: $ref: '#/components/parameters/PostIdParam'
headers
Переиспользуемые заголовки ответов:
headers:
TotalCount:
description: Общее количество элементов
schema:
type: integer
example: 150
TotalCount — заголовок для переиспользования:
description — описание
schema — целое число
example — пример
Использование: $ref: '#/components/headers/TotalCount'
responses
Тут находятся шаблоны стандартных ответов API. Они определяют HTTP-ответы со ссылками на схемы данных.
responses:
ValidationError:
description: Ошибка валидации
content:
application/json:
schema:
$ref: '#/components/schemas/ValidationError'
NotFound:
description: Ресурс не найден
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
ValidationError — ответ для ошибок валидации с деталями по каждому полю. NotFound — ответ для несуществующих ресурсов. Обратите внимание на то, что имена схем и ответов(responses) могут совпадать, за счет того что у них разные пути к конечным объектам.
Response содержит:
description — описание ответа
content — тип контента (обычно JSON)
schema — ссылка на структуру данных в components/schemas
Пример использования:
paths:
/posts:
post:
responses:
'400':
$ref: '#/components/responses/ValidationError'
'404':
$ref: '#/components/responses/NotFound'
Примеры JSON-ответов:
{
"error": {
"code": "VALIDATION_ERROR",
"message": "Неверный формат email"
}
}
{
"code": "VALIDATION_ERROR",
"message": "Ошибка валидации входных данных",
"errors": [
{
"field": "email",
"code": "INVALID_FORMAT",
"message": "Неверный формат email"
}
]
}
securitySchemes
Схемы аутентификации определяют способы защиты API. После объявления их можно применять ко всему API или отдельным эндпоинтам. Ниже представлен пример для BearerAuth (схема JWT-аутентификации через заголовок Authorization):
securitySchemes:
BearerAuth:
type: http
scheme: bearer
bearerFormat: JWT
description: |
JWT токен в заголовке Authorization.
Пример: `Authorization: Bearer <token>`
SecurityScheme содержит:
type — тип аутентификации (http, apiKey, oauth2, openIdConnect),
scheme — схема HTTP-аутентификации (bearer, basic),
bearerFormat — формат токена (опционально),
description — описание использования.
Глобальное применение:
security:
- BearerAuth: []
Применение к эндпоинту:
paths:
/posts:
post:
security:
- BearerAuth: []
# ...
/public:
get:
security: [] # Отключение аутентификации
# ...
Разбиение спецификации OpenAPI на файлы
Монолитная спецификация OpenAPI быстро становится большой и сложной при росте API. Файл в несколько тысяч строк усложняет навигацию, код-ревью и командную работу. Модульная структура решает эти проблемы через разделение ответственности: каждый компонент хранится в отдельном файле и подключается через механизм ссылок $ref.
Корневой openapi.yaml содержит только метаинформацию и ссылки:
openapi: 3.0.3
info:
title: Blog API
version: 1.0.0
paths:
/posts:
$ref: './paths/posts.yaml'
/posts/{postId}:
$ref: './paths/posts.{postId}.yaml'
components:
schemas:
Post:
$ref: './components/schemas/Post.yaml'
paths/posts.yaml описывает операции с коллекцией:
get:
summary: Получить список статей
responses:
'200':
content:
application/json:
schema:
$ref: '../components/schemas/PostList.yaml'
components/schemas/Post.yaml определяет структуру данных:
type: object
required: [id, title, content]
properties:
id: { type: integer }
title: { type: string, maxLength: 200 }
content: { type: string }
В результате вместо одного большого файла мы получаем модульную структуру с интуитивно понятными названиями. Пример организации файлов:

Механизм $ref поддерживает относительные пути от текущего файла. При ссылке из paths/ на компоненты используется префикс ../components/. Внутри одной директории можно ссылаться напрямую: ./User.yaml. Полный пример разбиения монолитного файла можете посмотреть на гитхабе.
Валидация файлов спецификации
Для проверки OpenAPI-документации используются два инструмента с разными задачами. Для проверки синтаксиса используется yq. Redocly CLI проверяет файл на соответствие спецификации OpenAPI. Оба инструмента легко интегрируются в CI/CD-процессы.
Установка инструментов:
sudo snap install yq
npm install -g @redocly/cli
Сначала проверим корректность YAML-файла. Утилита yq позволяет найти синтаксические ошибки. Для проверки нужно выполнить следующую команду:
yq e '.' docs/openapi/openapi.yaml >/dev/null && echo "OK"
При успешной проверке команда выведет OK. В случае ошибки будет показано сообщение с указанием проблемной строки.
После проверки синтаксиса мы должны удостовериться, что содержимое файла соответствует стандарту OpenAPI и не содержит логических ошибок. Для этого применяется инструмент Redocly CLI. Пример команды для валидации:
redocly lint docs/openapi/openapi.yaml
При наличии ошибок Redocly покажет детальное описание проблем с указанием файлов и путей.
Общие выводы
OpenAPI 3.0 представляет собой стандарт документирования REST API, обеспечивающий единый контракт между фронтендом и бэкендом. Спецификация описывает все аспекты API: эндпоинты, параметры, модели данных, методы аутентификации и форматы ответов.
Автор alex_name_m
НЛО прилетело и оставило здесь промокод для читателей нашего блога:
— 15% на заказ любого VDS (кроме тарифа Прогрев) — HABRFIRSTVDS.
ivvi
Ну не только REST API. Как будто в мире есть только рест, и любой апи на протоколе хттп является рестом...
OpenAPI прекрасно подходит и для не-RESTful API, например, для RPC HTTP API или Action-oriented (оно же Operation-centric) HTTP API. Читал, что в версии 4.0 собираются даже поддержку gRPC и асинхронщины прикрутить.
Нет никаких проблем описать в опенапи эндпоинт типа /doSomethingStrange. REST тут не при чем.
В остальном спасибо, конечно, но непонятно, к чему и почему это "пошаговое руководство". Просто краткий пересказ общедоступной спеки.