Files
EvoBGP/docs/openapi.yaml
T
Denozordec bae2d68803
CI / changes (push) Successful in 6s
CI / openapi (push) Successful in 22s
CI / go (push) Successful in 50s
CI / docker-web (deploy/docker/evobgp-web/Dockerfile, , evobgp-web) (push) Successful in 1m4s
CI / docker-web (deploy/docker/evobgp-web/Dockerfile, evobgp-all, evobgp-web-all) (push) Successful in 1m5s
CI / docker-bird (push) Has been skipped
CI / bird2 (push) Successful in 15s
CI / docker-go-prime (push) Successful in 24s
CI / docker-go (deploy/docker/evobgp-agent/Dockerfile, , evobgp-agent) (push) Successful in 1m1s
CI / docker-go (evobgp-all, 1, deploy/docker/gobinary/Dockerfile, , evobgp-all) (push) Successful in 2m7s
CI / docker-go (evobgp-api, 1, deploy/docker/gobinary/Dockerfile, , evobgp-api) (push) Successful in 1m22s
CI / docker-go (evobgp-deploy, 0, deploy/docker/gobinary/Dockerfile, , evobgp-deploy) (push) Successful in 1m26s
CI / docker-go (evobgp-ingest, 0, deploy/docker/gobinary/Dockerfile, , evobgp-ingest) (push) Successful in 1m23s
CI / docker-go (evobgp-node, 0, deploy/docker/gobinary/Dockerfile, , evobgp-node) (push) Successful in 1m6s
CI / docker-go (evobgp-render, 0, deploy/docker/gobinary/Dockerfile, , evobgp-render) (push) Successful in 1m28s
CI / docker-go (evobgp-scheduler, 0, deploy/docker/gobinary/Dockerfile, , evobgp-scheduler) (push) Successful in 1m21s
feat: add CSV import and export functionality for module entries. Implement endpoints for exporting and importing module entries in CSV format, supporting types AS_PREFIXES, DOMAINS, and IP_RANGES. Enhance UI with buttons for CSV operations, improving user experience in managing module data.
2026-04-06 18:58:52 +07:00

