[Документация Yandex Cloud](../index.md) > [Облачная терминология](index.md) > Сети и доставка контента > OpenAPI

# OpenAPI

OpenAPI — это открытый стандарт или спецификация для машиночитаемого описания HTTP API, таких как [REST-API](rest-api.md). С помощью спецификации описываются эндпоинты ([URL](url.md), по которому можно получить доступ к функциональности API), методы, параметры, заголовки, [cookies](cookie.md) и другие аспекты работы современных API.

До середины 2010-х годов каждый разработчик или компания самостоятельно определяли, как документировать свои API. Это приводило к огромному количеству ошибок и трате времени на внедрение очередного микросервиса. Для решения этой проблемы в 2010 году началась разработка стандартизированного описания API, которое позже получило название Swagger.

В 2015 году Swagger был передан организации OpenAPI Initiative, а вскоре спецификация стала называться OpenAPI. Сегодня без нее невозможно представить разработку большинства крупных проектов — без единого машиночитаемого формата интеграция множества внешних и внутренних сервисов стала бы крайне сложной задачей.

Создание стандарта также привело к появлению Design-First подхода в разработке API, при котором вы еще до написания кода описываете каждый элемент API таким образом, чтобы его могли понять и люди, и компьютеры. Это требует временных затрат на этапе проектирования, но в долгосрочной перспективе снижает количество ошибок и избавляет от необходимости переписывать код.

## Структура OpenAPI {#structure}

Спецификация описывается в формате JSON или YAML и представляет собой файл (или несколько — для больших проектов), который содержит множество элементов. Кратко рассмотрим основные секции спецификации OpenAPI:

