Files
flowfish/api/openapi-spec.yaml
T

1667 lines
42 KiB
YAML

openapi: 3.0.3
info:
title: Flowfish Platform API
description: |
# Flowfish Platform API
REST API documentation for the eBPF-based Kubernetes/OpenShift application communication and dependency mapping platform.
## Key Features
- **Automatic Discovery** — Automatically detect inter-pod communications using eBPF
- **Real-Time Dependency Map** — Live visualization of service dependency graphs
- **Anomaly Detection** — Intelligent anomaly detection powered by statistical analysis
- **Multi-Cluster** — Manage multiple clusters from a single interface
- **AI Integration** — Dependency intelligence APIs for AI agents and CI/CD pipeline integration
- **Pod & Deployment Annotations** — Rich metadata enrichment including annotations merged from owning Deployments/StatefulSets
- **Import/Export** — Data import and export in multiple formats
## Authentication
The API supports two authentication methods:
1. **JWT (JSON Web Token)** — Send a POST request to `/api/v1/auth/login` with username and password, then include the returned `access_token` in subsequent requests via `Authorization: Bearer <token>` header.
2. **API Key** — Generate an API key from Settings > API Keys, then include it via `X-API-Key: <key>` header. Recommended for CI/CD pipelines and AI agent integrations.
## Rate Limiting
- **Authenticated Users**: 1,000 requests/hour
- **Unauthenticated**: 100 requests/hour
version: 1.0.0
contact:
name: Flowfish Team
email: support@flowfish.io
license:
name: MIT
url: https://opensource.org/licenses/MIT
servers:
- url: https://api.flowfish.io/api/v1
description: Production server
- url: https://staging.flowfish.io/api/v1
description: Staging server
- url: http://localhost:8000/api/v1
description: Development server
tags:
- name: Authentication
description: User authentication, JWT token management, and 2FA
- name: Users
description: User management and profile operations
- name: Clusters
description: Kubernetes/OpenShift cluster registration, connection, and management
- name: Analyses
description: Analysis wizard, lifecycle management, and run execution
- name: Workloads
description: Kubernetes workload inventory (Pod, Deployment, Service, StatefulSet) with labels and annotations
- name: Communications
description: Service-to-service communication records and dependency graphs
- name: AI Integration
description: Dependency intelligence APIs for AI agents and CI/CD pipeline integrations — dependency discovery, impact analysis, and cross-project dependency mapping
- name: Dependencies
description: Dependency map and graph queries
- name: Anomalies
description: Detected anomalies and outlier events
- name: Changes
description: Change detection and infrastructure drift tracking
- name: Baselines
description: Traffic baseline profiles
- name: Import/Export
description: Data import and export in CSV, JSON, and graph formats
- name: Settings
description: System configuration and enterprise settings
components:
securitySchemes:
BearerAuth:
type: http
scheme: bearer
bearerFormat: JWT
description: JWT token authorization header using the Bearer scheme
schemas:
Error:
type: object
required:
- error
- message
properties:
error:
type: string
example: "UNAUTHORIZED"
message:
type: string
example: "Invalid or expired token"
details:
type: object
nullable: true
Pagination:
type: object
properties:
page:
type: integer
minimum: 1
default: 1
page_size:
type: integer
minimum: 1
maximum: 100
default: 20
total_items:
type: integer
total_pages:
type: integer
User:
type: object
required:
- id
- username
- email
properties:
id:
type: integer
username:
type: string
email:
type: string
format: email
first_name:
type: string
nullable: true
last_name:
type: string
nullable: true
avatar_url:
type: string
format: uri
nullable: true
is_active:
type: boolean
roles:
type: array
items:
type: string
created_at:
type: string
format: date-time
Cluster:
type: object
required:
- id
- name
- cluster_type
properties:
id:
type: integer
name:
type: string
description:
type: string
nullable: true
cluster_type:
type: string
enum: [kubernetes, openshift]
api_url:
type: string
format: uri
is_active:
type: boolean
is_default:
type: boolean
kubernetes_version:
type: string
nullable: true
node_count:
type: integer
nullable: true
pod_count:
type: integer
nullable: true
namespace_count:
type: integer
nullable: true
health_status:
type: string
enum: [healthy, degraded, unhealthy, unknown]
last_sync_at:
type: string
format: date-time
nullable: true
created_at:
type: string
format: date-time
Namespace:
type: object
properties:
id:
type: integer
cluster_id:
type: integer
name:
type: string
uid:
type: string
labels:
type: object
additionalProperties:
type: string
status:
type: string
created_at:
type: string
format: date-time
Workload:
type: object
properties:
id:
type: integer
cluster_id:
type: integer
namespace_id:
type: integer
workload_type:
type: string
enum: [pod, deployment, statefulset, service]
name:
type: string
labels:
type: object
additionalProperties:
type: string
annotations:
type: object
additionalProperties:
type: string
ip_address:
type: string
format: ipv4
nullable: true
ports:
type: array
items:
type: object
properties:
port:
type: integer
protocol:
type: string
status:
type: string
first_seen:
type: string
format: date-time
last_seen:
type: string
format: date-time
is_active:
type: boolean
Communication:
type: object
properties:
id:
type: integer
cluster_id:
type: integer
source_namespace:
type: string
source_workload:
type: string
source_workload_type:
type: string
destination_namespace:
type: string
destination_workload:
type: string
destination_workload_type:
type: string
destination_ip:
type: string
destination_port:
type: integer
protocol:
type: string
first_seen:
type: string
format: date-time
last_seen:
type: string
format: date-time
request_count:
type: integer
request_rate_per_second:
type: number
format: float
avg_latency_ms:
type: number
format: float
risk_score:
type: integer
minimum: 0
maximum: 100
risk_level:
type: string
enum: [low, medium, high, critical]
is_cross_namespace:
type: boolean
is_external:
type: boolean
is_active:
type: boolean
Analysis:
type: object
properties:
id:
type: integer
name:
type: string
description:
type: string
cluster_id:
type: integer
scope_type:
type: string
enum: [cluster, namespace, deployment, pod, label]
scope_config:
type: object
gadget_modules:
type: array
items:
type: string
time_config:
type: object
output_config:
type: object
status:
type: string
enum: [draft, running, stopped, completed, failed]
created_at:
type: string
format: date-time
Anomaly:
type: object
properties:
id:
type: integer
cluster_id:
type: integer
anomaly_type:
type: string
severity:
type: string
enum: [low, medium, high, critical]
anomaly_score:
type: integer
minimum: 0
maximum: 100
title:
type: string
description:
type: string
affected_workloads:
type: array
items:
type: object
recommended_action:
type: string
status:
type: string
enum: [new, investigating, resolved, false_positive]
detected_at:
type: string
format: date-time
DependencyStreamCommunication:
type: object
properties:
protocol:
type: string
app_protocol:
type: string
service_type:
type: string
description: Detected service type (e.g. postgresql, kafka, redis)
service_category:
type: string
description: Service category (database, cache, message_broker, search_engine, etc.)
enum: [database, cache, message_broker, search_engine, service_discovery, identity, object_storage, observability, api_gateway, mail, dns, file_transfer, service]
is_critical:
type: boolean
description: Whether this dependency is classified as infrastructure-critical
port:
type: integer
request_count:
type: integer
error_rate_percent:
type: number
retransmit_count:
type: integer
avg_latency_ms:
type: number
DependencyHealth:
type: object
properties:
score:
type: integer
minimum: 0
maximum: 100
status:
type: string
enum: [healthy, degraded, unhealthy, critical]
error_rate_percent:
type: number
retransmit_rate_percent:
type: number
avg_latency_ms:
type: number
risk_factors:
type: array
items:
type: string
DependencyStreamPeer:
type: object
properties:
hop_count:
type: integer
pod_name:
type: string
namespace:
type: string
labels:
type: object
additionalProperties:
type: string
annotations:
type: object
additionalProperties:
type: string
ip:
type: string
owner_kind:
type: string
owner_name:
type: string
communication:
$ref: '#/components/schemas/DependencyStreamCommunication'
health:
$ref: '#/components/schemas/DependencyHealth'
CommunicationsDependenciesBatchRequest:
type: object
required:
- services
properties:
analysis_id:
type: string
cluster_id:
type: string
services:
type: array
items:
type: object
properties:
pod_name:
type: string
namespace:
type: string
owner_name:
type: string
label_key:
type: string
label_value:
type: string
annotation_key:
type: string
annotation_value:
type: string
ip:
type: string
depth:
type: integer
default: 1
include_communication_details:
type: boolean
default: true
CommunicationsDependenciesBatchResponse:
type: object
properties:
success:
type: boolean
service_count:
type: integer
results:
type: array
items:
type: object
additionalProperties: true
shared_dependencies:
type: array
items:
type: string
CommunicationsDependenciesDiffResponse:
type: object
properties:
success:
type: boolean
service:
type: object
analysis_before:
type: object
analysis_after:
type: object
added_dependencies:
type: array
items:
type: object
additionalProperties: true
removed_dependencies:
type: array
items:
type: object
additionalProperties: true
changed_dependencies:
type: array
items:
type: object
additionalProperties: true
unchanged_count:
type: integer
summary:
type: object
CommunicationsDependenciesImpactResponse:
type: object
properties:
success:
type: boolean
service:
type: object
dependencies:
type: object
properties:
downstream:
type: array
items:
type: object
additionalProperties: true
callers:
type: array
items:
type: object
additionalProperties: true
downstream_count:
type: integer
callers_count:
type: integer
impact_assessment:
type: object
properties:
risk_score:
type: integer
description: Risk score 0-100
risk_level:
type: string
enum: [low, medium, high, critical]
blast_radius:
type: integer
description: Total direct dependency count
critical_dependencies:
type: array
items:
type: string
description: List of critical service types (e.g. postgresql, redis)
recommendation:
type: string
enum: [proceed, caution, block]
suggested_actions:
type: array
items:
type: object
properties:
priority:
type: string
enum: [critical, high, medium, low]
action:
type: string
reason:
type: string
automatable:
type: boolean
change_type:
type: string
enum: [image_update, config_change, scale_change, delete]
DependencySummaryService:
type: object
properties:
name:
type: string
namespace:
type: string
kind:
type: string
annotations:
type: object
additionalProperties:
type: string
labels:
type: object
additionalProperties:
type: string
is_critical:
type: boolean
service_type:
type: string
port:
type: integer
DependencySummaryGroup:
type: object
properties:
total:
type: integer
critical_count:
type: integer
by_category:
type: object
additionalProperties:
type: array
items:
$ref: '#/components/schemas/DependencySummaryService'
MatchedService:
type: object
properties:
name:
type: string
namespace:
type: string
kind:
type: string
annotations:
type: object
additionalProperties:
type: string
labels:
type: object
additionalProperties:
type: string
downstream_count:
type: integer
callers_count:
type: integer
DependencySummaryResponse:
type: object
properties:
success:
type: boolean
analysis_ids:
type: array
items:
type: integer
multi_service:
type: boolean
description: True when multiple upstream pods matched (e.g. namespace-wide query)
service:
$ref: '#/components/schemas/DependencySummaryService'
matched_services:
type: array
description: Present when multi_service is true. Lists each matched upstream pod with its dependency counts.
items:
$ref: '#/components/schemas/MatchedService'
downstream:
$ref: '#/components/schemas/DependencySummaryGroup'
callers:
$ref: '#/components/schemas/DependencySummaryGroup'
error:
type: string
GraphData:
type: object
properties:
nodes:
type: array
items:
type: object
properties:
id:
type: string
type:
type: string
name:
type: string
namespace:
type: string
labels:
type: object
additionalProperties:
type: string
annotations:
type: object
additionalProperties:
type: string
metadata:
type: object
edges:
type: array
items:
type: object
properties:
id:
type: string
source:
type: string
target:
type: string
port:
type: integer
protocol:
type: string
metrics:
type: object
security:
- BearerAuth: []
paths:
/auth/login:
post:
tags:
- Authentication
summary: User login
description: Authenticate with username and password to obtain a JWT access token
security: []
requestBody:
required: true
content:
application/json:
schema:
type: object
required:
- username
- password
properties:
username:
type: string
password:
type: string
format: password
examples:
example1:
summary: Admin user
value:
username: "admin"
password: "admin123"
responses:
'200':
description: Login successful
content:
application/json:
schema:
type: object
properties:
access_token:
type: string
token_type:
type: string
example: "bearer"
expires_in:
type: integer
example: 3600
user:
$ref: '#/components/schemas/User'
'401':
description: Invalid username or password
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/auth/me:
get:
tags:
- Authentication
summary: Get current user info
description: Returns user information decoded from the JWT token
responses:
'200':
description: User details
content:
application/json:
schema:
$ref: '#/components/schemas/User'
'401':
description: Invalid or missing token
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/clusters:
get:
tags:
- Clusters
summary: List clusters
description: Lists all clusters the authenticated user has access to
parameters:
- name: page
in: query
schema:
type: integer
minimum: 1
default: 1
- name: page_size
in: query
schema:
type: integer
minimum: 1
maximum: 100
default: 20
- name: is_active
in: query
schema:
type: boolean
responses:
'200':
description: Cluster list
content:
application/json:
schema:
type: object
properties:
items:
type: array
items:
$ref: '#/components/schemas/Cluster'
pagination:
$ref: '#/components/schemas/Pagination'
post:
tags:
- Clusters
summary: Add new cluster
requestBody:
required: true
content:
application/json:
schema:
type: object
required:
- name
- cluster_type
- api_url
properties:
name:
type: string
description:
type: string
cluster_type:
type: string
enum: [kubernetes, openshift]
api_url:
type: string
format: uri
kubeconfig:
type: string
description: Base64 encoded kubeconfig
responses:
'201':
description: Cluster created successfully
content:
application/json:
schema:
$ref: '#/components/schemas/Cluster'
'400':
description: Invalid request
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/clusters/{cluster_id}:
get:
tags:
- Clusters
summary: Get cluster details
parameters:
- name: cluster_id
in: path
required: true
schema:
type: integer
responses:
'200':
description: Cluster details
content:
application/json:
schema:
$ref: '#/components/schemas/Cluster'
'404':
description: Cluster not found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
put:
tags:
- Clusters
summary: Update cluster
parameters:
- name: cluster_id
in: path
required: true
schema:
type: integer
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
name:
type: string
description:
type: string
is_active:
type: boolean
responses:
'200':
description: Cluster updated
content:
application/json:
schema:
$ref: '#/components/schemas/Cluster'
delete:
tags:
- Clusters
summary: Delete cluster
parameters:
- name: cluster_id
in: path
required: true
schema:
type: integer
responses:
'204':
description: Cluster deleted
'404':
description: Cluster not found
/analyses:
get:
tags:
- Analyses
summary: List analyses
parameters:
- name: cluster_id
in: query
schema:
type: integer
- name: status
in: query
schema:
type: string
enum: [draft, running, stopped, completed, failed]
responses:
'200':
description: Analysis list
content:
application/json:
schema:
type: object
properties:
items:
type: array
items:
$ref: '#/components/schemas/Analysis'
post:
tags:
- Analyses
summary: Create new analysis
description: Defines a new analysis using configuration from the wizard
requestBody:
required: true
content:
application/json:
schema:
type: object
required:
- name
- cluster_id
- scope_type
- scope_config
- gadget_modules
- time_config
- output_config
properties:
name:
type: string
description:
type: string
cluster_id:
type: integer
scope_type:
type: string
enum: [cluster, namespace, deployment, pod, label]
scope_config:
type: object
gadget_modules:
type: array
items:
type: string
time_config:
type: object
properties:
mode:
type: string
enum: [continuous, time_bound, scheduled, baseline]
duration_minutes:
type: integer
schedule:
type: string
output_config:
type: object
properties:
dashboards:
type: array
items:
type: string
llm_enabled:
type: boolean
alerts_enabled:
type: boolean
responses:
'201':
description: Analysis created
content:
application/json:
schema:
$ref: '#/components/schemas/Analysis'
/analyses/{analysis_id}/start:
post:
tags:
- Analyses
summary: Start analysis
parameters:
- name: analysis_id
in: path
required: true
schema:
type: integer
responses:
'200':
description: Analysis started
content:
application/json:
schema:
type: object
properties:
message:
type: string
run_id:
type: integer
/analyses/{analysis_id}/stop:
post:
tags:
- Analyses
summary: Stop analysis
parameters:
- name: analysis_id
in: path
required: true
schema:
type: integer
responses:
'200':
description: Analysis stopped
/workloads:
get:
tags:
- Workloads
summary: List workloads
parameters:
- name: cluster_id
in: query
required: true
schema:
type: integer
- name: namespace
in: query
schema:
type: string
- name: workload_type
in: query
schema:
type: string
enum: [pod, deployment, statefulset, service]
- name: is_active
in: query
schema:
type: boolean
default: true
responses:
'200':
description: Workload list
content:
application/json:
schema:
type: object
properties:
items:
type: array
items:
$ref: '#/components/schemas/Workload'
/communications:
get:
tags:
- Communications
summary: List communication records
parameters:
- name: cluster_id
in: query
required: true
schema:
type: integer
- name: namespace
in: query
schema:
type: string
- name: source_workload
in: query
schema:
type: string
- name: destination_workload
in: query
schema:
type: string
- name: risk_level
in: query
schema:
type: string
enum: [low, medium, high, critical]
- name: is_active
in: query
schema:
type: boolean
default: true
- name: from_time
in: query
schema:
type: string
format: date-time
- name: to_time
in: query
schema:
type: string
format: date-time
responses:
'200':
description: Communication records
content:
application/json:
schema:
type: object
properties:
items:
type: array
items:
$ref: '#/components/schemas/Communication'
total_count:
type: integer
/dependencies/graph:
get:
tags:
- Dependencies
summary: Get dependency map
description: Returns the dependency map as a graph with nodes and edges
parameters:
- name: cluster_id
in: query
description: Optional; used for filtering in multi-cluster scenarios
schema:
type: integer
- name: analysis_id
in: query
schema:
type: integer
- name: namespace
in: query
schema:
type: string
- name: depth
in: query
schema:
type: integer
default: 2
- name: search
in: query
schema:
type: string
minLength: 3
responses:
'200':
description: Graph data
content:
application/json:
schema:
$ref: '#/components/schemas/GraphData'
/communications/dependencies/stream:
get:
tags:
- AI Integration
- Communications
summary: Get pod dependencies as upstream/downstream
description: |
Query pod dependencies using any identifying information (annotation, label,
pod name, namespace, IP). The matched pod is treated as the upstream service.
Pods it communicates with are returned as downstream. Pods that connect to it
are returned as callers. Annotations include merged Deployment/StatefulSet metadata.
parameters:
- name: analysis_id
in: query
schema:
type: integer
- name: cluster_id
in: query
schema:
type: integer
- name: pod_name
in: query
schema:
type: string
- name: namespace
in: query
schema:
type: string
- name: owner_name
in: query
description: Deployment/StatefulSet/DaemonSet name
schema:
type: string
- name: annotation_key
in: query
schema:
type: string
- name: annotation_value
in: query
schema:
type: string
- name: label_key
in: query
schema:
type: string
- name: label_value
in: query
schema:
type: string
- name: ip
in: query
schema:
type: string
- name: depth
in: query
schema:
type: integer
minimum: 1
maximum: 5
default: 1
- name: format
in: query
schema:
type: string
enum: [json, mermaid, dot]
default: json
responses:
'200':
description: Upstream pod and its downstream dependencies
content:
application/json:
schema:
type: object
properties:
success:
type: boolean
count:
type: integer
results:
type: array
items:
type: object
properties:
upstream:
type: object
properties:
pod_name:
type: string
namespace:
type: string
labels:
type: object
annotations:
type: object
ip:
type: string
owner_kind:
type: string
owner_name:
type: string
downstream:
type: array
items:
$ref: '#/components/schemas/DependencyStreamPeer'
callers:
type: array
items:
$ref: '#/components/schemas/DependencyStreamPeer'
/communications/dependencies/batch:
post:
tags:
- AI Integration
- Communications
summary: Batch query dependencies for multiple services
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/CommunicationsDependenciesBatchRequest'
responses:
'200':
description: Batch dependency results
content:
application/json:
schema:
$ref: '#/components/schemas/CommunicationsDependenciesBatchResponse'
/communications/dependencies/diff:
get:
tags:
- AI Integration
- Communications
summary: Get dependency diff between two analyses
parameters:
- name: analysis_id_before
in: query
required: true
schema:
type: string
- name: analysis_id_after
in: query
required: true
schema:
type: string
- name: pod_name
in: query
schema:
type: string
- name: namespace
in: query
schema:
type: string
- name: owner_name
in: query
schema:
type: string
- name: cluster_id
in: query
schema:
type: integer
responses:
'200':
description: Dependency diff result
content:
application/json:
schema:
$ref: '#/components/schemas/CommunicationsDependenciesDiffResponse'
/communications/dependencies/impact:
get:
tags:
- AI Integration
- Communications
summary: Dependency impact analysis by change type
parameters:
- name: analysis_id
in: query
schema:
type: integer
- name: cluster_id
in: query
schema:
type: integer
- name: pod_name
in: query
schema:
type: string
- name: namespace
in: query
schema:
type: string
- name: owner_name
in: query
schema:
type: string
- name: annotation_key
in: query
schema:
type: string
- name: annotation_value
in: query
schema:
type: string
- name: label_key
in: query
schema:
type: string
- name: label_value
in: query
schema:
type: string
- name: ip
in: query
schema:
type: string
- name: depth
in: query
schema:
type: integer
minimum: 1
maximum: 5
default: 1
- name: change_type
in: query
schema:
type: string
enum: [image_update, config_change, scale_change, delete]
default: image_update
responses:
'200':
description: Impact analysis result
content:
application/json:
schema:
$ref: '#/components/schemas/CommunicationsDependenciesImpactResponse'
/communications/dependencies/summary:
get:
tags:
- AI Integration
summary: AI-agent-friendly dependency summary grouped by category
description: |
Returns a compact, grouped dependency summary for AI agents and CI/CD pipelines.
Dependencies are grouped by service_category. Annotations and labels are prominently
exposed for cross-project impact analysis (e.g. git-repo URLs, team info).
Requires at least one analysis_id and one search parameter.
parameters:
- name: analysis_ids
in: query
required: true
description: Analysis IDs (at least one required)
schema:
type: array
items:
type: integer
minItems: 1
- name: cluster_id
in: query
schema:
type: integer
- name: pod_name
in: query
schema:
type: string
- name: namespace
in: query
schema:
type: string
- name: owner_name
in: query
schema:
type: string
- name: annotation_key
in: query
schema:
type: string
- name: annotation_value
in: query
schema:
type: string
- name: label_key
in: query
schema:
type: string
- name: label_value
in: query
schema:
type: string
- name: ip
in: query
schema:
type: string
- name: depth
in: query
schema:
type: integer
minimum: 1
maximum: 5
default: 1
responses:
'200':
description: Grouped dependency summary
content:
application/json:
schema:
$ref: '#/components/schemas/DependencySummaryResponse'
/anomalies:
get:
tags:
- Anomalies
summary: List anomalies
parameters:
- name: cluster_id
in: query
schema:
type: integer
- name: severity
in: query
schema:
type: string
enum: [low, medium, high, critical]
- name: status
in: query
schema:
type: string
enum: [new, investigating, resolved, false_positive]
- name: from_date
in: query
schema:
type: string
format: date
responses:
'200':
description: Anomaly list
content:
application/json:
schema:
type: object
properties:
items:
type: array
items:
$ref: '#/components/schemas/Anomaly'
/export/csv:
get:
tags:
- Import/Export
summary: Export in CSV format
parameters:
- name: cluster_id
in: query
required: true
schema:
type: integer
- name: namespace
in: query
schema:
type: string
- name: from_time
in: query
schema:
type: string
format: date-time
- name: to_time
in: query
schema:
type: string
format: date-time
responses:
'200':
description: CSV file
content:
text/csv:
schema:
type: string
/export/graph-json:
get:
tags:
- Import/Export
summary: Export in Graph JSON format
parameters:
- name: cluster_id
in: query
required: true
schema:
type: integer
responses:
'200':
description: Graph JSON file
content:
application/json:
schema:
type: object
/import:
post:
tags:
- Import/Export
summary: Import data
requestBody:
required: true
content:
multipart/form-data:
schema:
type: object
required:
- file
- cluster_id
- import_mode
properties:
file:
type: string
format: binary
cluster_id:
type: integer
import_mode:
type: string
enum: [merge, overwrite, snapshot]
responses:
'202':
description: Import job started
content:
application/json:
schema:
type: object
properties:
job_id:
type: integer
message:
type: string