OpenAPI: контракт, специфікація та документація API
OpenAPI: контракт, специфікація та документація API
1. Навіщо OpenAPI, якщо код уже існує
Уявімо реальну ситуацію. Команда бекенду каже: «Ендпоінт готовий, просто виклич POST /v1/orders». Команда фронтенду питає:
- Які поля обов'язкові?
- Який формат має
created_at? - Які статус-коди повертаються при помилках?
- Чи потрібно передавати
Authorization? - Який вигляд має
422, а який409?
Якщо відповіді на ці питання живуть лише в коді сервера, то клієнтський розробник змушений або читати чужий бекенд, або експериментувати через Postman, або ставити десятки уточнювальних питань. Це дорого, повільно і небезпечно, бо API перетворюється з контракту на набір припущень.
OpenAPI розв'язує цю проблему: він формалізує HTTP API в машинозчитуваний документ. Такий документ може одночасно читати людина, IDE, генератор клієнтів, тестові інструменти та система перевірки контракту.
Що ви отримаєте
- Чітке розуміння, що саме описує OpenAPI
- Навичку читати структуру
paths,responses,components,schemas - Вміння відрізняти специфікацію від інструментів на кшталт Swagger UI
- Практичний YAML-приклад невеликого API
Пререквізити
- Розуміння базового HTTP: методи, URL, статус-коди
- Знання JSON та структури HTTP-запиту/відповіді
- Бажано прочитати матеріали про формати даних, статус-коди, валідацію та безпеку
2. Що таке OpenAPI насправді
OpenAPI Specification (OAS), або просто OpenAPI, це стандарт опису HTTP API у форматі YAML або JSON.
Ключова думка: OpenAPI описує контракт взаємодії, а не реалізацію сервера. У специфікації немає SQL-запитів, внутрішніх сервісів, middleware чи класів доменної моделі. Там є лише те, що бачить зовнішній споживач API:
- які ресурси існують;
- які HTTP-методи підтримуються;
- які параметри треба передати;
- яке тіло запиту очікується;
- які відповіді можливі;
- які схеми даних використовуються;
- яка авторизація потрібна.
OpenAPI, Swagger, Swagger UI: де тут плутанина
Тут часто виникає термінологічний хаос, тому розмежуємо поняття одразу.
| Термін | Що це таке | Роль |
|---|---|---|
| OpenAPI | Стандарт специфікації | Описує контракт API |
| Swagger Specification | Історична назва попередніх версій стандарту | Сьогодні майже завжди мають на увазі OpenAPI |
| Swagger UI | Вебінтерфейс для візуалізації специфікації | Показує документацію та дає робити тестові запити |
| Swagger Editor | Редактор специфікацій | Дає писати і перевіряти YAML/JSON |
| Code Generator | Інструмент генерації клієнта або серверного каркаса | Використовує специфікацію як вхідні дані |
Проблема в тому, що в побутовій мові розробники часто кажуть «Swagger», маючи на увазі будь-що з цього списку. Але технічно коректніше розділяти:
OpenAPI— це формат договору;Swagger UI— це спосіб показати договір;generator— це спосіб використати договір.
3. Що саме дає OpenAPI команді
OpenAPI цінний не тому, що «гарно виглядає в браузері». Його сила в тому, що один документ стає єдиним джерелом правди для кількох ролей одночасно.
Практична користь:
| Сценарій | Як допомагає OpenAPI |
|---|---|
| Документація | Swagger UI або інші сайти будують reference автоматично |
| Розробка клієнта | Генеруються DTO, методи виклику, типи помилок |
| Тестування | Можна перевіряти, чи сервер не порушив контракт |
| Рев'ю API-дизайну | Контракт видно до реалізації коду |
| Onboarding | Новий інженер читає специфікацію, а не 30 контролерів |
4. Анатомія OpenAPI-документа
OpenAPI-документ зазвичай має кілька великих частин. Кожна відповідає на окремий клас запитань.
Крок 1: Метадані документа
Секції openapi, info і servers відповідають на питання:
- яку версію стандарту ми використовуємо;
- як називається API;
- де воно доступне;
- який базовий URL вважати коренем.
Крок 2: Операції та маршрути
Секція paths описує URL та HTTP-методи. Саме тут живуть get, post, put, delete, параметри маршруту, query-параметри, requestBody і responses.
Крок 3: Повторно використовувані схеми
Секція components потрібна, щоб не дублювати структури всюди вручну. Тут зберігають:
schemasдля типів даних;parametersдля спільних параметрів;responsesдля типових відповідей;securitySchemesдля опису авторизації.
Крок 4: Правила безпеки
Секції securitySchemes і security формалізують, які механізми аутентифікації потрібні: Bearer token, API key, OAuth2 тощо.
Мінімальна мапа структури
openapi: 3.1.0
info:
title: Coffee API
version: 1.0.0
servers:
- url: https://api.example.com
paths:
/v1/orders:
post:
summary: Create order
components:
schemas: {}
securitySchemes: {}
Цей каркас нічого корисного ще не описує, але показує головну ідею: документ читається зверху вниз, від загальних метаданих до конкретних операцій і повторно використовуваних типів.
Каталог важливих елементів і їх варіацій
До цього моменту ми бачили лише великий каркас. Але реальна робота з OpenAPI майже завжди відбувається на рівні маленьких фрагментів: сьогодні вам треба згадати, як описати multipart/form-data, завтра — як оформити oneOf, післязавтра — як документувати query-параметр-масив.
Нижче наведено саме такий довідковий шар: короткі приклади, які можна читати незалежно один від одного.
info: не лише title і version
Секція info може містити не тільки назву та версію, а й метадані для людей, юристів і партнерів.
info:
title: Billing API
version: 2.3.0
summary: API для рахунків, платежів і повернень
description: >
Публічний контракт платіжної платформи для партнерів.
termsOfService: https://example.com/terms
contact:
name: API Support
email: api-support@example.com
url: https://example.com/support
license:
name: Commercial License
url: https://example.com/license
Практичний сенс:
summaryдає короткий контекст;contactзменшує кількість «кому писати, якщо щось не працює?»;licenseтаtermsOfServiceважливі для публічних або партнерських API.
servers: фіксовані URL та змінні
Найпростіший варіант ми вже бачили: список готових URL. Але servers підтримує і змінні.
servers:
- url: https://api.example.com
description: Production
- url: https://sandbox.example.com
description: Sandbox
servers:
- url: https://{environment}.example.com/{basePath}
description: Configurable endpoint
variables:
environment:
default: api
enum: [api, sandbox, staging]
basePath:
default: v1
Змінні корисні, коли адреса API структурно стабільна, але середовище або базовий префікс можуть змінюватися.
tags: не декоративна дрібниця
Багато хто сприймає tags як косметику для UI. Насправді це основний інструмент навігації у великих документах.
tags:
- name: Orders
description: Операції із замовленнями
- name: Payments
description: Платежі, повернення та статуси транзакцій
- name: Admin
description: Адміністративні endpoint-и
Якщо у вас 80 операцій і немає тегів, документація швидко стає непридатною до використання.
parameters: чотири місця розташування
Параметри в OpenAPI описуються не абстрактно, а з чітким in.
parameters:
- name: orderId
in: path
required: true
schema:
type: string
format: uuid
Для path параметрів required: true є фактично обов'язковим, бо інакше сам шлях втрачає сенс.
parameters:
- name: limit
in: query
required: false
schema:
type: integer
minimum: 1
maximum: 100
Типовий сценарій: фільтри, сортування, пагінація, пошук.
parameters:
- name: X-Correlation-Id
in: header
required: false
schema:
type: string
Зручно для correlation id, feature flags, ідемпотентності, умовних ревізій.
parameters:
- name: session_id
in: cookie
required: true
schema:
type: string
Цей варіант рідше зустрічається в публічних API, але корисний для browser-oriented сценаріїв.
style і explode: як серіалізуються параметри
Один і той самий масив можна передати кількома способами. Саме для цього існують style і explode.
in | Типовий style | Що це означає |
|---|---|---|
path | simple, label, matrix | як параметр вбудовується в URL-шлях |
query | form, spaceDelimited, pipeDelimited, deepObject | як параметр потрапляє в query string |
header | simple | як значення кодується в заголовку |
cookie | form | як значення кодується в cookie |
parameters:
- name: tags
in: query
style: form
explode: true
schema:
type: array
items:
type: string
Такий опис зазвичай означає формат на кшталт:
?tags=coffee&tags=arabica&tags=discount
Ще один приклад:
parameters:
- name: filter
in: query
style: deepObject
explode: true
schema:
type: object
properties:
status:
type: string
minPrice:
type: number
Це вже відповідає формату:
?filter[status]=active&filter[minPrice]=100
style і explode, якщо ваш бекенд насправді не підтримує таку серіалізацію. Це один із найпідступніших способів зробити документацію формально валідною, але практично хибною.requestBody: не лише JSON
requestBody потрібен не всім методам, але коли він є, OpenAPI дозволяє дуже точно вказати тип контенту.
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/CreateOrderRequest'
requestBody:
required: true
content:
application/x-www-form-urlencoded:
schema:
type: object
required: [email, password]
properties:
email:
type: string
format: email
password:
type: string
Підходить для класичних login/form сценаріїв.
requestBody:
required: true
content:
multipart/form-data:
schema:
type: object
required: [file]
properties:
file:
type: string
format: binary
folder:
type: string
Підходить для завантаження файлів.
responses: фіксовані коди, default, headers, links
Більшість статей обмежуються прикладом 200 і 404. Але OpenAPI підтримує значно більше.
responses:
'200':
description: Успішна відповідь
content:
application/json:
schema:
$ref: '#/components/schemas/Order'
responses:
default:
description: Непередбачена помилка
content:
application/json:
schema:
$ref: '#/components/schemas/ApiError'
Корисно, коли ви хочете зафіксувати загальну fallback-помилку для невідомих статусів.
responses:
'201':
description: Створено
headers:
Location:
description: URL нового ресурсу
schema:
type: string
format: uri
responses:
'201':
description: Створено
links:
GetCreatedOrder:
operationId: getOrderById
parameters:
orderId: '$response.body#/id'
links не виконує логіку сам по собі, але формально документує зв'язок: після одного виклику можна переходити до іншого.
content: одна відповідь, кілька media type
OpenAPI дозволяє описати кілька форматів представлення тієї самої відповіді.
responses:
'200':
description: Товар знайдено
content:
application/json:
schema:
$ref: '#/components/schemas/Product'
application/xml:
schema:
$ref: '#/components/schemas/Product'
У сучасних HTTP API найчастіше достатньо application/json, але стандарт не обмежується лише ним.
components: не лише schemas
У багатьох командах components асоціюється лише зі schemas. Це спрощення. Насправді components може бути центральним місцем для всіх повторно використовуваних шматків контракту.
components:
schemas: {}
responses: {}
parameters: {}
examples: {}
requestBodies: {}
headers: {}
securitySchemes: {}
links: {}
callbacks: {}
Найчастіше реально використовують:
schemas;responses;parameters;securitySchemes.
Але для великих API також корисні requestBodies, headers, examples і links.
components:
requestBodies:
CreateOrderBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/CreateOrderRequest'
paths:
/v1/orders:
post:
requestBody:
$ref: '#/components/requestBodies/CreateOrderBody'
components:
headers:
RequestId:
description: Унікальний ідентифікатор запиту
schema:
type: string
responses:
'200':
description: OK
headers:
X-Request-Id:
$ref: '#/components/headers/RequestId'
components:
examples:
ReadyOrder:
summary: Готове замовлення
value:
id: 42
status: ready
Практичний принцип тут простий: якщо один і той самий фрагмент починає копіюватися в кілька місць, подумайте, чи не час винести його в components.
example vs examples
Це маленька, але дуже часта точка плутанини.
schema:
type: string
example: pending
content:
application/json:
schema:
$ref: '#/components/schemas/Order'
examples:
draft:
summary: Чернетка
value:
id: 1
status: pending
done:
summary: Завершене замовлення
value:
id: 2
status: ready
example добре підходить для простих полів. examples краще, коли треба показати кілька реальних сценаріїв.
schemas: не лише примітиви
У components/schemas можна описувати як прості типи, так і складні композиції.
OrderStatus:
type: string
enum: [pending, paid, canceled]
ValidationError:
allOf:
- $ref: '#/components/schemas/ApiError'
- type: object
properties:
errors:
type: array
items:
type: string
PaymentMethod:
oneOf:
- $ref: '#/components/schemas/CardPayment'
- $ref: '#/components/schemas/CashPayment'
SearchFilter:
anyOf:
- $ref: '#/components/schemas/DateFilter'
- $ref: '#/components/schemas/StatusFilter'
User:
type: object
properties:
id:
type: string
readOnly: true
password:
type: string
writeOnly: true
Практична інтерпретація:
allOfдобре підходить для наслідування або розширення базової помилки;oneOfозначає «рівно одна форма з кількох»;anyOfозначає «може відповідати кільком формам одразу»;readOnlyіwriteOnlyдопомагають не плутати поля, що приходять лише від клієнта або лише від сервера.
discriminator: коли oneOf стає складним
Якщо oneOf описує поліморфні об'єкти, часто потрібен discriminator, щоб клієнт зрозумів, яку саме форму він отримав.
PaymentMethod:
oneOf:
- $ref: '#/components/schemas/CardPayment'
- $ref: '#/components/schemas/BankTransferPayment'
discriminator:
propertyName: type
mapping:
card: '#/components/schemas/CardPayment'
bank_transfer: '#/components/schemas/BankTransferPayment'
securitySchemes: основні варіанти
securitySchemes:
bearerAuth:
type: http
scheme: bearer
bearerFormat: JWT
securitySchemes:
apiKeyAuth:
type: apiKey
in: header
name: X-Api-Key
securitySchemes:
oauth2:
type: oauth2
flows:
authorizationCode:
authorizationUrl: https://auth.example.com/authorize
tokenUrl: https://auth.example.com/token
scopes:
orders.read: Read orders
orders.write: Modify orders
securitySchemes:
oidc:
type: openIdConnect
openIdConnectUrl: https://auth.example.com/.well-known/openid-configuration
Після визначення схеми її ще треба застосувати:
security:
- bearerAuth: []
Або глобально для всього документа:
security:
- bearerAuth: []
callbacks і webhooks: просунуті сценарії
Більшість OpenAPI-документів ніколи не використовують callbacks, але для асинхронних інтеграцій це дуже цінний інструмент.
callbacks:
paymentUpdated:
'{$request.body#/callbackUrl}':
post:
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/PaymentStatusChanged'
responses:
'200':
description: Callback accepted
Сенс тут такий: клієнт передає URL зворотного виклику, а сервер документує, який HTTP-запит прийде туди пізніше.
externalDocs: коли специфікації замало
OpenAPI добре описує контракт, але не замінює повністю гіди, туторіали та бізнесові пояснення.
externalDocs:
description: Повний гайд для інтеграції
url: https://developer.example.com/guides/orders
Цей елемент корисний, коли вам треба пов'язати формальний контракт із навчальним або бізнесовим контекстом.
5. Повний приклад невеликої специфікації
Нижче наведено компактний, але реалістичний OpenAPI-документ для створення і читання замовлень.
openapi: 3.1.0
info:
title: Coffee Orders API
version: 1.0.0
summary: API для створення та перегляду замовлень кави
description: >
Контракт HTTP API для мобільного додатка кав'ярні.
API дозволяє створювати замовлення та отримувати їх за ідентифікатором.
servers:
- url: https://api.example.com
description: Production
- url: https://sandbox.api.example.com
description: Sandbox
tags:
- name: Orders
description: Операції із замовленнями
paths:
/v1/orders:
post:
tags: [Orders]
operationId: createOrder
summary: Створити нове замовлення
description: >
Приймає дані нового замовлення, виконує валідацію
і повертає створений ресурс.
security:
- bearerAuth: []
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/CreateOrderRequest'
examples:
lungo:
summary: Замовлення лунго
value:
recipeId: lungo
volumeMl: 300
sugar: 1
responses:
'201':
description: Замовлення створено
headers:
Location:
description: URL створеного ресурсу
schema:
type: string
format: uri
content:
application/json:
schema:
$ref: '#/components/schemas/Order'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'422':
$ref: '#/components/responses/ValidationError'
/v1/orders/{orderId}:
get:
tags: [Orders]
operationId: getOrderById
summary: Отримати замовлення за ідентифікатором
security:
- bearerAuth: []
parameters:
- $ref: '#/components/parameters/OrderId'
responses:
'200':
description: Замовлення знайдено
content:
application/json:
schema:
$ref: '#/components/schemas/Order'
'401':
$ref: '#/components/responses/Unauthorized'
'404':
$ref: '#/components/responses/NotFound'
components:
parameters:
OrderId:
name: orderId
in: path
required: true
description: UUID замовлення
schema:
type: string
format: uuid
securitySchemes:
bearerAuth:
type: http
scheme: bearer
bearerFormat: JWT
responses:
BadRequest:
description: Некоректний формат запиту
content:
application/json:
schema:
$ref: '#/components/schemas/ApiError'
Unauthorized:
description: Користувач не аутентифікований
content:
application/json:
schema:
$ref: '#/components/schemas/ApiError'
NotFound:
description: Замовлення не знайдено
content:
application/json:
schema:
$ref: '#/components/schemas/ApiError'
ValidationError:
description: Помилка валідації полів
content:
application/json:
schema:
$ref: '#/components/schemas/ValidationError'
schemas:
CreateOrderRequest:
type: object
additionalProperties: false
required:
- recipeId
- volumeMl
properties:
recipeId:
type: string
description: Код рецепта
example: lungo
volumeMl:
type: integer
minimum: 50
maximum: 500
description: Об'єм напою в мілілітрах
example: 300
sugar:
type: integer
minimum: 0
maximum: 5
description: Кількість ложок цукру
example: 1
Order:
type: object
required:
- id
- recipeId
- volumeMl
- status
- createdAt
properties:
id:
type: string
format: uuid
recipeId:
type: string
volumeMl:
type: integer
sugar:
type: integer
nullable: true
status:
type: string
enum: [pending, brewing, ready, canceled]
createdAt:
type: string
format: date-time
ApiError:
type: object
required:
- status
- reason
- developerMessage
properties:
status:
type: integer
example: 401
reason:
type: string
example: authentication_required
developerMessage:
type: string
example: Bearer token is missing or invalid
ValidationError:
allOf:
- $ref: '#/components/schemas/ApiError'
- type: object
properties:
errors:
type: array
items:
type: object
required: [field, message]
properties:
field:
type: string
message:
type: string
Як читати цей документ
info і servers
Блок info описує сам документ: назву, версію, короткий опис. Блок servers показує, проти яких середовищ клієнт може працювати. Це не просто декоративна інформація: інструменти можуть підставляти Production або Sandbox як базову адресу для тестових запитів.
paths
Тут видно дві операції:
POST /v1/ordersстворює ресурс;GET /v1/orders/{orderId}читає ресурс.
Кожна операція має власні:
summaryіdescriptionдля документації;operationIdдля генераторів SDK;securityдля вимог авторизації;parameters,requestBody,responsesдля контракту взаємодії.
requestBody
У POST /v1/orders тіло запиту оголошене явно. Специфікація не просто каже «передайте JSON», а визначає:
- MIME-тип через
application/json; - конкретну схему через
$ref; - приклади через
examples.
Саме тому якісний OpenAPI-документ корисніший за звичайний Markdown-опис. Він не обмежується словами, а формалізує структуру.
responses
У кожного статус-коду є свій опис. Це критично важливо: без цього клієнт бачить лише «може бути 400», але не знає, яке тіло повернеться і як його парсити.
Зверніть увагу на два прийоми:
201описано локально, бо там унікальна відповідь зLocation;400,401,404,422винесені вcomponents/responses, щоб не дублювати один і той самий фрагмент у десяти ендпоінтах.
components/schemas
Секція schemas описує форми даних. Це фактично словник типів, який використовує весь документ.
Наприклад:
CreateOrderRequestописує payload вхідного запиту;Orderописує успішну відповідь;ApiErrorіValidationErrorописують формат помилок.
Якщо ви змінюєте схему в одному місці, усі $ref, що посилаються на неї, автоматично використовують оновлений контракт.
6. Ключові елементи, які часто недооцінюють
operationId
Для людини operationId може виглядати необов'язковим. Але для генератора клієнта це майже ім'я методу.
Без operationId ви ризикуєте отримати в SDK щось на кшталт postV1Orders або getV1OrdersOrderId, що складно читати й підтримувати. Імена на кшталт createOrder, getOrderById, cancelOrder роблять сгенерований код набагато якіснішим.
examples
Схема показує форму даних, але приклад показує семантику. Поле volumeMl: integer не пояснює, чи типове значення це 50, 300 чи 5000. Приклад показує нормальний, очікуваний сценарій використання.
additionalProperties: false
Цей прапорець означає: «не приймайте довільні зайві поля». Він корисний, коли ви хочете жорсткіший контракт і не бажаєте мовчазно проковтувати сміттєві дані.
securitySchemes та security
Безпека в OpenAPI не повинна лишатися «текстом у README». Якщо API вимагає Bearer token, це має бути описано структуровано. Інакше документація виглядатиме повною, але фактично не дозволить коректно використати API.
7. Contract-first vs Code-first
Це одна з головних стратегічних розвилок у роботі з OpenAPI.
Спочатку команда проєктує OpenAPI-специфікацію, рев'ює її і лише потім починає реалізацію сервера та клієнтів.
Цей підхід сильний тоді, коли:
- API споживає кілька команд;
- контракт має бути стабільним і погодженим заздалегідь;
- важливо провести дизайн-рев'ю до написання коду;
- потрібна генерація SDK або мок-сервера з контракту.
Спочатку пишеться серверний код, а OpenAPI генерується з реалізації автоматично через framework або бібліотеку.
Цей підхід сильний тоді, коли:
- API невеликий;
- серверна команда одна і рухається швидко;
- важливіше зменшити ручну працю, ніж провести окремий етап контрактного дизайну;
- framework добре генерує специфікацію з анотацій чи метаданих.
Який підхід кращий
Універсально «кращого» підходу не існує. Потрібно дивитися на організаційний контекст.
| Сценарій | Кращий стартовий вибір |
|---|---|
| Публічне API для зовнішніх інтеграцій | contract-first |
| B2B API з тривалим життєвим циклом | contract-first |
| Внутрішній сервіс невеликої команди | code-first |
| Прототип або MVP | code-first, але з подальшим контрактним прибиранням |
code-first режимі команда повинна почати ставитися до згенерованого OpenAPI як до публічного артефакту, який перевіряють у code review так само уважно, як і код.8. Типові помилки в OpenAPI-специфікаціях
Погана специфікація не краща за відсутність специфікації. Вона створює фальшиве відчуття надійності.
400, 401, 403, 404, 409, 422, 429, 500 або інші релевантні сценарії.camelCase, а сервер повертає snake_case; у схемі date-time, а сервер віддає локальну дату без timezone. Така документація не просто застаріла, а брехлива.components.9. Як OpenAPI пов'язаний з іншими темами API-дизайну
OpenAPI не живе окремо від решти архітектурних рішень. Він лише фіксує їх у формальному вигляді.
Статус-коди
responses.Валідація
requestBody, schemas і моделі ApiError.Безпека
Процес проєктування
10. Інструменти та робочий процес
На практиці команда рідко працює зі специфікацією «вручну і в вакуумі». Зазвичай навколо OpenAPI існує цілий pipeline.
- Команда проєктує або генерує специфікацію.
- Специфікація перевіряється валідатором і проходить review.
- Документаційний UI показує reference.
- Генератор клієнтів або контрактні тести використовують документ як джерело правди.
- Зміни у специфікації порівнюються на предмет breaking changes.
11. Практичні завдання
Рівень 1: Базовий
Візьміть наведений у статті YAML і письмово дайте відповідь на питання:
- Які операції описані в
paths? - Яка схема використовується для створення замовлення?
- Які помилки може повернути
POST /v1/orders? - Де саме описано Bearer-аутентифікацію?
Розширте специфікацію новою операцією GET /v1/orders, яка повертає список замовлень.
Додайте:
- query-параметр
limit; - query-параметр
cursor; - схему відповіді для списку;
- мінімум одну помилку для неавторизованого запиту.
Рівень 2: Аналітика контракту
Створіть навмисно проблемну версію контракту:
- Приберіть
requiredдля одного обов'язкового поля - Замініть
format: uuidна звичайнийstring - Видаліть опис помилки
422 - Приберіть
securityу захищеного endpoint
Після цього поясніть, які проблеми це створить для клієнта, документації та генератора SDK.
Оберіть один реальний сценарій:
- внутрішній сервіс команди;
- партнерське API;
- публічне API мобільного застосунку.
Для нього аргументуйте, який підхід буде кращим: contract-first чи code-first. Аргументи мають стосуватися не технології, а процесу команди, ризику breaking changes і вимог до документації.
Рівень 3: Мініпроєкт
Оберіть одну предметну область: бібліотека, спортзал, доставка їжі або бронювання переговорних кімнат.
Створіть OpenAPI-специфікацію, що містить:
infoтаservers;- мінімум 3 маршрути в
paths; - одну mutation-операцію з
requestBody; - мінімум 3 схеми в
components/schemas; - мінімум 4 статус-коди відповідей;
- один механізм авторизації в
securitySchemes.
Після цього перевірте, чи ваш контракт узгоджується з правилами з матеріалів про статус-коди, валідацію, пагінацію та безпеку.
12. Підсумок
OpenAPI потрібен не для «гарної Swagger-сторінки», а для формалізації контракту між сервером і споживачами API. Якщо дизайн API є хорошим, OpenAPI робить його видимим, перевірюваним і придатним для автоматизації. Якщо дизайн API є поганим, OpenAPI дуже швидко це викриває.
Практичний висновок такий:
- спочатку спроєктуйте поведінку API;
- потім зафіксуйте її у специфікації;
- ставтеся до OpenAPI як до публічного контракту, а не як до другорядного артефакту tooling.
Саме в такому вигляді специфікація стає частиною інженерної дисципліни, а не просто ще одним YAML-файлом у репозиторії.
Процес проєктування API та документування
Покроковий алгоритм проєктування API: від аналізу предметної області до документації, версіонування, code style та чеклиста якості.
Основи аутентифікації та авторизації
Authentication vs Authorization, Claims-модель ідентичності .NET, ClaimsPrincipal, AuthenticationMiddleware, схеми аутентифікації та повний потік обробки запиту.