* `openapi` — первая и обязательная секция с версией спецификации, по которой инструменты проверяют совместимость.
* `info` — метаданные API. Своего рода «паспорт» документа. Для публичных или партнерских API рекомендуется подробно заполнять ключ `description`, чтобы разработчикам и ИИ-агентам было понятнее.
* `servers` — список серверов, на которые направляются запросы к API. Разделены по назначению, например, тестовый и рабочий.
* `paths` — доступные эндпоинты и методы, которые через них вызываются. Каждой HTTP-операции должен быть присвоен путь. Подробнее в разделе [HTTP-методы](#http-methods).
* `components` — многократно используемые компоненты, которые встречаются в разных частях спецификации. Подробнее в разделе [Описание переиспользуемых объектов](#components).
* `webhooks` — список входящих [вебхуков](webhook.md). Описывает, какие запросы типа `POST` API отправляет клиенту при возникновении заданных событий, например уведомления об отправке заказа.
* `security` — требования авторизации для операций. Подробнее в разделе [Безопасность и аутентификация](#security).
* `tags` — секция группировки эндпоинтов операций для облегчения навигации. Удобна для больших API, в которых операции можно сгруппировать по типу, например `users`, `payments`.
* `externalDocs` — ссылки на дополнительную документацию. При необходимости также можно добавлять ссылки к конкретным эндпоинтам для уточняющей информации.

{% cut "Упрощенный пример структуры" %}

```yaml
openapi: 3.1.0
info:
  title: Книжный магазин
  description: Простой API для работы с книгами
  version: 1.0.0

servers:
  - url: https://api.bookshop.example.com/v1

paths:
    post:
      summary: Добавить новую книгу
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/BookCreate'
      responses:
        '201':
          description: Книга создана
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Book'

  /books/{id}:
    get:
      summary: Получить одну книгу по ID
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: integer
          description: ID книги
      responses:
        '200':
          description: Найденная книга
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Book'
        '404':
          description: Книга не найдена

components:
  schemas:
    Book:
      type: object
      properties:
        id:
          type: integer
        title:
          type: string
        author:
          type: string
        year:
          type: integer
        price:
          type: number
    BookCreate:
      type: object
      required: [title, author]
      properties:
        title:
          type: string
        author:
          type: string
        year:
          type: integer
        price:
          type: number
```

{% endcut %}

## HTTP-методы {#http-methods}

HTTP-методы описываются внутри секции `paths` и задают конкретный путь и объект операции. OpenAPI поддерживает следующие методы:

* `get` — получение ресурса или списка ресурсов;
* `post` — создание ресурса, запуск действия или отправка формы;
* `put` — полное обновление ресурса или создание нового, если его нет;
* `patch` — частичное обновление ресурса;
* `delete` — удаление ресурсов;
* `head` — получение заголовков (метаданных) ресурса без его содержимого;
* `options` — получение списка поддерживаемых опций и [CORS-политик](cors.md);
* `trace` — получение полного HTTP-запроса обратно, чтобы клиент мог проверить, не изменился ли запрос по пути;
* `query` (появился в OpenAPI 3.2) — выполнение сложных поисковых или фильтрующих операций.

Также в секции `path` определяется все, что ожидается получить в теле каждого запроса (блок `requestBody`), и как это должно быть валидировано (блок `schema`).

## Описание переиспользуемых объектов {#components}

При описании API часто возникает ситуация, когда нужно многократно описывать один и тот же объект. В OpenAPI есть специальная секция `components`, в которой можно описать все часто повторяющиеся структуры данных (`schemas`), а потом просто ссылаться на них. Пример схемы для объекта `User`:

```yaml
components:
  schemas:
    User:
      type: object
      properties:
        id:
          type: integer
        name:
          type: string
```

Имея такую схему, можно сослаться на нее в другой части спецификации с помощью ссылки: `$ref: '#/components/schemas/User'`.

Для создания составных типов объектов можно использовать ключи `allOf`, `oneOf` и `anyOf`. Разберем их особенности:

* `allOf` — объект сочетает все перечисленные схемы. Например, роль `Admin` наследует все права роли `Editor` и добавляет свои (возможность блокировать пользователей):

  ```yaml
  Admin:
    allOf:
      - $ref: '#/components/schemas/Editor'
      - type: object
        properties:
          canBanUsers:
            type: boolean
  ```

* `oneOf` — объект должен иметь свойства только одной из перечисленных схем. Например, пользователь должен иметь роль `Admin`, `Editor` или `Viewer`:

  ```yaml
  User:
    oneOf:
      - $ref: '#/components/schemas/Admin'
      - $ref: '#/components/schemas/Editor'
      - $ref: '#/components/schemas/Viewer'
  ```

* `anyOf` — значение должно соответствовать хотя бы одной из перечисленных схем. Например, контактная информация может быть `email`, `phone` или сочетать оба способа:

  ```yaml
  Contact:
    anyOf:
      - type: object
        properties:
          email: { type: string, format: email }
        required: [email]
      - type: object
        properties:
          phone: { type: string, pattern: '^\+?[1-9]\d{1,14}$' }
        required: [phone]
  ```

## Безопасность и аутентификация {#security}

Основные вещи, связанные с безопасностью в OpenAPI, описываются в двух местах:

* `components/securitySchemes` — описание способов защиты (API-ключи, HTTP-аутентификация, [OpenID Connect](sso.md) и другие). На объекты из этого блока также можно ссылаться через `$ref` в других частях спецификации. Например, опишем метод аутентификации по API-ключу, который нужно передать в заголовке `X-API-Key`:

  ```yaml
  components:
    securitySchemes:
      api_key:
        type: apiKey
        name: X-API-Key
        in: header
  ```

* `security` — привязка способов защиты к конкретным методам, ко всему эндпоинту или ко всей спецификации.

  Чтобы назначить способ защиты на всю спецификацию, поместите `security` в корневую часть:

  ```yaml
  security:
    - api_key: []
  ```

  Чтобы назначить способ защиты на конкретный метод или путь, поместите `security` в блок `paths`. Например, на получение списка пользователей:

  ```yaml
  paths:
    /users:
      get:
        security:
          - api_key: []
  ```

В публичных API часто есть методы или эндпоинты, для которых защита не требуется. В таком случае можно передать в `security` пустой массив. Например, отключим защиту на эндпоинте `/login`:

```yaml
/login:
  post:
    security: []
```

## Сравнение версий {#versions}

С переходом со Swagger 2.0 на OpenAPI 3.0 и выше в спецификации произошли значительные изменения. Документация стала намного логичнее и понятнее, а функциональность API заметно расширилась. Рассмотрим основные изменения:

| Аспект | Swagger 2.0 | OpenAPI 3.0+ |
|--------|-------------|-------------|
| Адреса серверов | Блоки `host`, `basePath`, `schemes` | Секция `servers` |
| Тело HTTP-запроса | Описывается в параметрах объектов | Блок `requestBody` в описании запроса |
| Повторяющиеся компоненты | Блоки `definitions`, `securityDefinitions`, `parameters`, `responses` | Секция `components` |
| Безопасность | Ограниченные схемы | Поддержка всех популярных методов |
| Поддержка примеров | Один пример на поле или схему | Множество примеров с описаниями |
| Составные типы объектов | Нет | Да (ключи `allOf`, `oneOf` и `anyOf`) |

Кроме того, в OpenAPI 3.0+ появились дополнительные блоки и свойства:

* `components.callbacks` — поддержка асинхронных уведомлений;
* `webhooks` — поддержка вебхуков;
* `components.links` — возвращение в ответе дополнительных ссылок для пользователя;
* `in: cookie` — поддержка cookie в параметрах;
* `.parameters.style` — определяет, как значение параметра должно быть сериализовано;
* `.parameters.explode` — определяет, нужно ли разбивать сериализованный параметр на логические компоненты.

### Переход со Swagger 2.0 на OpenAPI 3.0+ {#migration}

Swagger 2.0 значительно уступает более поздним версиям спецификации, поэтому переход рекомендуется для любых API. Вы можете использовать автоконвертер (например, [swagger2openapi](https://github.com/dumildematos/swagger2openapi)), а затем провалидировать изменения. Кратко, по шагам переход выглядит так:

1. Заголовок `swagger: "2.0"` меняется на `openapi: <версия_спецификации>` (например, `openapi: 3.2.0`).
1. Содержимое `host`, `basePath`, `schemes` переносится в секцию `servers`.
1. Все переиспользуемые объекты переносятся в `components.schemas`.
1. Методы защиты из `securityDefinitions` переносятся в `components.securitySchemes`.
1. Параметры `parameters` переносятся в блок `requestBody`.
1. При необходимости постепенно внедряются новые функции (`examples`, `links`, `callbacks` и другие).

## Инструменты и экосистема {#tools}

Так как OpenAPI-спецификация является стандартом для большинства API, вокруг нее возникла обширная экосистема, в которой можно найти все необходимые инструменты. Рассмотрим основные задачи, которые возникают при разработке API, и инструменты, которые помогут их решить:

Задача | Примеры инструментов
-------|---------------------
Генерация SDK | <ul><li>[OpenAPI Generator](https://openapi-generator.tech/)</li><li>[Fern](https://buildwithfern.com/)</li><li>[Stainless](https://www.stainless.com/)</li></ul>
Красивая документация | <ul><li>[Redoc / Redocly](https://github.com/Redocly/redoc)</li><li>[Scalar](https://scalar.com/)</li><li>[Stoplight Elements](https://stoplight.io/open-source/elements)</li></ul>
Средство проверки документации | <ul><li>[Spectral](https://stoplight.io/open-source/spectral)</li><li>[Redocly CLI](https://github.com/Redocly/redocly-cli)</li></ul>
Тестирование | <ul><li>[Postman](https://www.postman.com/)</li><li>[Schemathesis](https://schemathesis.readthedocs.io/)</li><li>[Insomnia](https://insomnia.rest/)</li></ul>
Полноценная API-платформа | <ul><li>[Yandex API Gateway](https://yandex.cloud/ru-kz/services/api-gateway)</li><li>[Stoplight](https://stoplight.io/)</li></ul>

## Ограничения и альтернативы {#disadvantages}

OpenAPI Specification — это доминирующий стандарт для описания REST API, однако для других задач он может быть менее эффективен, предполагать использование дополнительных решений или быть вовсе бесполезным. Рассмотрим виды API, с которыми могут возникнуть проблемы:

* **Асинхронные API**: OpenAPI ориентирован на схему «запрос — ответ», но асинхронные API, такие как WebSocket, подразумевают непрерывный обмен сообщениями без четкой структуры. Спецификацию придется расширить, либо описание API получится неполным и интуитивно непонятным.

  Альтернатива — [AsyncAPI](https://www.asyncapi.com/en) — спецификация, которая ориентирована на события.

* **gRPC**:

  * в OpenAPI нет полноценной поддержки многопоточности и нескольких языков;
  * не позволяет получить высокую производительность, которая является одним из основных преимуществ gRPC;
  * построен вокруг структурированных форматов сообщений (JSON Schema, XML), тогда как gRPC использует бинарный Protobuf.

  Альтернатива — встроенные инструменты, такие как protoc, Buf, gRPC-Gateway, ConnectRPC.

* **GraphQL**: OpenAPI не умеет работать с гибкими запросами, которые лежат в основе API, подобных GraphQL.

  Альтернатива — [GraphQL SDL](https://graphql.org/learn/schema/).

## Работа с API в Yandex Cloud {#openapi-yc}

Yandex Cloud предлагает [Yandex API Gateway](https://yandex.cloud/ru-kz/services/api-gateway) — полностью управляемый сервис для разработки, развертывания, управления и обеспечения безопасности API-шлюзов. Среди основных возможностей сервиса:

* создание и изменение OpenAPI-спецификаций;
* автоматическое масштабирование сервера при увеличении количества запросов;
* возможность использовать домены сервиса при обращении к API;
* создание канареечных релизов (доступных определенным пользователям);
* интеграция с другими сервисами Yandex Cloud без необходимости писать код;
* защита шлюзов от DDoS-атак и ботов.

Подробнее о сервисе в [документации](../api-gateway/index.md).

#### Полезные материалы {#see-also}

* [Создание интерактивного приложения с использованием Yandex API Gateway и протокола WebSocket](https://yandex.cloud/ru-kz/blog/posts/2023/04/yandex-api-gateway-and-websocket)
* [Распределение нагрузки с помощью Yandex API Gateway и других инструментов балансировки](https://yandex.cloud/ru-kz/blog/posts/2024/04/api-gateway-or-yandex-alb)
* [Разграничение доступа к API с помощью Yandex API Gateway](https://yandex.cloud/ru-kz/blog/posts/2023/07/yandex-api-gateway-and-jwt-authorizer)