756 lines
26 KiB
YAML
756 lines
26 KiB
YAML
openapi: 3.0.3
|
||
info:
|
||
title: Workflows API
|
||
version: "1.0.0"
|
||
description: |
|
||
REST API сервиса **workflows-api** для работы с workflow (пайплайнами задач):
|
||
создание, получение, перезапуск задач, отмена запусков, приоритизация и получение
|
||
позиции в очереди.
|
||
|
||
### Технологии
|
||
- Язык: Go 1.24, HTTP-фреймворк **Fiber v2**.
|
||
- JSON-сериализация: `bytedance/sonic`.
|
||
- Хранилище: PostgreSQL (пул `pgx/v5`).
|
||
- Трейсинг: OpenTelemetry (`otelfiber`), включается переменной `TRACER_USE`.
|
||
|
||
### Группы маршрутов
|
||
Все обработчики регистрируются дважды — в двух группах с одинаковым набором путей
|
||
(см. `internal/server/server.go` и `internal/controller/http/v1/workflows/routes.go`):
|
||
|
||
- **`/api/v1/...`** — публичная группа. На префикс `/api` навешен middleware аутентификации
|
||
(`auth.AuthMiddleware`): требуется валидный JWT. Для запросов выставляется `is_internal=false`
|
||
и проверяется принадлежность пользователя к компании.
|
||
- **`/internal/v1/...`** — внутренняя группа (сервис-сервис) без аутентификации; трактуется как
|
||
доверенная (`is_internal=true`), проверки принадлежности к компании пропускаются.
|
||
|
||
Отдельно, вне групп и без авторизации, доступен health-check **`GET /ping`**.
|
||
|
||
В этом документе пути описаны относительно базового префикса группы `/api/v1`
|
||
(см. `servers`). Те же пути доступны и под `/internal/v1`.
|
||
|
||
### Аутентификация
|
||
Группа `/api` защищена middleware, который принимает один из двух токенов:
|
||
- **`Authorization: Bearer <JWT>`** — токен Sarex, подпись проверяется публичным ключом
|
||
из переменной `PUBLIC_KEY` (RS/PKIX). Из claims извлекаются `user_id`, `company_ids`,
|
||
`is_superuser`.
|
||
- **`Identity: Bearer <JWT>`** — токен Zitadel (проверяется без верификации подписи,
|
||
`ParseUnverified`); данные пользователя берутся из claim
|
||
`urn:zitadel:iam:user:metadata` (поля `id`, `company_ids`, `is_superuser`).
|
||
|
||
Если присутствует заголовок `Identity`, используется он; иначе — `Authorization`.
|
||
Часть операций (`prioritize`, `move_to_super_high_resources`) доступна только суперпользователю
|
||
(`is_superuser=true`).
|
||
|
||
### Пагинация
|
||
Метод `GET /workflows` поддерживает `limit` и `offset` (query-параметры, строки).
|
||
Ответ содержит `items`, а также `limit`, `offset`, `total`.
|
||
|
||
### Обработка ошибок
|
||
Ошибки возвращаются в JSON вида:
|
||
```json
|
||
{ "message": "human readable message", "error_code": "WF-0001" }
|
||
```
|
||
Коды (`internal/app_errors`): `WF-0000` (system, 500), `WF-0001` (not found, 404),
|
||
`WF-0002` (no auth, 401), `WF-0003` (no access), `WF-0004` (invalid, 400),
|
||
`WF-0005` (workflow config error / forbidden, 400/403).
|
||
HTTP-статус выбирается в `ErrorHandler` фреймворка по типу ошибки: 400 (ошибки парсинга/валидации/
|
||
конфигурации workflow), 401 (нет/некорректный токен), 403 (forbidden), 404 (не найдено), 500 (прочее).
|
||
|
||
### Замечания (расхождения кода и существующей схемы)
|
||
Документ приведён в соответствие с реальными маршрутами `routes.go`. Отличия от старого
|
||
`openapi_schema.yaml`:
|
||
- **Добавлены** отсутствовавшие маршруты: `POST /workflows/batch`, `GET /workflows/{workflow_id}/position`,
|
||
`POST /workflows/{workflow_id}/prioritize`, `POST /tasks/{task_id}/move_to_super_high_resources`.
|
||
- **Удалён** маршрут `GET /tasks-runs/{task_run_id}/logs` — в коде такого обработчика нет.
|
||
(Внимание: `workflows-frontend` этот эндпоинт вызывает — см. `workflows-frontend.ENDPOINTS.md`.)
|
||
- `POST /tasks-runs/{task_run_id}/cancel` фактически возвращает пустой объект `{}` (в коде
|
||
`c.JSON(&struct{}{})`), а не объект task_run.
|
||
- У задачи (`Task`) в модели есть поля `execution`, `services`, `layer`, `id`, `workflow_id`,
|
||
а у workflow — `document_id`, которые в старой схеме отсутствовали.
|
||
servers:
|
||
- url: 'http://localhost:8000/api/v1'
|
||
description: Локальный сервер (дефолт HTTP_HOST / docker-compose)
|
||
- url: 'http://workflows-service/api/v1'
|
||
description: Внутрикластерный сервис (preprod/production; stage — workflows-api-service:8000)
|
||
- url: 'https://stage-api.sarex.io/workflows/api/v1'
|
||
description: Публичный stage (через ingress, префикс /workflows)
|
||
- url: 'https://api.sarex.io/workflows/api/v1'
|
||
description: Публичный production (через ingress, префикс /workflows)
|
||
tags:
|
||
- name: workflows
|
||
description: Операции с workflow
|
||
- name: tasks
|
||
description: Операции с задачами workflow
|
||
- name: task-runs
|
||
description: Операции с запусками задач
|
||
- name: health
|
||
description: Проверка доступности сервиса
|
||
paths:
|
||
/ping:
|
||
get:
|
||
tags: [health]
|
||
summary: Health-check
|
||
description: >
|
||
Проверка готовности сервиса. Зарегистрирован вне групп `/api` и `/internal`,
|
||
без аутентификации (реальный путь — `/ping`, без префикса `/api/v1`).
|
||
operationId: Ping
|
||
responses:
|
||
'200':
|
||
description: Сервис готов
|
||
content:
|
||
application/json:
|
||
schema:
|
||
type: object
|
||
properties:
|
||
status:
|
||
type: string
|
||
example: ready
|
||
|
||
/companies/{company_id}/workflows:
|
||
post:
|
||
tags: [workflows]
|
||
summary: Создать workflow
|
||
description: >
|
||
Создаёт workflow для компании. Для группы `/api` пользователь должен принадлежать
|
||
компании `company_id`. Задачи не должны содержать поле `services` — используется
|
||
`service_requests`. Если у задачи не задан `backoff_limit`, он проставляется равным 5.
|
||
Поле `valid_until` должно быть в будущем.
|
||
operationId: CreateWorkflow
|
||
parameters:
|
||
- $ref: '#/components/parameters/AuthorizationHeader'
|
||
- name: company_id
|
||
in: path
|
||
required: true
|
||
description: Идентификатор компании
|
||
schema:
|
||
type: integer
|
||
example: 1
|
||
requestBody:
|
||
required: true
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/CreateWorkflowRequest'
|
||
responses:
|
||
'200':
|
||
description: Созданный workflow
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/Workflow'
|
||
'400':
|
||
$ref: '#/components/responses/BadRequest'
|
||
'401':
|
||
$ref: '#/components/responses/Unauthorized'
|
||
'403':
|
||
$ref: '#/components/responses/Forbidden'
|
||
'500':
|
||
$ref: '#/components/responses/InternalError'
|
||
|
||
/workflows:
|
||
get:
|
||
tags: [workflows]
|
||
summary: Список workflow по компаниям
|
||
description: >
|
||
Возвращает список workflow для указанных компаний. Параметр `company_ids` —
|
||
обязательная строка с идентификаторами через запятую. Для группы `/api`
|
||
не-суперпользователю возвращаются только его компании.
|
||
operationId: ListByCompanyID
|
||
parameters:
|
||
- $ref: '#/components/parameters/AuthorizationHeader'
|
||
- name: company_ids
|
||
in: query
|
||
required: true
|
||
description: Идентификаторы компаний через запятую
|
||
schema:
|
||
type: string
|
||
example: "1,2,3"
|
||
- name: limit
|
||
in: query
|
||
required: false
|
||
schema:
|
||
type: integer
|
||
example: 100
|
||
- name: offset
|
||
in: query
|
||
required: false
|
||
schema:
|
||
type: integer
|
||
example: 0
|
||
responses:
|
||
'200':
|
||
description: Список workflow
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/WorkflowsResponse'
|
||
'400':
|
||
$ref: '#/components/responses/BadRequest'
|
||
'401':
|
||
$ref: '#/components/responses/Unauthorized'
|
||
'403':
|
||
$ref: '#/components/responses/Forbidden'
|
||
'500':
|
||
$ref: '#/components/responses/InternalError'
|
||
|
||
/workflows/batch:
|
||
post:
|
||
tags: [workflows]
|
||
summary: Получить workflow пачкой
|
||
description: Возвращает workflow по списку идентификаторов.
|
||
operationId: GetWorkflows
|
||
parameters:
|
||
- $ref: '#/components/parameters/AuthorizationHeader'
|
||
requestBody:
|
||
required: true
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/GetBatchWorkflowsRequest'
|
||
responses:
|
||
'200':
|
||
description: Найденные workflow
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/WorkflowsBatchResponse'
|
||
'400':
|
||
$ref: '#/components/responses/BadRequest'
|
||
'401':
|
||
$ref: '#/components/responses/Unauthorized'
|
||
'403':
|
||
$ref: '#/components/responses/Forbidden'
|
||
'500':
|
||
$ref: '#/components/responses/InternalError'
|
||
|
||
/workflows/{id}:
|
||
get:
|
||
tags: [workflows]
|
||
summary: Получить workflow по ID
|
||
operationId: GetWorkflow
|
||
parameters:
|
||
- $ref: '#/components/parameters/AuthorizationHeader'
|
||
- name: id
|
||
in: path
|
||
required: true
|
||
description: UUID workflow
|
||
schema:
|
||
type: string
|
||
format: uuid
|
||
responses:
|
||
'200':
|
||
description: Workflow
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/Workflow'
|
||
'400':
|
||
$ref: '#/components/responses/BadRequest'
|
||
'401':
|
||
$ref: '#/components/responses/Unauthorized'
|
||
'403':
|
||
$ref: '#/components/responses/Forbidden'
|
||
'404':
|
||
$ref: '#/components/responses/NotFound'
|
||
'500':
|
||
$ref: '#/components/responses/InternalError'
|
||
|
||
/workflows/{workflows_ids}/state:
|
||
get:
|
||
tags: [workflows]
|
||
summary: Состояния нескольких workflow
|
||
description: >
|
||
Возвращает отображение `workflow_id -> state` для списка workflow.
|
||
`workflows_ids` — UUID через запятую.
|
||
operationId: GetStates
|
||
parameters:
|
||
- $ref: '#/components/parameters/AuthorizationHeader'
|
||
- name: workflows_ids
|
||
in: path
|
||
required: true
|
||
description: UUID workflow через запятую
|
||
schema:
|
||
type: string
|
||
example: "3fa85f64-5717-4562-b3fc-2c963f66afa6,4fa85f64-5717-4562-b3fc-2c963f66afa6"
|
||
responses:
|
||
'200':
|
||
description: Отображение id -> состояние
|
||
content:
|
||
application/json:
|
||
schema:
|
||
type: object
|
||
additionalProperties:
|
||
$ref: '#/components/schemas/CompletenessState'
|
||
example: { "3fa85f64-5717-4562-b3fc-2c963f66afa6": "done" }
|
||
'400':
|
||
$ref: '#/components/responses/BadRequest'
|
||
'401':
|
||
$ref: '#/components/responses/Unauthorized'
|
||
'403':
|
||
$ref: '#/components/responses/Forbidden'
|
||
'500':
|
||
$ref: '#/components/responses/InternalError'
|
||
|
||
/workflows/{workflow_id}/position:
|
||
get:
|
||
tags: [workflows]
|
||
summary: Позиция workflow в очереди
|
||
description: Возвращает позицию workflow в очереди на выполнение (ограничение 100).
|
||
operationId: GetWorkflowQueuePosition
|
||
parameters:
|
||
- $ref: '#/components/parameters/AuthorizationHeader'
|
||
- name: workflow_id
|
||
in: path
|
||
required: true
|
||
schema:
|
||
type: string
|
||
format: uuid
|
||
responses:
|
||
'200':
|
||
description: Позиция в очереди
|
||
content:
|
||
application/json:
|
||
schema:
|
||
type: object
|
||
properties:
|
||
position:
|
||
type: string
|
||
'400':
|
||
$ref: '#/components/responses/BadRequest'
|
||
'404':
|
||
$ref: '#/components/responses/NotFound'
|
||
'500':
|
||
$ref: '#/components/responses/InternalError'
|
||
|
||
/workflows/{workflow_id}/prioritize:
|
||
post:
|
||
tags: [workflows]
|
||
summary: Приоритизировать workflow
|
||
description: Повышает приоритет workflow. Доступно только суперпользователю.
|
||
operationId: PrioritizeWorkflow
|
||
parameters:
|
||
- $ref: '#/components/parameters/AuthorizationHeader'
|
||
- name: workflow_id
|
||
in: path
|
||
required: true
|
||
schema:
|
||
type: string
|
||
format: uuid
|
||
responses:
|
||
'204':
|
||
description: Успешно, тело отсутствует
|
||
'400':
|
||
$ref: '#/components/responses/BadRequest'
|
||
'401':
|
||
$ref: '#/components/responses/Unauthorized'
|
||
'403':
|
||
$ref: '#/components/responses/Forbidden'
|
||
'500':
|
||
$ref: '#/components/responses/InternalError'
|
||
|
||
/tasks/{task_id}/restart:
|
||
post:
|
||
tags: [tasks]
|
||
summary: Перезапустить задачу
|
||
description: >
|
||
Перезапускает задачу, опционально переопределяя `inputs`, `outputs`, `parameters`,
|
||
`valid_until`. Возвращает обновлённый workflow.
|
||
operationId: RestartTask
|
||
parameters:
|
||
- $ref: '#/components/parameters/AuthorizationHeader'
|
||
- name: task_id
|
||
in: path
|
||
required: true
|
||
schema:
|
||
type: string
|
||
format: uuid
|
||
requestBody:
|
||
required: false
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/RestartTaskRequest'
|
||
responses:
|
||
'200':
|
||
description: Обновлённый workflow
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/Workflow'
|
||
'400':
|
||
$ref: '#/components/responses/BadRequest'
|
||
'401':
|
||
$ref: '#/components/responses/Unauthorized'
|
||
'403':
|
||
$ref: '#/components/responses/Forbidden'
|
||
'404':
|
||
$ref: '#/components/responses/NotFound'
|
||
'500':
|
||
$ref: '#/components/responses/InternalError'
|
||
|
||
/tasks/{task_id}/move_to_super_high_resources:
|
||
post:
|
||
tags: [tasks]
|
||
summary: Перевести задачу на super-high-resources
|
||
description: Перемещает задачу на пул ресурсов super-high-resources. Только суперпользователь.
|
||
operationId: MoveTaskToSuperHighResources
|
||
parameters:
|
||
- $ref: '#/components/parameters/AuthorizationHeader'
|
||
- name: task_id
|
||
in: path
|
||
required: true
|
||
schema:
|
||
type: string
|
||
format: uuid
|
||
responses:
|
||
'204':
|
||
description: Успешно, тело отсутствует
|
||
'400':
|
||
$ref: '#/components/responses/BadRequest'
|
||
'401':
|
||
$ref: '#/components/responses/Unauthorized'
|
||
'403':
|
||
$ref: '#/components/responses/Forbidden'
|
||
'404':
|
||
$ref: '#/components/responses/NotFound'
|
||
'500':
|
||
$ref: '#/components/responses/InternalError'
|
||
|
||
/tasks-runs/{task_run_id}/cancel:
|
||
post:
|
||
tags: [task-runs]
|
||
summary: Отменить запуск задачи
|
||
description: Отменяет запуск задачи (task run). Возвращает пустой объект.
|
||
operationId: CancelTaskRun
|
||
parameters:
|
||
- $ref: '#/components/parameters/AuthorizationHeader'
|
||
- name: task_run_id
|
||
in: path
|
||
required: true
|
||
schema:
|
||
type: string
|
||
format: uuid
|
||
responses:
|
||
'200':
|
||
description: Успешно (пустой объект)
|
||
content:
|
||
application/json:
|
||
schema:
|
||
type: object
|
||
'400':
|
||
$ref: '#/components/responses/BadRequest'
|
||
'401':
|
||
$ref: '#/components/responses/Unauthorized'
|
||
'403':
|
||
$ref: '#/components/responses/Forbidden'
|
||
'404':
|
||
$ref: '#/components/responses/NotFound'
|
||
'500':
|
||
$ref: '#/components/responses/InternalError'
|
||
|
||
components:
|
||
parameters:
|
||
AuthorizationHeader:
|
||
name: Authorization
|
||
in: header
|
||
required: true
|
||
description: >
|
||
`Bearer <JWT>` — токен Sarex. Альтернативно можно передать заголовок
|
||
`Identity: Bearer <JWT>` (токен Zitadel). Не требуется для группы `/internal`.
|
||
schema:
|
||
type: string
|
||
example: "Bearer eyJhbGciOi..."
|
||
|
||
responses:
|
||
BadRequest:
|
||
description: Некорректный запрос (парсинг/валидация/конфигурация workflow)
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/AppError'
|
||
Unauthorized:
|
||
description: Не авторизован (нет/некорректный токен)
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/AppError'
|
||
Forbidden:
|
||
description: Доступ запрещён
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/AppError'
|
||
NotFound:
|
||
description: Ресурс не найден
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/AppError'
|
||
InternalError:
|
||
description: Внутренняя ошибка
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/AppError'
|
||
|
||
schemas:
|
||
AppError:
|
||
type: object
|
||
properties:
|
||
message:
|
||
type: string
|
||
example: "not found workflow"
|
||
error_code:
|
||
type: string
|
||
description: "Код ошибки: WF-0000..WF-0005"
|
||
example: "WF-0001"
|
||
|
||
CompletenessState:
|
||
type: string
|
||
description: Состояние workflow
|
||
enum: [done, running, error]
|
||
|
||
ExecutionState:
|
||
type: string
|
||
description: Состояние запуска задачи (task run)
|
||
enum: [pending, done, canceling, canceled, idle, running, error, lost]
|
||
|
||
Description:
|
||
type: object
|
||
description: Описание входа/выхода задачи (источник/приёмник данных)
|
||
required: [type, path]
|
||
properties:
|
||
type:
|
||
type: string
|
||
maxLength: 32
|
||
description: "Тип хранилища (валидация: google, local, s3, s3v2, srx-tmp, url, pdm)"
|
||
example: s3
|
||
path:
|
||
type: string
|
||
maxLength: 512
|
||
|
||
ServicePublicDescription:
|
||
type: object
|
||
properties:
|
||
type:
|
||
type: string
|
||
kind:
|
||
type: string
|
||
|
||
Resources:
|
||
type: object
|
||
properties:
|
||
cpu_limits:
|
||
type: string
|
||
memory_limits:
|
||
type: string
|
||
cpu_requests:
|
||
type: string
|
||
memory_requests:
|
||
type: string
|
||
|
||
Execution:
|
||
type: object
|
||
properties:
|
||
executor:
|
||
type: string
|
||
description: "Исполнитель задачи (допустимые: k8s, amqp)"
|
||
enum: [k8s, amqp]
|
||
resources:
|
||
$ref: '#/components/schemas/Resources'
|
||
|
||
Task:
|
||
type: object
|
||
properties:
|
||
id:
|
||
type: string
|
||
format: uuid
|
||
workflow_id:
|
||
type: string
|
||
format: uuid
|
||
slug:
|
||
type: string
|
||
docker_image:
|
||
type: string
|
||
backoff_limit:
|
||
type: integer
|
||
format: int32
|
||
description: "По умолчанию 5, если не задан"
|
||
inputs:
|
||
type: object
|
||
additionalProperties:
|
||
$ref: '#/components/schemas/Description'
|
||
outputs:
|
||
type: object
|
||
additionalProperties:
|
||
$ref: '#/components/schemas/Description'
|
||
parameters:
|
||
type: object
|
||
additionalProperties: true
|
||
service_requests:
|
||
type: array
|
||
items:
|
||
type: string
|
||
services:
|
||
type: array
|
||
items:
|
||
$ref: '#/components/schemas/ServicePublicDescription'
|
||
execution:
|
||
$ref: '#/components/schemas/Execution'
|
||
needs:
|
||
type: array
|
||
items:
|
||
type: string
|
||
layer:
|
||
type: integer
|
||
nullable: true
|
||
created_at:
|
||
type: string
|
||
format: date-time
|
||
updated_at:
|
||
type: string
|
||
format: date-time
|
||
|
||
TaskRun:
|
||
type: object
|
||
properties:
|
||
id:
|
||
type: string
|
||
format: uuid
|
||
task_id:
|
||
type: string
|
||
format: uuid
|
||
workflow_id:
|
||
type: string
|
||
format: uuid
|
||
state:
|
||
$ref: '#/components/schemas/ExecutionState'
|
||
reason:
|
||
type: string
|
||
nullable: true
|
||
progress:
|
||
type: integer
|
||
format: int32
|
||
nullable: true
|
||
total_time:
|
||
type: integer
|
||
format: int32
|
||
nullable: true
|
||
logs_paths:
|
||
type: array
|
||
items:
|
||
type: string
|
||
logs_storage:
|
||
type: string
|
||
nullable: true
|
||
logs_last_gathered:
|
||
type: string
|
||
format: date-time
|
||
nullable: true
|
||
created_at:
|
||
type: string
|
||
format: date-time
|
||
updated_at:
|
||
type: string
|
||
format: date-time
|
||
|
||
Workflow:
|
||
type: object
|
||
properties:
|
||
id:
|
||
type: string
|
||
format: uuid
|
||
company_id:
|
||
type: integer
|
||
state:
|
||
$ref: '#/components/schemas/CompletenessState'
|
||
name:
|
||
type: string
|
||
valid_until:
|
||
type: string
|
||
format: date-time
|
||
document_id:
|
||
type: integer
|
||
nullable: true
|
||
created_at:
|
||
type: string
|
||
format: date-time
|
||
updated_at:
|
||
type: string
|
||
format: date-time
|
||
tasks:
|
||
type: array
|
||
items:
|
||
$ref: '#/components/schemas/Task'
|
||
task_runs:
|
||
type: array
|
||
items:
|
||
$ref: '#/components/schemas/TaskRun'
|
||
|
||
CreateWorkflowRequest:
|
||
type: object
|
||
required: [name, valid_until]
|
||
properties:
|
||
name:
|
||
type: string
|
||
valid_until:
|
||
type: string
|
||
format: date-time
|
||
document_id:
|
||
type: integer
|
||
nullable: true
|
||
tasks:
|
||
type: array
|
||
items:
|
||
$ref: '#/components/schemas/Task'
|
||
|
||
RestartTaskRequest:
|
||
type: object
|
||
properties:
|
||
inputs:
|
||
type: object
|
||
additionalProperties:
|
||
$ref: '#/components/schemas/Description'
|
||
outputs:
|
||
type: object
|
||
additionalProperties:
|
||
$ref: '#/components/schemas/Description'
|
||
parameters:
|
||
type: object
|
||
additionalProperties: true
|
||
valid_until:
|
||
type: string
|
||
format: date-time
|
||
|
||
GetBatchWorkflowsRequest:
|
||
type: object
|
||
required: [workflows_ids]
|
||
properties:
|
||
workflows_ids:
|
||
type: array
|
||
items:
|
||
type: string
|
||
format: uuid
|
||
|
||
WorkflowsBatchResponse:
|
||
type: object
|
||
properties:
|
||
workflows:
|
||
type: array
|
||
items:
|
||
$ref: '#/components/schemas/Workflow'
|
||
|
||
WorkflowsResponse:
|
||
type: object
|
||
properties:
|
||
items:
|
||
type: array
|
||
items:
|
||
$ref: '#/components/schemas/Workflow'
|
||
limit:
|
||
type: integer
|
||
offset:
|
||
type: integer
|
||
total:
|
||
type: integer
|