2510 lines
78 KiB
YAML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
openapi: 3.1.0
info:
title: EvoBGP Control Plane API
version: 0.1.0
description: |
REST API управления префиксами, модулями ingest, ревизиями конфигурации BIRD и задачами (async jobs).
**Соглашения:** префикс `/v1`; идентификаторы - UUID v7 или ULID (строки); время - ISO 8601 UTC.
Ошибки - `application/problem+json` ([RFC 9457](https://www.rfc-editor.org/rfc/rfc9457)).
Пагинация списков - `cursor` + `limit`; ответ содержит `items`, `next_cursor`, `has_more`.
**Роли** (матрица доступа): `viewer`, `editor`, `operator`, `node`. Нода использует отдельные пути и ключ с ролью `node`.
Заголовок `X-Tenant-Id` допускается только для супер-ролей (явный tenant); иначе tenant берётся из API-ключа.
license:
name: Proprietary
identifier: LicenseRef-Proprietary
servers:
- url: https://api.example.com
description: Базовый URL инсталляции (замените на свой)
tags:
- name: System
description: Liveness, readiness и метаданные сборки. Обычно без чувствительных данных; доступ может быть шире.
- name: Modules
description: Экземпляры модулей префиксов (AS, CDN, домены, статические IP-диапазоны) и вложенные записи. Чтение - viewer+; изменение - editor+.
- name: DoH profiles
description: Профили DNS-over-HTTPS для модулей типа домены. Секрет в ответах не возвращается.
- name: Communities
description: Справочник BGP community в скоупе tenant.
- name: Peers
description: BGP-пиры и политики; привязка к спикеру или ко всем спикерам.
- name: Speakers
description: Регистрация и метаданные экземпляров BIRD (master/replica/canary).
- name: Revisions
description: История ревизий конфигурации, снимки префиксов, превью и откат (часто асинхронно).
- name: Deploy
description: Применение ревизий на спикерах и опциональный reload BIRD. Требуется роль operator.
- name: Jobs
description: Асинхронные задачи; статус и отмена (best-effort).
- name: Node
description: "API для evobgp-node (бандлы ревизий и enrollment). Отдельный ключ или mTLS, роль node."
- name: Settings
description: Глобальные настройки и feature flags; изменение - только operator.
security:
- bearerAuth: []
externalDocs:
description: Черновик и контекст API
url: ./evobgp-api-sketches.md
components:
securitySchemes:
bearerAuth:
type: http
scheme: bearer
description: API-ключ в формате `Bearer <token>`. На edge может заменяться или дополняться mTLS.
parameters:
TenantId:
name: X-Tenant-Id
in: header
required: false
schema:
$ref: "#/components/schemas/ResourceId"
description: Явный tenant (только супер-роли). Без заголовка tenant определяется по ключу.
IdempotencyKey:
name: Idempotency-Key
in: header
required: false
schema:
type: string
maxLength: 256
description: Идемпотентность мутаций. Для `POST` apply и части refresh рекомендуется или обязателен по политике продукта.
Cursor:
name: cursor
in: query
schema:
type: string
description: Непрозрачный курсор из предыдущего ответа.
Limit:
name: limit
in: query
schema:
type: integer
minimum: 1
maximum: 500
default: 50
description: Размер страницы (по умолчанию 50).
ModuleId:
name: module_id
in: path
required: true
schema:
$ref: "#/components/schemas/ResourceId"
SpeakerId:
name: speaker_id
in: path
required: true
schema:
$ref: "#/components/schemas/ResourceId"
RevisionId:
name: revision_id
in: path
required: true
schema:
$ref: "#/components/schemas/ResourceId"
JobId:
name: job_id
in: path
required: true
schema:
$ref: "#/components/schemas/ResourceId"
PeerId:
name: id
in: path
required: true
schema:
$ref: "#/components/schemas/ResourceId"
DohProfileId:
name: id
in: path
required: true
schema:
$ref: "#/components/schemas/ResourceId"
CommunityId:
name: id
in: path
required: true
schema:
$ref: "#/components/schemas/ResourceId"
SourceId:
name: source_id
in: path
required: true
schema:
$ref: "#/components/schemas/ResourceId"
EntryId:
name: entry_id
in: path
required: true
schema:
$ref: "#/components/schemas/ResourceId"
RevisionA:
name: revision_a
in: path
required: true
schema:
$ref: "#/components/schemas/ResourceId"
RevisionB:
name: revision_b
in: path
required: true
schema:
$ref: "#/components/schemas/ResourceId"
ModuleTypeFilter:
name: type
in: query
schema:
$ref: "#/components/schemas/ModuleType"
ModuleEnabledFilter:
name: enabled
in: query
schema:
type: boolean
SpeakerFilter:
name: speaker_id
in: query
schema:
$ref: "#/components/schemas/ResourceId"
RevisionModuleFilter:
name: module_id
in: query
schema:
$ref: "#/components/schemas/ResourceId"
JobStatusFilter:
name: status
in: query
schema:
$ref: "#/components/schemas/JobStatus"
JobKindFilter:
name: kind
in: query
schema:
type: string
description: Фильтр по виду задачи; точный перечень расширяем.
responses:
Unauthorized:
description: Нет или невалидный Bearer-токен.
content:
application/problem+json:
schema:
$ref: "#/components/schemas/Problem"
Forbidden:
description: Недостаточно прав для операции.
content:
application/problem+json:
schema:
$ref: "#/components/schemas/Problem"
NotFound:
description: Ресурс не найден в скоупе tenant.
content:
application/problem+json:
schema:
$ref: "#/components/schemas/Problem"
Conflict:
description: Конфликт состояния (например, удаление DoH-профиля, который ещё используется).
content:
application/problem+json:
schema:
$ref: "#/components/schemas/Problem"
UnprocessableEntity:
description: Семантическая ошибка запроса или валидации полей.
content:
application/problem+json:
schema:
$ref: "#/components/schemas/Problem"
DefaultProblem:
description: Ошибка (см. тело Problem).
content:
application/problem+json:
schema:
$ref: "#/components/schemas/Problem"
schemas:
ResourceId:
type: string
description: UUID v7 или ULID.
pattern: "^[0-9A-Za-z_-]{20,36}$"
examples:
- 01JQXYZABCDEFGHIJKLMNOPQRS
Problem:
type: object
description: Problem Details (RFC 9457).
required:
- title
- status
properties:
type:
type: string
format: uri-reference
description: URI типа проблемы.
title:
type: string
status:
type: integer
detail:
type: string
instance:
type: string
format: uri-reference
errors:
type: array
items:
$ref: "#/components/schemas/FieldError"
additionalProperties: true
FieldError:
type: object
properties:
field:
type: string
description: Имя поля (или JSON Pointer).
pointer:
type: string
description: JSON Pointer к значению.
message:
type: string
additionalProperties: true
AsyncJobAccepted:
type: object
required:
- job_id
- status
properties:
job_id:
$ref: "#/components/schemas/ResourceId"
status:
type: string
enum: [queued]
description: Начальный статус задачи в очереди.
ModuleType:
type: string
enum:
- AS_PREFIXES
- CDN_CIDRS
- DOMAINS
- IP_RANGES
JobStatus:
type: string
description: Статус задачи; перечень может расширяться.
enum:
- queued
- running
- succeeded
- failed
- cancelled
ApplyStrategy:
type: string
description: Стратегия выбора спикеров для apply.
enum:
- all_speakers
Module:
type: object
required:
- id
- type
- name
- enabled
- priority
properties:
id:
$ref: "#/components/schemas/ResourceId"
type:
$ref: "#/components/schemas/ModuleType"
name:
type: string
enabled:
type: boolean
priority:
type: integer
doh_profile_id:
type: ["string", "null"]
refresh_interval_sec:
type: ["integer", "null"]
minimum: 0
cron_expr:
type: ["string", "null"]
default_community_id:
type: ["string", "null"]
additionalProperties: true
ModuleCreate:
type: object
required:
- type
- name
properties:
type:
$ref: "#/components/schemas/ModuleType"
name:
type: string
enabled:
type: boolean
default: true
priority:
type: integer
default: 0
doh_profile_id:
type: ["string", "null"]
refresh_interval_sec:
type: ["integer", "null"]
cron_expr:
type: ["string", "null"]
default_community_id:
type: ["string", "null"]
ModulePatch:
type: object
properties:
name:
type: string
enabled:
type: boolean
priority:
type: integer
doh_profile_id:
type: ["string", "null"]
refresh_interval_sec:
type: ["integer", "null"]
cron_expr:
type: ["string", "null"]
default_community_id:
type: ["string", "null"]
CdnSource:
type: object
required:
- id
- url
- source_kind
properties:
id:
$ref: "#/components/schemas/ResourceId"
url:
type: string
format: uri
source_kind:
type: string
description: Формат скачанного списка / парсер.
prefix_path:
type: string
description: Путь до поля с префиксами для source_kind=json (например data.items[].cidr).
community_id:
type: ["string", "null"]
refresh_interval_sec:
type: ["integer", "null"]
CdnSourceCreate:
type: object
required:
- url
- source_kind
properties:
url:
type: string
format: uri
source_kind:
type: string
prefix_path:
type: string
community_id:
type: ["string", "null"]
CdnSourcePatch:
type: object
properties:
url:
type: string
format: uri
source_kind:
type: string
prefix_path:
type: string
community_id:
type: ["string", "null"]
refresh_interval_sec:
type: ["integer", "null"]
CdnPreviewRequest:
type: object
required: [url, source_kind]
properties:
url:
type: string
format: uri
source_kind:
type: string
prefix_path:
type: string
CdnPreviewResponse:
type: object
required: [items, total, truncated, source_url]
properties:
items:
type: array
items:
type: string
total:
type: integer
truncated:
type: boolean
source_url:
type: string
AsEntry:
type: object
required:
- id
- asn
properties:
id:
$ref: "#/components/schemas/ResourceId"
asn:
type: integer
minimum: 1
maximum: 4294967295
community_id:
type: ["string", "null"]
additionalProperties: true
AsEntryCreate:
type: object
required:
- asn
properties:
asn:
type: integer
minimum: 1
maximum: 4294967295
community_id:
type: ["string", "null"]
additionalProperties: true
AsEntryPatch:
type: object
properties:
asn:
type: integer
minimum: 1
maximum: 4294967295
community_id:
type: ["string", "null"]
additionalProperties: true
DomainEntry:
type: object
required:
- id
- fqdn
properties:
id:
$ref: "#/components/schemas/ResourceId"
fqdn:
type: string
community_id:
type: ["string", "null"]
DomainEntryCreate:
type: object
required:
- fqdn
properties:
fqdn:
type: string
community_id:
type: ["string", "null"]
IpRangeEntry:
type: object
required:
- id
- prefix
- community_id
properties:
id:
$ref: "#/components/schemas/ResourceId"
prefix:
type: string
description: IPv4/IPv6 CIDR.
example: 203.0.113.0/24
community_id:
$ref: "#/components/schemas/ResourceId"
IpRangeEntryCreate:
type: object
required:
- prefix
- community_id
properties:
prefix:
type: string
community_id:
$ref: "#/components/schemas/ResourceId"
DohProfile:
type: object
required:
- id
properties:
id:
$ref: "#/components/schemas/ResourceId"
url:
type: string
format: uri
timeout_ms:
type: integer
vault_secret_ref:
type: ["string", "null"]
description: Ссылка на секрет в vault; сырое значение не отдаётся в GET.
additionalProperties: true
DohProfileCreate:
type: object
required:
- url
properties:
url:
type: string
format: uri
timeout_ms:
type: integer
vault_secret_ref:
type: ["string", "null"]
BgpCommunity:
type: object
required:
- id
properties:
id:
$ref: "#/components/schemas/ResourceId"
community:
type: string
description: Техническое значение BGP community (строка для BIRD, например 65001:120 или large JSON в value_json).
title:
type: string
description: Человекочитаемое название для UI и фильтров.
additionalProperties: true
BgpPeer:
type: object
required:
- id
properties:
id:
$ref: "#/components/schemas/ResourceId"
neighbor:
type: string
description: IP соседа.
remote_asn:
type: integer
bgp_speaker_id:
type: ["string", "null"]
description: "`null` - политика для всех спикеров."
policies_json:
type: string
description: >
JSON-объект (строка). Поля `local_ipv4`, `local_ipv6`, `local_asn` переопределяют
глобальные `bird_local_ipv4` / `bird_local_ipv6` / `bird_local_asn` тенанта.
Если эффективный локальный адрес или ASN пира отличается от дефолтов тенанта (`bird_local_*`),
в блок `protocol bgp … from bgp_template` добавляется строка `local … as …`.
additionalProperties: true
BgpSpeaker:
type: object
required:
- id
properties:
id:
$ref: "#/components/schemas/ResourceId"
role:
type: string
description: master, replica, canary и т.д.
endpoint:
type: string
last_applied_revision_id:
type: ["string", "null"]
additionalProperties: true
ConfigRevision:
type: object
required:
- id
properties:
id:
$ref: "#/components/schemas/ResourceId"
parent_revision_id:
type: ["string", "null"]
content_hash:
type: string
created_at:
type: string
format: date-time
additionalProperties: true
PrefixSnapshotItem:
type: object
description: >
Элемент материализованного снимка. Поле prefix обычно содержит CIDR;
для модулей AS_PREFIXES допускается ключ вида as:<номер_asn> (не CIDR).
additionalProperties: true
Job:
type: object
required:
- job_id
- kind
- status
- created_at
properties:
job_id:
$ref: "#/components/schemas/ResourceId"
kind:
type: string
status:
$ref: "#/components/schemas/JobStatus"
idempotency_key:
type: ["string", "null"]
created_at:
type: string
format: date-time
started_at:
type: ["string", "null"]
description: ISO 8601 UTC, если задача уже стартовала.
finished_at:
type: ["string", "null"]
description: ISO 8601 UTC по завершении.
error:
type: ["string", "null"]
meta:
type: object
additionalProperties: true
ApplyRequest:
type: object
properties:
revision_id:
$ref: "#/components/schemas/ResourceId"
strategy:
$ref: "#/components/schemas/ApplyStrategy"
dry_run:
type: boolean
default: false
VersionInfo:
type: object
properties:
api_version:
type: string
git_sha:
type: string
build_time:
type: string
format: date-time
additionalProperties: true
HealthStatus:
type: object
properties:
status:
type: string
example: ok
additionalProperties: true
ReadyStatus:
type: object
properties:
status:
type: string
example: ready
checks:
type: object
additionalProperties: true
additionalProperties: true
Settings:
type: object
description: |
KV настройки tenant/глобальные лимиты и feature flags.
Параметры BIRD (строки в `global_settings`, JSON-значения — обычно строка или число):
`bird_router_id`, `bird_local_ipv4`, `bird_local_ipv6`, `bird_local_asn`;
если задан `bird_bgp_source_ipv4`, он подставляется как BIRD `router id` (перекрывает `bird_router_id`).
Ключи `bird_bgp_source_ipv4` / `bird_bgp_source_ipv6` в сгенерированном BGP для пиров не используются (оставлены для совместимости API).
Шаблон BGP в конфиге: `local as <bird_local_asn>;` без локального IP.
properties:
bird_router_id:
type: string
description: BIRD `router id` (IPv4 dotted quad), если не задан `bird_bgp_source_ipv4`.
bird_local_ipv4:
type: string
bird_local_ipv6:
type: string
bird_local_asn:
type: integer
bird_bgp_source_ipv4:
type: string
description: |
Если задан — используется как BIRD `router id` (IPv4). В блоках `protocol bgp … from bgp_template` строка `source address` не генерируется.
bird_bgp_source_ipv6:
type: string
description: Зарезервировано; в текущей генерации BGP не используется.
additionalProperties: true
RevisionDiff:
type: object
description: |
Сравнение двух ревизий. Конкретный формат (JSON Patch, табличный diff и т.д.) задаётся реализацией - контракт может уточняться.
additionalProperties: true
NodeEnrollRequest:
type: object
description: Тело регистрации ноды; протокол обмена ключами уточняется отдельно.
properties:
public_key:
type: string
speaker_id:
$ref: "#/components/schemas/ResourceId"
additionalProperties: true
NodeEnrollResponse:
type: object
description: Подтверждение записи enrollment (метаданные спикера обновлены).
properties:
status:
type: string
example: enrolled
speaker_id:
$ref: "#/components/schemas/ResourceId"
tenant_id:
$ref: "#/components/schemas/ResourceId"
additionalProperties: true
DohProfilePatch:
type: object
properties:
url:
type: string
format: uri
timeout_ms:
type: integer
vault_secret_ref:
type: ["string", "null"]
BgpCommunityCreate:
type: object
required: [community]
properties:
community:
type: string
title:
type: string
additionalProperties: true
BgpCommunityPatch:
type: object
properties:
community:
type: string
title:
type: string
additionalProperties: true
BgpPeerCreate:
type: object
required: [neighbor, remote_asn]
properties:
neighbor:
type: string
remote_asn:
type: integer
bgp_speaker_id:
type: ["string", "null"]
additionalProperties: true
BgpPeerPatch:
type: object
properties:
neighbor:
type: string
remote_asn:
type: integer
bgp_speaker_id:
type: ["string", "null"]
additionalProperties: true
BgpSpeakerCreate:
type: object
required: [endpoint]
properties:
role:
type: string
endpoint:
type: string
additionalProperties: true
BgpSpeakerPatch:
type: object
properties:
role:
type: string
endpoint:
type: string
additionalProperties: true
LatestRevisionPointer:
type: object
required:
- revision_id
properties:
revision_id:
$ref: "#/components/schemas/ResourceId"
published_at:
type: string
format: date-time
paths:
/v1/health:
get:
tags: [System]
summary: Liveness
description: Проверка, что процесс API жив. Не обязана проверять БД или брокер.
operationId: getHealth
responses:
"200":
description: Процесс отвечает.
content:
application/json:
schema:
$ref: "#/components/schemas/HealthStatus"
default:
$ref: "#/components/responses/DefaultProblem"
/v1/ready:
get:
tags: [System]
summary: Readiness
description: Готовность к трафику (БД, брокер сообщений при reference-архитектуре и т.д.).
operationId: getReady
responses:
"200":
description: Сервис готов принимать запросы.
content:
application/json:
schema:
$ref: "#/components/schemas/ReadyStatus"
"503":
description: Не готов (зависимости недоступны).
content:
application/problem+json:
schema:
$ref: "#/components/schemas/Problem"
default:
$ref: "#/components/responses/DefaultProblem"
/v1/version:
get:
tags: [System]
summary: Версия сборки
description: Версия API и control-plane (`git_sha`, `build_time` и др.).
operationId: getVersion
responses:
"200":
description: Метаданные сборки.
content:
application/json:
schema:
$ref: "#/components/schemas/VersionInfo"
default:
$ref: "#/components/responses/DefaultProblem"
/v1/modules:
get:
tags: [Modules]
summary: Список модулей
description: Модули tenant с опциональными фильтрами по типу и флагу `enabled`.
operationId: listModules
parameters:
- $ref: "#/components/parameters/TenantId"
- $ref: "#/components/parameters/Cursor"
- $ref: "#/components/parameters/Limit"
- $ref: "#/components/parameters/ModuleTypeFilter"
- $ref: "#/components/parameters/ModuleEnabledFilter"
responses:
"200":
description: Страница модулей.
content:
application/json:
schema:
type: object
required: [items, has_more]
properties:
items:
type: array
items:
$ref: "#/components/schemas/Module"
next_cursor:
type: ["string", "null"]
has_more:
type: boolean
"401":
$ref: "#/components/responses/Unauthorized"
default:
$ref: "#/components/responses/DefaultProblem"
post:
tags: [Modules]
summary: Создать модуль
description: |
Создаёт экземпляр модуля. Поле `type` задаёт вид (`AS_PREFIXES`, `CDN_CIDRS`, `DOMAINS`, `IP_RANGES`).
`module_id` в других путях - идентификатор экземпляра, не имя типа.
operationId: createModule
parameters:
- $ref: "#/components/parameters/TenantId"
- $ref: "#/components/parameters/IdempotencyKey"
requestBody:
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/ModuleCreate"
responses:
"201":
description: Модуль создан.
content:
application/json:
schema:
$ref: "#/components/schemas/Module"
"401":
$ref: "#/components/responses/Unauthorized"
"403":
$ref: "#/components/responses/Forbidden"
"422":
$ref: "#/components/responses/UnprocessableEntity"
default:
$ref: "#/components/responses/DefaultProblem"
/v1/modules/{module_id}:
parameters:
- $ref: "#/components/parameters/TenantId"
- $ref: "#/components/parameters/ModuleId"
get:
tags: [Modules]
summary: Получить модуль
operationId: getModule
responses:
"200":
description: Успешно.
content:
application/json:
schema:
$ref: "#/components/schemas/Module"
"401":
$ref: "#/components/responses/Unauthorized"
"404":
$ref: "#/components/responses/NotFound"
default:
$ref: "#/components/responses/DefaultProblem"
patch:
tags: [Modules]
summary: Обновить модуль
description: Частичное обновление (расписание, DoH, приоритет, `enabled` и т.д.).
operationId: patchModule
parameters:
- $ref: "#/components/parameters/IdempotencyKey"
requestBody:
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/ModulePatch"
responses:
"200":
description: Успешно.
content:
application/json:
schema:
$ref: "#/components/schemas/Module"
"401":
$ref: "#/components/responses/Unauthorized"
"403":
$ref: "#/components/responses/Forbidden"
"404":
$ref: "#/components/responses/NotFound"
"422":
$ref: "#/components/responses/UnprocessableEntity"
default:
$ref: "#/components/responses/DefaultProblem"
delete:
tags: [Modules]
summary: Удалить модуль
description: Мягкое удаление или перевод в `enabled=false` - конкретное поведение задаётся реализацией.
operationId: deleteModule
parameters:
- $ref: "#/components/parameters/IdempotencyKey"
responses:
"204":
description: Удалено или деактивировано.
"401":
$ref: "#/components/responses/Unauthorized"
"403":
$ref: "#/components/responses/Forbidden"
"404":
$ref: "#/components/responses/NotFound"
default:
$ref: "#/components/responses/DefaultProblem"
/v1/modules/{module_id}/cdn-sources:
parameters:
- $ref: "#/components/parameters/TenantId"
- $ref: "#/components/parameters/ModuleId"
get:
tags: [Modules]
summary: Список CDN-источников
operationId: listCdnSources
parameters:
- $ref: "#/components/parameters/Cursor"
- $ref: "#/components/parameters/Limit"
responses:
"200":
description: Успешно.
content:
application/json:
schema:
type: object
required: [items, has_more]
properties:
items:
type: array
items:
$ref: "#/components/schemas/CdnSource"
next_cursor:
type: ["string", "null"]
has_more:
type: boolean
"401":
$ref: "#/components/responses/Unauthorized"
"404":
$ref: "#/components/responses/NotFound"
default:
$ref: "#/components/responses/DefaultProblem"
post:
tags: [Modules]
summary: Добавить CDN-источник
description: URL, `source_kind`, опционально `community_id`.
operationId: createCdnSource
parameters:
- $ref: "#/components/parameters/IdempotencyKey"
requestBody:
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/CdnSourceCreate"
responses:
"201":
description: Ресурс создан.
content:
application/json:
schema:
$ref: "#/components/schemas/CdnSource"
"401":
$ref: "#/components/responses/Unauthorized"
"403":
$ref: "#/components/responses/Forbidden"
"404":
$ref: "#/components/responses/NotFound"
"422":
$ref: "#/components/responses/UnprocessableEntity"
default:
$ref: "#/components/responses/DefaultProblem"
/v1/modules/{module_id}/cdn-sources/{source_id}:
parameters:
- $ref: "#/components/parameters/TenantId"
- $ref: "#/components/parameters/ModuleId"
- $ref: "#/components/parameters/SourceId"
patch:
tags: [Modules]
summary: Обновить CDN-источник
operationId: patchCdnSource
parameters:
- $ref: "#/components/parameters/IdempotencyKey"
requestBody:
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/CdnSourcePatch"
responses:
"200":
description: Успешно.
content:
application/json:
schema:
$ref: "#/components/schemas/CdnSource"
"401":
$ref: "#/components/responses/Unauthorized"
"404":
$ref: "#/components/responses/NotFound"
default:
$ref: "#/components/responses/DefaultProblem"
delete:
tags: [Modules]
summary: Удалить CDN-источник
operationId: deleteCdnSource
parameters:
- $ref: "#/components/parameters/IdempotencyKey"
responses:
"204":
description: Удалено.
"401":
$ref: "#/components/responses/Unauthorized"
"404":
$ref: "#/components/responses/NotFound"
default:
$ref: "#/components/responses/DefaultProblem"
/v1/modules/{module_id}/as-entries:
parameters:
- $ref: "#/components/parameters/TenantId"
- $ref: "#/components/parameters/ModuleId"
get:
tags: [Modules]
summary: Список AS-записей
operationId: listAsEntries
parameters:
- $ref: "#/components/parameters/Cursor"
- $ref: "#/components/parameters/Limit"
responses:
"200":
description: Успешно.
content:
application/json:
schema:
type: object
required: [items, has_more]
properties:
items:
type: array
items:
$ref: "#/components/schemas/AsEntry"
next_cursor:
type: ["string", "null"]
has_more:
type: boolean
"404":
$ref: "#/components/responses/NotFound"
default:
$ref: "#/components/responses/DefaultProblem"
post:
tags: [Modules]
summary: Добавить AS-запись
operationId: createAsEntry
parameters:
- $ref: "#/components/parameters/IdempotencyKey"
requestBody:
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/AsEntryCreate"
responses:
"201":
description: Ресурс создан.
content:
application/json:
schema:
$ref: "#/components/schemas/AsEntry"
"404":
$ref: "#/components/responses/NotFound"
default:
$ref: "#/components/responses/DefaultProblem"
/v1/modules/{module_id}/as-entries/{entry_id}:
parameters:
- $ref: "#/components/parameters/TenantId"
- $ref: "#/components/parameters/ModuleId"
- $ref: "#/components/parameters/EntryId"
patch:
tags: [Modules]
summary: Обновить AS-запись
operationId: patchAsEntry
parameters:
- $ref: "#/components/parameters/IdempotencyKey"
requestBody:
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/AsEntryPatch"
responses:
"200":
description: Успешно.
content:
application/json:
schema:
$ref: "#/components/schemas/AsEntry"
"404":
$ref: "#/components/responses/NotFound"
default:
$ref: "#/components/responses/DefaultProblem"
delete:
tags: [Modules]
summary: Удалить AS-запись
operationId: deleteAsEntry
parameters:
- $ref: "#/components/parameters/IdempotencyKey"
responses:
"204":
description: Удалено.
"404":
$ref: "#/components/responses/NotFound"
default:
$ref: "#/components/responses/DefaultProblem"
/v1/modules/{module_id}/domain-entries:
parameters:
- $ref: "#/components/parameters/TenantId"
- $ref: "#/components/parameters/ModuleId"
get:
tags: [Modules]
summary: Список доменных записей
description: FQDN и привязка к community.
operationId: listDomainEntries
parameters:
- $ref: "#/components/parameters/Cursor"
- $ref: "#/components/parameters/Limit"
responses:
"200":
description: Успешно.
content:
application/json:
schema:
type: object
required: [items, has_more]
properties:
items:
type: array
items:
$ref: "#/components/schemas/DomainEntry"
next_cursor:
type: ["string", "null"]
has_more:
type: boolean
"404":
$ref: "#/components/responses/NotFound"
default:
$ref: "#/components/responses/DefaultProblem"
post:
tags: [Modules]
summary: Добавить доменную запись
operationId: createDomainEntry
parameters:
- $ref: "#/components/parameters/IdempotencyKey"
requestBody:
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/DomainEntryCreate"
responses:
"201":
description: Ресурс создан.
content:
application/json:
schema:
$ref: "#/components/schemas/DomainEntry"
"404":
$ref: "#/components/responses/NotFound"
default:
$ref: "#/components/responses/DefaultProblem"
/v1/modules/{module_id}/domain-entries/{entry_id}:
parameters:
- $ref: "#/components/parameters/TenantId"
- $ref: "#/components/parameters/ModuleId"
- $ref: "#/components/parameters/EntryId"
patch:
tags: [Modules]
summary: Обновить доменную запись
operationId: patchDomainEntry
parameters:
- $ref: "#/components/parameters/IdempotencyKey"
requestBody:
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/DomainEntryCreate"
responses:
"200":
description: Успешно.
content:
application/json:
schema:
$ref: "#/components/schemas/DomainEntry"
"404":
$ref: "#/components/responses/NotFound"
default:
$ref: "#/components/responses/DefaultProblem"
delete:
tags: [Modules]
summary: Удалить доменную запись
operationId: deleteDomainEntry
parameters:
- $ref: "#/components/parameters/IdempotencyKey"
responses:
"204":
description: Удалено.
"404":
$ref: "#/components/responses/NotFound"
default:
$ref: "#/components/responses/DefaultProblem"
/v1/modules/{module_id}/ip-range-entries:
parameters:
- $ref: "#/components/parameters/TenantId"
- $ref: "#/components/parameters/ModuleId"
get:
tags: [Modules]
summary: Список IP-диапазонов
description: "Только для модулей с типом IP_RANGES (статические CIDR и community_id)."
operationId: listIpRangeEntries
parameters:
- $ref: "#/components/parameters/Cursor"
- $ref: "#/components/parameters/Limit"
responses:
"200":
description: Успешно.
content:
application/json:
schema:
type: object
required: [items, has_more]
properties:
items:
type: array
items:
$ref: "#/components/schemas/IpRangeEntry"
next_cursor:
type: ["string", "null"]
has_more:
type: boolean
"404":
$ref: "#/components/responses/NotFound"
default:
$ref: "#/components/responses/DefaultProblem"
post:
tags: [Modules]
summary: Добавить IP-диапазон
operationId: createIpRangeEntry
parameters:
- $ref: "#/components/parameters/IdempotencyKey"
requestBody:
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/IpRangeEntryCreate"
responses:
"201":
description: Ресурс создан.
content:
application/json:
schema:
$ref: "#/components/schemas/IpRangeEntry"
"404":
$ref: "#/components/responses/NotFound"
default:
$ref: "#/components/responses/DefaultProblem"
/v1/modules/{module_id}/ip-range-entries/{entry_id}:
parameters:
- $ref: "#/components/parameters/TenantId"
- $ref: "#/components/parameters/ModuleId"
- $ref: "#/components/parameters/EntryId"
patch:
tags: [Modules]
summary: Обновить IP-диапазон
operationId: patchIpRangeEntry
parameters:
- $ref: "#/components/parameters/IdempotencyKey"
requestBody:
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/IpRangeEntryCreate"
responses:
"200":
description: Успешно.
content:
application/json:
schema:
$ref: "#/components/schemas/IpRangeEntry"
"404":
$ref: "#/components/responses/NotFound"
default:
$ref: "#/components/responses/DefaultProblem"
delete:
tags: [Modules]
summary: Удалить IP-диапазон
operationId: deleteIpRangeEntry
parameters:
- $ref: "#/components/parameters/IdempotencyKey"
responses:
"204":
description: Удалено.
"404":
$ref: "#/components/responses/NotFound"
default:
$ref: "#/components/responses/DefaultProblem"
/v1/modules/{module_id}/refresh:
parameters:
- $ref: "#/components/parameters/TenantId"
- $ref: "#/components/parameters/ModuleId"
post:
tags: [Modules]
summary: Запустить ingest
description: |
Запуск обновления данных модуля (CDN / DoH / AS в зависимости от типа).
Итоговая ревизия и фрагменты BIRD строятся **по всем включённым модулям тенанта**:
обновляемый модуль пересчитывается заново, остальные — по текущему состоянию в БД/источниках,
так что префиксы ASN, CDN, IP и т.д. суммируются в одном конфиге.
Для `IP_RANGES` данные обычно только в БД: сервер может вернуть **204** (no-op) или **400**, если refresh не поддерживается - поведение фиксируется в реализации.
Рекомендуется передавать `Idempotency-Key`.
operationId: postModuleRefresh
parameters:
- $ref: "#/components/parameters/IdempotencyKey"
responses:
"202":
description: Задача поставлена в очередь.
headers:
Location:
description: URL задачи `/v1/jobs/{job_id}`
schema:
type: string
content:
application/json:
schema:
$ref: "#/components/schemas/AsyncJobAccepted"
"204":
description: Нет операции (например модуль `IP_RANGES` и no-op).
"400":
description: Тип модуля не поддерживает refresh.
content:
application/problem+json:
schema:
$ref: "#/components/schemas/Problem"
"401":
$ref: "#/components/responses/Unauthorized"
"404":
$ref: "#/components/responses/NotFound"
default:
$ref: "#/components/responses/DefaultProblem"
/v1/modules/{module_id}/entries.csv:
parameters:
- $ref: "#/components/parameters/TenantId"
- $ref: "#/components/parameters/ModuleId"
get:
tags: [Modules]
summary: Экспорт записей модуля в CSV
description: |
Доступно для типов модулей `AS_PREFIXES`, `DOMAINS`, `IP_RANGES`.
Возвращает CSV с колонками:
- AS: `asn,community`
- Домены: `domain,community`
- IP ranges: `ipRange,community`
operationId: exportModuleEntriesCsv
responses:
"200":
description: CSV-файл записей модуля.
content:
text/csv:
schema:
type: string
"404":
$ref: "#/components/responses/NotFound"
"422":
$ref: "#/components/responses/UnprocessableEntity"
default:
$ref: "#/components/responses/DefaultProblem"
post:
tags: [Modules]
summary: Импорт записей модуля из CSV
description: |
Импортирует CSV в модуль типов `AS_PREFIXES`, `DOMAINS`, `IP_RANGES`.
Поддерживаемые заголовки:
- `asn,community`
- `domain,community`
- `ipRange,community`
В поле `community` можно передавать либо ID community, либо её значение.
operationId: importModuleEntriesCsv
parameters:
- $ref: "#/components/parameters/IdempotencyKey"
requestBody:
required: true
content:
text/csv:
schema:
type: string
responses:
"200":
description: Импорт завершён.
content:
application/json:
schema:
type: object
required: [imported, module_type]
properties:
imported:
type: integer
minimum: 0
module_type:
type: string
"404":
$ref: "#/components/responses/NotFound"
"422":
$ref: "#/components/responses/UnprocessableEntity"
default:
$ref: "#/components/responses/DefaultProblem"
/v1/doh-profiles:
get:
tags: [DoH profiles]
summary: Список DoH-профилей
operationId: listDohProfiles
parameters:
- $ref: "#/components/parameters/TenantId"
- $ref: "#/components/parameters/Cursor"
- $ref: "#/components/parameters/Limit"
responses:
"200":
description: Успешно.
content:
application/json:
schema:
type: object
required: [items, has_more]
properties:
items:
type: array
items:
$ref: "#/components/schemas/DohProfile"
next_cursor:
type: ["string", "null"]
has_more:
type: boolean
default:
$ref: "#/components/responses/DefaultProblem"
post:
tags: [DoH profiles]
summary: Создать DoH-профиль
description: URL и таймауты; секрет - через vault id или отдельный вызов установки секрета.
operationId: createDohProfile
parameters:
- $ref: "#/components/parameters/TenantId"
- $ref: "#/components/parameters/IdempotencyKey"
requestBody:
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/DohProfileCreate"
responses:
"201":
description: Ресурс создан.
content:
application/json:
schema:
$ref: "#/components/schemas/DohProfile"
"422":
$ref: "#/components/responses/UnprocessableEntity"
default:
$ref: "#/components/responses/DefaultProblem"
/v1/modules/{module_id}/cdn-sources/preview:
parameters:
- $ref: "#/components/parameters/TenantId"
- $ref: "#/components/parameters/ModuleId"
post:
tags: [Modules]
summary: Предпросмотр префиксов из CDN-источника
description: >
Загружает URL, парсит как plaintext или json и возвращает список извлечённых префиксов (до 100 записей).
operationId: previewCdnSource
requestBody:
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/CdnPreviewRequest"
responses:
"200":
description: Успешно.
content:
application/json:
schema:
$ref: "#/components/schemas/CdnPreviewResponse"
"401":
$ref: "#/components/responses/Unauthorized"
"403":
$ref: "#/components/responses/Forbidden"
"404":
$ref: "#/components/responses/NotFound"
"422":
$ref: "#/components/responses/UnprocessableEntity"
default:
$ref: "#/components/responses/DefaultProblem"
/v1/doh-profiles/{id}:
parameters:
- $ref: "#/components/parameters/TenantId"
- $ref: "#/components/parameters/DohProfileId"
get:
tags: [DoH profiles]
summary: Получить DoH-профиль
description: Секрет в ответе не возвращается.
operationId: getDohProfile
responses:
"200":
description: Успешно.
content:
application/json:
schema:
$ref: "#/components/schemas/DohProfile"
"404":
$ref: "#/components/responses/NotFound"
default:
$ref: "#/components/responses/DefaultProblem"
patch:
tags: [DoH profiles]
summary: Обновить DoH-профиль
operationId: patchDohProfile
parameters:
- $ref: "#/components/parameters/IdempotencyKey"
requestBody:
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/DohProfilePatch"
responses:
"200":
description: Успешно.
content:
application/json:
schema:
$ref: "#/components/schemas/DohProfile"
"404":
$ref: "#/components/responses/NotFound"
default:
$ref: "#/components/responses/DefaultProblem"
delete:
tags: [DoH profiles]
summary: Удалить DoH-профиль
description: Допустимо только если профиль не используется модулями.
operationId: deleteDohProfile
parameters:
- $ref: "#/components/parameters/IdempotencyKey"
responses:
"204":
description: Удалено.
"409":
$ref: "#/components/responses/Conflict"
"404":
$ref: "#/components/responses/NotFound"
default:
$ref: "#/components/responses/DefaultProblem"
/v1/communities:
get:
tags: [Communities]
summary: Список BGP community
operationId: listCommunities
parameters:
- $ref: "#/components/parameters/TenantId"
- $ref: "#/components/parameters/Cursor"
- $ref: "#/components/parameters/Limit"
responses:
"200":
description: Успешно.
content:
application/json:
schema:
type: object
required: [items, has_more]
properties:
items:
type: array
items:
$ref: "#/components/schemas/BgpCommunity"
next_cursor:
type: ["string", "null"]
has_more:
type: boolean
default:
$ref: "#/components/responses/DefaultProblem"
post:
tags: [Communities]
summary: Создать community
operationId: createCommunity
parameters:
- $ref: "#/components/parameters/TenantId"
- $ref: "#/components/parameters/IdempotencyKey"
requestBody:
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/BgpCommunityCreate"
responses:
"201":
description: Ресурс создан.
content:
application/json:
schema:
$ref: "#/components/schemas/BgpCommunity"
default:
$ref: "#/components/responses/DefaultProblem"
/v1/communities/{id}:
parameters:
- $ref: "#/components/parameters/TenantId"
- $ref: "#/components/parameters/CommunityId"
get:
tags: [Communities]
summary: Получить community
operationId: getCommunity
responses:
"200":
description: Успешно.
content:
application/json:
schema:
$ref: "#/components/schemas/BgpCommunity"
"404":
$ref: "#/components/responses/NotFound"
default:
$ref: "#/components/responses/DefaultProblem"
patch:
tags: [Communities]
summary: Обновить community
operationId: patchCommunity
parameters:
- $ref: "#/components/parameters/IdempotencyKey"
requestBody:
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/BgpCommunityPatch"
responses:
"200":
description: Успешно.
content:
application/json:
schema:
$ref: "#/components/schemas/BgpCommunity"
"404":
$ref: "#/components/responses/NotFound"
default:
$ref: "#/components/responses/DefaultProblem"
delete:
tags: [Communities]
summary: Удалить community
description: Только при отсутствии ссылок из других сущностей.
operationId: deleteCommunity
parameters:
- $ref: "#/components/parameters/IdempotencyKey"
responses:
"204":
description: Удалено.
"409":
$ref: "#/components/responses/Conflict"
"404":
$ref: "#/components/responses/NotFound"
default:
$ref: "#/components/responses/DefaultProblem"
/v1/peers:
get:
tags: [Peers]
summary: Список пиров
operationId: listPeers
parameters:
- $ref: "#/components/parameters/TenantId"
- $ref: "#/components/parameters/Cursor"
- $ref: "#/components/parameters/Limit"
- $ref: "#/components/parameters/SpeakerFilter"
responses:
"200":
description: Успешно.
content:
application/json:
schema:
type: object
required: [items, has_more]
properties:
items:
type: array
items:
$ref: "#/components/schemas/BgpPeer"
next_cursor:
type: ["string", "null"]
has_more:
type: boolean
default:
$ref: "#/components/responses/DefaultProblem"
post:
tags: [Peers]
summary: Создать пира
operationId: createPeer
parameters:
- $ref: "#/components/parameters/TenantId"
- $ref: "#/components/parameters/IdempotencyKey"
requestBody:
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/BgpPeerCreate"
responses:
"201":
description: Ресурс создан.
content:
application/json:
schema:
$ref: "#/components/schemas/BgpPeer"
default:
$ref: "#/components/responses/DefaultProblem"
/v1/peers/{id}:
parameters:
- $ref: "#/components/parameters/TenantId"
- $ref: "#/components/parameters/PeerId"
get:
tags: [Peers]
summary: Получить пира
operationId: getPeer
responses:
"200":
description: Успешно.
content:
application/json:
schema:
$ref: "#/components/schemas/BgpPeer"
"404":
$ref: "#/components/responses/NotFound"
default:
$ref: "#/components/responses/DefaultProblem"
patch:
tags: [Peers]
summary: Обновить пира
description: >
Политики (`policies_json`: `local_ipv4`, `local_ipv6`, `local_asn`), neighbor, ASN,
привязка к `bgp_speaker_id` или `null` для всех спикеров.
operationId: patchPeer
parameters:
- $ref: "#/components/parameters/IdempotencyKey"
requestBody:
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/BgpPeerPatch"
responses:
"200":
description: Успешно.
content:
application/json:
schema:
$ref: "#/components/schemas/BgpPeer"
"404":
$ref: "#/components/responses/NotFound"
default:
$ref: "#/components/responses/DefaultProblem"
delete:
tags: [Peers]
summary: Удалить или отключить пира
operationId: deletePeer
parameters:
- $ref: "#/components/parameters/IdempotencyKey"
responses:
"204":
description: Удалено / отключено.
"404":
$ref: "#/components/responses/NotFound"
default:
$ref: "#/components/responses/DefaultProblem"
/v1/speakers:
get:
tags: [Speakers]
summary: Список спикеров
description: Master / replica, endpoint и связанные поля.
operationId: listSpeakers
parameters:
- $ref: "#/components/parameters/TenantId"
- $ref: "#/components/parameters/Cursor"
- $ref: "#/components/parameters/Limit"
responses:
"200":
description: Успешно.
content:
application/json:
schema:
type: object
required: [items, has_more]
properties:
items:
type: array
items:
$ref: "#/components/schemas/BgpSpeaker"
next_cursor:
type: ["string", "null"]
has_more:
type: boolean
default:
$ref: "#/components/responses/DefaultProblem"
post:
tags: [Speakers]
summary: Зарегистрировать спикер
description: Реплика, canary и т.д.
operationId: createSpeaker
parameters:
- $ref: "#/components/parameters/TenantId"
- $ref: "#/components/parameters/IdempotencyKey"
requestBody:
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/BgpSpeakerCreate"
responses:
"201":
description: Ресурс создан.
content:
application/json:
schema:
$ref: "#/components/schemas/BgpSpeaker"
default:
$ref: "#/components/responses/DefaultProblem"
/v1/speakers/{id}:
parameters:
- $ref: "#/components/parameters/TenantId"
- $ref: "#/components/parameters/PeerId"
get:
tags: [Speakers]
summary: Получить спикер
description: В т.ч. `last_applied_revision_id`.
operationId: getSpeaker
responses:
"200":
description: Успешно.
content:
application/json:
schema:
$ref: "#/components/schemas/BgpSpeaker"
"404":
$ref: "#/components/responses/NotFound"
default:
$ref: "#/components/responses/DefaultProblem"
patch:
tags: [Speakers]
summary: Обновить метаданные спикера
operationId: patchSpeaker
parameters:
- $ref: "#/components/parameters/IdempotencyKey"
requestBody:
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/BgpSpeakerPatch"
responses:
"200":
description: Успешно.
content:
application/json:
schema:
$ref: "#/components/schemas/BgpSpeaker"
"404":
$ref: "#/components/responses/NotFound"
default:
$ref: "#/components/responses/DefaultProblem"
/v1/revisions:
get:
tags: [Revisions]
summary: История ревизий
operationId: listRevisions
parameters:
- $ref: "#/components/parameters/TenantId"
- $ref: "#/components/parameters/Cursor"
- $ref: "#/components/parameters/Limit"
- $ref: "#/components/parameters/RevisionModuleFilter"
responses:
"200":
description: Список ревизий с cursor-пагинацией; опциональный фильтр `module_id`.
content:
application/json:
schema:
type: object
required: [items, has_more]
properties:
items:
type: array
items:
$ref: "#/components/schemas/ConfigRevision"
next_cursor:
type: ["string", "null"]
has_more:
type: boolean
default:
$ref: "#/components/responses/DefaultProblem"
/v1/revisions/{revision_id}:
parameters:
- $ref: "#/components/parameters/TenantId"
- $ref: "#/components/parameters/RevisionId"
get:
tags: [Revisions]
summary: Метаданные ревизии
description: Хэш, родитель, время, артефакты.
operationId: getRevision
responses:
"200":
description: Успешно.
content:
application/json:
schema:
$ref: "#/components/schemas/ConfigRevision"
"404":
$ref: "#/components/responses/NotFound"
default:
$ref: "#/components/responses/DefaultProblem"
/v1/revisions/{revision_id}/prefixes:
parameters:
- $ref: "#/components/parameters/TenantId"
- $ref: "#/components/parameters/RevisionId"
get:
tags: [Revisions]
summary: Снимок префиксов ревизии
operationId: getRevisionPrefixes
parameters:
- $ref: "#/components/parameters/Cursor"
- $ref: "#/components/parameters/Limit"
responses:
"200":
description: Успешно.
content:
application/json:
schema:
type: object
required: [items, has_more]
properties:
items:
type: array
items:
$ref: "#/components/schemas/PrefixSnapshotItem"
next_cursor:
type: ["string", "null"]
has_more:
type: boolean
"404":
$ref: "#/components/responses/NotFound"
default:
$ref: "#/components/responses/DefaultProblem"
/v1/revisions/{revision_id}/preview:
parameters:
- $ref: "#/components/parameters/TenantId"
- $ref: "#/components/parameters/RevisionId"
get:
tags: [Revisions]
summary: Превью фрагментов BIRD
description: Только чтение, без apply.
operationId: getRevisionPreview
responses:
"200":
description: Текст или структурированное представление - формат задаётся реализацией.
content:
application/json:
schema:
type: object
additionalProperties: true
text/plain:
schema:
type: string
"404":
$ref: "#/components/responses/NotFound"
default:
$ref: "#/components/responses/DefaultProblem"
/v1/revisions/{revision_id}/rollback:
parameters:
- $ref: "#/components/parameters/TenantId"
- $ref: "#/components/parameters/RevisionId"
post:
tags: [Revisions]
summary: Откат через новую ревизию
description: |
Создаёт **новую** ревизию с содержимым отката от указанной. Часто возвращает **202** с `Location` на задачу.
Рекомендуется `Idempotency-Key`.
operationId: postRevisionRollback
parameters:
- $ref: "#/components/parameters/IdempotencyKey"
responses:
"202":
description: Откат поставлен в очередь.
headers:
Location:
schema:
type: string
content:
application/json:
schema:
$ref: "#/components/schemas/AsyncJobAccepted"
"401":
$ref: "#/components/responses/Unauthorized"
"404":
$ref: "#/components/responses/NotFound"
default:
$ref: "#/components/responses/DefaultProblem"
/v1/revisions/{revision_a}/diff/{revision_b}:
parameters:
- $ref: "#/components/parameters/TenantId"
- $ref: "#/components/parameters/RevisionA"
- $ref: "#/components/parameters/RevisionB"
get:
tags: [Revisions]
summary: Сравнить две ревизии
description: Формат diff (JSON Patch, табличный и т.д.) определяется реализацией.
operationId: getRevisionDiff
responses:
"200":
description: Успешно.
content:
application/json:
schema:
$ref: "#/components/schemas/RevisionDiff"
"404":
$ref: "#/components/responses/NotFound"
default:
$ref: "#/components/responses/DefaultProblem"
/v1/apply:
post:
tags: [Deploy]
summary: Применить конфигурацию
description: |
Применить целевую ревизию на спикерах (политика по умолчанию или из тела).
Ответ **202** с `Location` на `/v1/jobs/{job_id}`. **Рекомендуется или обязателен** `Idempotency-Key` по политике продукта.
operationId: postApply
parameters:
- $ref: "#/components/parameters/TenantId"
- $ref: "#/components/parameters/IdempotencyKey"
requestBody:
required: false
content:
application/json:
schema:
$ref: "#/components/schemas/ApplyRequest"
responses:
"202":
description: Запрос принят, задача поставлена в очередь.
headers:
Location:
schema:
type: string
content:
application/json:
schema:
$ref: "#/components/schemas/AsyncJobAccepted"
"401":
$ref: "#/components/responses/Unauthorized"
"403":
$ref: "#/components/responses/Forbidden"
default:
$ref: "#/components/responses/DefaultProblem"
/v1/speakers/{id}/apply:
parameters:
- $ref: "#/components/parameters/TenantId"
- $ref: "#/components/parameters/PeerId"
post:
tags: [Deploy]
summary: Применить на одном спикере
description: Canary / точечный deploy. **202** + `Location` на job.
operationId: postSpeakerApply
parameters:
- $ref: "#/components/parameters/IdempotencyKey"
requestBody:
required: false
content:
application/json:
schema:
$ref: "#/components/schemas/ApplyRequest"
responses:
"202":
description: Запрос принят, задача поставлена в очередь.
headers:
Location:
schema:
type: string
content:
application/json:
schema:
$ref: "#/components/schemas/AsyncJobAccepted"
"403":
$ref: "#/components/responses/Forbidden"
"404":
$ref: "#/components/responses/NotFound"
default:
$ref: "#/components/responses/DefaultProblem"
/v1/bird/reload:
post:
tags: [Deploy]
summary: Мягкий reload BIRD
description: Опциональный явный reload политики, если отделён от apply; иначе может отсутствовать или быть частью apply.
operationId: postBirdReload
parameters:
- $ref: "#/components/parameters/TenantId"
- $ref: "#/components/parameters/IdempotencyKey"
responses:
"202":
description: Задача reload поставлена (если реализовано как async).
headers:
Location:
schema:
type: string
content:
application/json:
schema:
$ref: "#/components/schemas/AsyncJobAccepted"
"204":
description: Reload выполнен синхронно (если так реализовано).
"501":
description: Эндпоинт не используется в данной сборке.
content:
application/problem+json:
schema:
$ref: "#/components/schemas/Problem"
default:
$ref: "#/components/responses/DefaultProblem"
/v1/jobs:
get:
tags: [Jobs]
summary: Список задач
operationId: listJobs
parameters:
- $ref: "#/components/parameters/TenantId"
- $ref: "#/components/parameters/Cursor"
- $ref: "#/components/parameters/Limit"
- $ref: "#/components/parameters/JobStatusFilter"
- $ref: "#/components/parameters/JobKindFilter"
responses:
"200":
description: Успешно.
content:
application/json:
schema:
type: object
required: [items, has_more]
properties:
items:
type: array
items:
$ref: "#/components/schemas/Job"
next_cursor:
type: ["string", "null"]
has_more:
type: boolean
default:
$ref: "#/components/responses/DefaultProblem"
/v1/jobs/{job_id}:
parameters:
- $ref: "#/components/parameters/TenantId"
- $ref: "#/components/parameters/JobId"
get:
tags: [Jobs]
summary: Статус задачи
description: Прогресс, ошибка, связанные сущности в `meta`.
operationId: getJob
responses:
"200":
description: Успешно.
content:
application/json:
schema:
$ref: "#/components/schemas/Job"
"404":
$ref: "#/components/responses/NotFound"
default:
$ref: "#/components/responses/DefaultProblem"
/v1/jobs/{job_id}/cancel:
parameters:
- $ref: "#/components/parameters/TenantId"
- $ref: "#/components/parameters/JobId"
post:
tags: [Jobs]
summary: Запросить отмену задачи
description: Best-effort; гарантии зависят от вида задачи.
operationId: postJobCancel
parameters:
- $ref: "#/components/parameters/IdempotencyKey"
responses:
"202":
description: Запрос отмены принят.
content:
application/json:
schema:
$ref: "#/components/schemas/Job"
"404":
$ref: "#/components/responses/NotFound"
default:
$ref: "#/components/responses/DefaultProblem"
/v1/speakers/{speaker_id}/revisions/latest:
parameters:
- $ref: "#/components/parameters/SpeakerId"
get:
tags: [Node]
summary: Последняя опубликованная ревизия для ноды
description: Вызывается **evobgp-node** с ключом роли `node`.
operationId: getSpeakerLatestRevision
security:
- bearerAuth: []
responses:
"200":
description: Успешно.
content:
application/json:
schema:
$ref: "#/components/schemas/LatestRevisionPointer"
"404":
$ref: "#/components/responses/NotFound"
default:
$ref: "#/components/responses/DefaultProblem"
/v1/speakers/{speaker_id}/bundle/{revision_id}:
parameters:
- $ref: "#/components/parameters/SpeakerId"
- $ref: "#/components/parameters/RevisionId"
get:
tags: [Node]
summary: Скачать подписанный бандл
description: |
Архив с `manifest.json` и подписью (например Ed25519). Целостность по SHA-256 в манифесте.
`Content-Type` - `application/octet-stream` или multipart; детали - в реализации.
operationId: getSpeakerBundle
security:
- bearerAuth: []
responses:
"200":
description: Бинарное тело бандла.
headers:
Content-Disposition:
schema:
type: string
content:
application/octet-stream:
schema:
type: string
format: binary
"404":
$ref: "#/components/responses/NotFound"
default:
$ref: "#/components/responses/DefaultProblem"
/v1/nodes/enroll:
post:
tags: [Node]
summary: Регистрация ноды
description: Обмен ключами и привязка к `speaker_id`; детали протокола уточняются отдельно.
operationId: postNodeEnroll
security:
- bearerAuth: []
requestBody:
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/NodeEnrollRequest"
responses:
"200":
description: Enrollment записан (node_public_key и время в meta спикера при наличии ключа).
content:
application/json:
schema:
$ref: "#/components/schemas/NodeEnrollResponse"
"422":
$ref: "#/components/responses/UnprocessableEntity"
default:
$ref: "#/components/responses/DefaultProblem"
/v1/settings:
get:
tags: [Settings]
summary: Получить настройки
description: KV (лимиты CDN, feature flags и т.д.).
operationId: getSettings
parameters:
- $ref: "#/components/parameters/TenantId"
responses:
"200":
description: Успешно.
content:
application/json:
schema:
$ref: "#/components/schemas/Settings"
default:
$ref: "#/components/responses/DefaultProblem"
patch:
tags: [Settings]
summary: Частично обновить настройки
description: Только роль **operator**.
operationId: patchSettings
parameters:
- $ref: "#/components/parameters/TenantId"
- $ref: "#/components/parameters/IdempotencyKey"
requestBody:
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/Settings"
responses:
"200":
description: Успешно.
content:
application/json:
schema:
$ref: "#/components/schemas/Settings"
"403":
$ref: "#/components/responses/Forbidden"
default:
$ref: "#/components/responses/DefaultProblem"