mirror of
https://github.com/wukko/cobalt.git
synced 2025-03-03 23:48:50 +01:00
Create OpenAPI specification schema
feat: Create OpenAPI Specification schema - Adds a structured OpenAPI 3.0 specification for the Cobalt API. - Provides a unified, standardized definition of endpoints, authentication, and request/response schemas. - Enables easy generation of server and client SDKs with OpenAPI tools. - Ensures better compliance with API documentation best practices. - Improves maintainability and facilitates integrations with third-party services.
This commit is contained in:
parent
b540e48ffb
commit
d59968bb6b
1 changed files with 477 additions and 0 deletions
477
docs/openapi-schema.yaml
Normal file
477
docs/openapi-schema.yaml
Normal file
|
@ -0,0 +1,477 @@
|
||||||
|
openapi: "3.0.3"
|
||||||
|
info:
|
||||||
|
title: "Imputnet Cobalt API"
|
||||||
|
description: >
|
||||||
|
OpenAPI specification for the Imputnet Cobalt API. This API provides endpoints
|
||||||
|
for retrieving content (such as videos or images) from various services and for
|
||||||
|
obtaining authentication tokens. Note: Official hosted instances (e.g.
|
||||||
|
"api.cobalt.tools") may enforce bot protection; self-hosting or obtaining
|
||||||
|
explicit access is recommended.
|
||||||
|
version: "1.0.0"
|
||||||
|
servers:
|
||||||
|
- url: "https://api.cobalt.tools"
|
||||||
|
description: "Example public API instance (may require permission)"
|
||||||
|
- url: "http://localhost:9000"
|
||||||
|
description: "Local instance for self-hosting (default port 9000)"
|
||||||
|
security:
|
||||||
|
- ApiKeyAuth: []
|
||||||
|
- BearerAuth: []
|
||||||
|
components:
|
||||||
|
securitySchemes:
|
||||||
|
ApiKeyAuth:
|
||||||
|
type: apiKey
|
||||||
|
in: header
|
||||||
|
name: Authorization
|
||||||
|
description: "API Key authentication via 'Authorization: Api-Key <API_TOKEN>'"
|
||||||
|
BearerAuth:
|
||||||
|
type: http
|
||||||
|
scheme: bearer
|
||||||
|
bearerFormat: JWT
|
||||||
|
description: "Bearer JWT authentication via 'Authorization: Bearer <JWT_TOKEN>' (obtained from the /session endpoint)"
|
||||||
|
schemas:
|
||||||
|
DownloadRequest:
|
||||||
|
type: object
|
||||||
|
required:
|
||||||
|
- url
|
||||||
|
description: "Request payload for content download. Must include a target URL and can specify optional parameters (quality, format, etc.)."
|
||||||
|
properties:
|
||||||
|
url:
|
||||||
|
type: string
|
||||||
|
format: uri
|
||||||
|
description: "The URL of the content to download (required)."
|
||||||
|
videoQuality:
|
||||||
|
type: string
|
||||||
|
enum: ["144", "240", "360", "480", "720", "1080", "1440", "2160", "4320", "max"]
|
||||||
|
default: "1080"
|
||||||
|
description: "Video resolution quality (e.g., '144', '720', '1080', up to '4320' or 'max')."
|
||||||
|
audioFormat:
|
||||||
|
type: string
|
||||||
|
enum: ["best", "mp3", "ogg", "wav", "opus"]
|
||||||
|
default: "mp3"
|
||||||
|
description: "Audio format for extraction or conversion."
|
||||||
|
audioBitrate:
|
||||||
|
type: string
|
||||||
|
enum: ["320", "256", "128", "96", "64", "8"]
|
||||||
|
default: "128"
|
||||||
|
description: "Audio bitrate in kbps for conversion; applies only when converting to audio."
|
||||||
|
filenameStyle:
|
||||||
|
type: string
|
||||||
|
enum: ["classic", "pretty", "basic", "nerdy"]
|
||||||
|
default: "classic"
|
||||||
|
description: "File naming style for the output file."
|
||||||
|
downloadMode:
|
||||||
|
type: string
|
||||||
|
enum: ["auto", "audio", "mute"]
|
||||||
|
default: "auto"
|
||||||
|
description: "Download mode: 'auto' (video with audio), 'audio' (audio-only), or 'mute' (video without audio)."
|
||||||
|
youtubeVideoCodec:
|
||||||
|
type: string
|
||||||
|
enum: ["h264", "av1", "vp9"]
|
||||||
|
default: "h264"
|
||||||
|
description: "Preferred video codec for YouTube downloads."
|
||||||
|
youtubeDubLang:
|
||||||
|
type: string
|
||||||
|
description: "Language code for dubbed audio on YouTube (if applicable), e.g. 'en', 'ru', 'ja', 'es-US'."
|
||||||
|
alwaysProxy:
|
||||||
|
type: boolean
|
||||||
|
default: false
|
||||||
|
description: "If true, forces all downloads to proxy through the server."
|
||||||
|
disableMetadata:
|
||||||
|
type: boolean
|
||||||
|
default: false
|
||||||
|
description: "If true, do not embed metadata (like title or artist tags) in the output file."
|
||||||
|
tiktokFullAudio:
|
||||||
|
type: boolean
|
||||||
|
default: false
|
||||||
|
description: "If true, download the original sound for a TikTok video when available."
|
||||||
|
tiktokH265:
|
||||||
|
type: boolean
|
||||||
|
default: false
|
||||||
|
description: "If true, allow H.265/HEVC video for TikTok (and Xiaohongshu) if available."
|
||||||
|
twitterGif:
|
||||||
|
type: boolean
|
||||||
|
default: true
|
||||||
|
description: "If true, convert Twitter 'GIFs' (video format) into actual .gif files."
|
||||||
|
youtubeHLS:
|
||||||
|
type: boolean
|
||||||
|
default: false
|
||||||
|
description: "If true, use HLS streaming for YouTube video/audio downloads when available."
|
||||||
|
RedirectResponse:
|
||||||
|
type: object
|
||||||
|
required:
|
||||||
|
- status
|
||||||
|
- url
|
||||||
|
- filename
|
||||||
|
description: "Response indicating the client should be redirected to an external URL for the content."
|
||||||
|
properties:
|
||||||
|
status:
|
||||||
|
type: string
|
||||||
|
enum: ["redirect"]
|
||||||
|
description: "Redirect status indicator."
|
||||||
|
url:
|
||||||
|
type: string
|
||||||
|
format: uri
|
||||||
|
description: "External URL to download the content directly."
|
||||||
|
filename:
|
||||||
|
type: string
|
||||||
|
description: "Suggested filename for the downloaded content."
|
||||||
|
TunnelResponse:
|
||||||
|
type: object
|
||||||
|
required:
|
||||||
|
- status
|
||||||
|
- url
|
||||||
|
- filename
|
||||||
|
description: "Response indicating the content is being proxied (tunneled) through the Cobalt server."
|
||||||
|
properties:
|
||||||
|
status:
|
||||||
|
type: string
|
||||||
|
enum: ["tunnel"]
|
||||||
|
description: "Tunnel status indicator."
|
||||||
|
url:
|
||||||
|
type: string
|
||||||
|
format: uri
|
||||||
|
description: "Cobalt tunnel URL to fetch the content via the server proxy."
|
||||||
|
filename:
|
||||||
|
type: string
|
||||||
|
description: "Suggested filename for the downloaded content."
|
||||||
|
PickerItem:
|
||||||
|
type: object
|
||||||
|
required:
|
||||||
|
- type
|
||||||
|
- url
|
||||||
|
description: "An individual media entry available for selection (in a picker response)."
|
||||||
|
properties:
|
||||||
|
type:
|
||||||
|
type: string
|
||||||
|
enum: ["photo", "video", "gif"]
|
||||||
|
description: "Type of media item (photo, video, or gif)."
|
||||||
|
url:
|
||||||
|
type: string
|
||||||
|
format: uri
|
||||||
|
description: "Direct URL of the media item."
|
||||||
|
thumb:
|
||||||
|
type: string
|
||||||
|
format: uri
|
||||||
|
description: "Thumbnail URL for the media (optional)."
|
||||||
|
PickerResponse:
|
||||||
|
type: object
|
||||||
|
required:
|
||||||
|
- status
|
||||||
|
- picker
|
||||||
|
description: "Response indicating multiple media items to choose from (e.g., an image slideshow)."
|
||||||
|
properties:
|
||||||
|
status:
|
||||||
|
type: string
|
||||||
|
enum: ["picker"]
|
||||||
|
description: "Picker status indicator."
|
||||||
|
audio:
|
||||||
|
type: string
|
||||||
|
format: uri
|
||||||
|
description: "URL to a background audio track (if the content has separate audio)."
|
||||||
|
audioFilename:
|
||||||
|
type: string
|
||||||
|
description: "Filename for the audio track, if provided."
|
||||||
|
picker:
|
||||||
|
type: array
|
||||||
|
description: "Array of media items available for selection."
|
||||||
|
items:
|
||||||
|
$ref: "#/components/schemas/PickerItem"
|
||||||
|
ErrorContext:
|
||||||
|
type: object
|
||||||
|
description: "Optional additional context for an error, providing extra details."
|
||||||
|
properties:
|
||||||
|
service:
|
||||||
|
type: string
|
||||||
|
description: "Service/source involved in the error (e.g., 'youtube')."
|
||||||
|
limit:
|
||||||
|
type: number
|
||||||
|
description: "Numeric limit related to the error (e.g., rate limit or duration limit)."
|
||||||
|
ErrorDetail:
|
||||||
|
type: object
|
||||||
|
required:
|
||||||
|
- code
|
||||||
|
description: "Error details object containing a code and optional context information."
|
||||||
|
properties:
|
||||||
|
code:
|
||||||
|
type: string
|
||||||
|
description: "Machine-readable error code explaining the reason."
|
||||||
|
context:
|
||||||
|
$ref: "#/components/schemas/ErrorContext"
|
||||||
|
ErrorResponse:
|
||||||
|
type: object
|
||||||
|
required:
|
||||||
|
- status
|
||||||
|
- error
|
||||||
|
description: "Response indicating an error occurred during the request."
|
||||||
|
properties:
|
||||||
|
status:
|
||||||
|
type: string
|
||||||
|
enum: ["error"]
|
||||||
|
description: "Error status indicator."
|
||||||
|
error:
|
||||||
|
$ref: "#/components/schemas/ErrorDetail"
|
||||||
|
ServerInfoResponse:
|
||||||
|
type: object
|
||||||
|
required:
|
||||||
|
- cobalt
|
||||||
|
- git
|
||||||
|
description: "Server status information, including Cobalt instance details and git info."
|
||||||
|
properties:
|
||||||
|
cobalt:
|
||||||
|
type: object
|
||||||
|
description: "Information about the Cobalt instance."
|
||||||
|
properties:
|
||||||
|
version:
|
||||||
|
type: string
|
||||||
|
description: "Current version of the Cobalt server instance."
|
||||||
|
url:
|
||||||
|
type: string
|
||||||
|
description: "Base URL of the server instance."
|
||||||
|
startTime:
|
||||||
|
type: number
|
||||||
|
description: "Server start time (Unix timestamp in milliseconds)."
|
||||||
|
durationLimit:
|
||||||
|
type: number
|
||||||
|
description: "Maximum allowed video duration for downloads (in seconds)."
|
||||||
|
services:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
type: string
|
||||||
|
description: "List of supported service names for this instance."
|
||||||
|
required:
|
||||||
|
- version
|
||||||
|
- url
|
||||||
|
- startTime
|
||||||
|
- durationLimit
|
||||||
|
- services
|
||||||
|
git:
|
||||||
|
type: object
|
||||||
|
description: "Git repository information for the running codebase."
|
||||||
|
properties:
|
||||||
|
commit:
|
||||||
|
type: string
|
||||||
|
description: "Git commit hash of the currently running code."
|
||||||
|
branch:
|
||||||
|
type: string
|
||||||
|
description: "Git branch name of the currently running code."
|
||||||
|
remote:
|
||||||
|
type: string
|
||||||
|
description: "Git remote URL of the repository."
|
||||||
|
required:
|
||||||
|
- commit
|
||||||
|
- branch
|
||||||
|
- remote
|
||||||
|
SessionResponse:
|
||||||
|
type: object
|
||||||
|
required:
|
||||||
|
- token
|
||||||
|
- exp
|
||||||
|
description: "Response containing a newly issued JWT token and its expiration time."
|
||||||
|
properties:
|
||||||
|
token:
|
||||||
|
type: string
|
||||||
|
description: "JWT token to use for Bearer authentication in subsequent requests."
|
||||||
|
exp:
|
||||||
|
type: number
|
||||||
|
description: "Token lifetime (expiration time in seconds from issuance)."
|
||||||
|
paths:
|
||||||
|
"/":
|
||||||
|
get:
|
||||||
|
summary: "Get Server Information"
|
||||||
|
description: "Retrieve basic information about the Cobalt server instance (version, uptime, supported services, etc.)."
|
||||||
|
responses:
|
||||||
|
"200":
|
||||||
|
description: "Server info retrieved successfully"
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: "#/components/schemas/ServerInfoResponse"
|
||||||
|
examples:
|
||||||
|
example:
|
||||||
|
summary: "Example server info"
|
||||||
|
value:
|
||||||
|
cobalt:
|
||||||
|
version: "1.0.0"
|
||||||
|
url: "https://api.cobalt.tools"
|
||||||
|
startTime: 1700000000000
|
||||||
|
durationLimit: 600
|
||||||
|
services:
|
||||||
|
- "youtube"
|
||||||
|
- "tiktok"
|
||||||
|
- "twitter"
|
||||||
|
git:
|
||||||
|
commit: "abcdef1234567890"
|
||||||
|
branch: "main"
|
||||||
|
remote: "https://github.com/imputnet/cobalt.git"
|
||||||
|
"401":
|
||||||
|
description: "Unauthorized – missing or invalid API key/Bearer token"
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: "#/components/schemas/ErrorResponse"
|
||||||
|
examples:
|
||||||
|
authRequired:
|
||||||
|
summary: "Authentication required error"
|
||||||
|
value:
|
||||||
|
status: "error"
|
||||||
|
error:
|
||||||
|
code: "api.auth.api-key.missing"
|
||||||
|
context: {}
|
||||||
|
default:
|
||||||
|
description: "Unexpected error"
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: "#/components/schemas/ErrorResponse"
|
||||||
|
examples:
|
||||||
|
errorExample:
|
||||||
|
summary: "General error example"
|
||||||
|
value:
|
||||||
|
status: "error"
|
||||||
|
error:
|
||||||
|
code: "error.api.fetch.critical"
|
||||||
|
context:
|
||||||
|
service: "youtube"
|
||||||
|
post:
|
||||||
|
summary: "Process Download Request"
|
||||||
|
description: >
|
||||||
|
Submit a URL to download content. The server will process the request and respond with
|
||||||
|
either a direct link, a proxy tunnel, a picker for multiple items, or an error.
|
||||||
|
**Headers**: This endpoint requires 'Accept: application/json' and 'Content-Type: application/json'.
|
||||||
|
requestBody:
|
||||||
|
required: true
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: "#/components/schemas/DownloadRequest"
|
||||||
|
example:
|
||||||
|
url: "https://youtu.be/dQw4w9WgXcQ"
|
||||||
|
videoQuality: "720"
|
||||||
|
audioFormat: "mp3"
|
||||||
|
downloadMode: "audio"
|
||||||
|
responses:
|
||||||
|
"200":
|
||||||
|
description: "Request processed successfully (see 'status' field for result type)"
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
oneOf:
|
||||||
|
- $ref: "#/components/schemas/RedirectResponse"
|
||||||
|
- $ref: "#/components/schemas/TunnelResponse"
|
||||||
|
- $ref: "#/components/schemas/PickerResponse"
|
||||||
|
examples:
|
||||||
|
redirect:
|
||||||
|
summary: "Redirect response example"
|
||||||
|
value:
|
||||||
|
status: "redirect"
|
||||||
|
url: "https://example.com/path/to/content.mp4"
|
||||||
|
filename: "video.mp4"
|
||||||
|
tunnel:
|
||||||
|
summary: "Tunnel response example"
|
||||||
|
value:
|
||||||
|
status: "tunnel"
|
||||||
|
url: "https://api.cobalt.tools/tunnel/123e4567-e89b-12d3-a456-426614174000"
|
||||||
|
filename: "video.mp4"
|
||||||
|
picker:
|
||||||
|
summary: "Picker response example"
|
||||||
|
value:
|
||||||
|
status: "picker"
|
||||||
|
audio: "https://api.cobalt.tools/tunnel/audio/abc12345.mp3"
|
||||||
|
audioFilename: "background_audio.mp3"
|
||||||
|
picker:
|
||||||
|
- type: "photo"
|
||||||
|
url: "https://api.cobalt.tools/tunnel/image1.jpg"
|
||||||
|
thumb: "https://api.cobalt.tools/tunnel/image1_thumb.jpg"
|
||||||
|
- type: "photo"
|
||||||
|
url: "https://api.cobalt.tools/tunnel/image2.jpg"
|
||||||
|
thumb: "https://api.cobalt.tools/tunnel/image2_thumb.jpg"
|
||||||
|
"400":
|
||||||
|
description: "Bad request or processing error"
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: "#/components/schemas/ErrorResponse"
|
||||||
|
examples:
|
||||||
|
processingError:
|
||||||
|
summary: "Processing error example"
|
||||||
|
value:
|
||||||
|
status: "error"
|
||||||
|
error:
|
||||||
|
code: "error.api.fetch.critical"
|
||||||
|
context:
|
||||||
|
service: "youtube"
|
||||||
|
"401":
|
||||||
|
description: "Unauthorized – missing or invalid API key/Bearer token"
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: "#/components/schemas/ErrorResponse"
|
||||||
|
examples:
|
||||||
|
authError:
|
||||||
|
summary: "Authentication error example"
|
||||||
|
value:
|
||||||
|
status: "error"
|
||||||
|
error:
|
||||||
|
code: "api.auth.bearer.missing"
|
||||||
|
context: {}
|
||||||
|
default:
|
||||||
|
description: "Unexpected server error"
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: "#/components/schemas/ErrorResponse"
|
||||||
|
"/session":
|
||||||
|
post:
|
||||||
|
summary: "Create Session Token"
|
||||||
|
description: >
|
||||||
|
Generate a short-lived JWT token (Bearer) by proving a successful Turnstile challenge solution.
|
||||||
|
The client must provide the Turnstile response token in the 'cf-turnstile-response' header.
|
||||||
|
security: []
|
||||||
|
parameters:
|
||||||
|
- name: "cf-turnstile-response"
|
||||||
|
in: header
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
description: "Turnstile challenge response token provided by the client."
|
||||||
|
requestBody:
|
||||||
|
description: "No request body is required (the challenge token is provided via header)."
|
||||||
|
content: {}
|
||||||
|
responses:
|
||||||
|
"200":
|
||||||
|
description: "A new JWT token has been issued."
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: "#/components/schemas/SessionResponse"
|
||||||
|
example:
|
||||||
|
token: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...<snip>"
|
||||||
|
exp: 1800
|
||||||
|
"400":
|
||||||
|
description: "Invalid or missing challenge response (token not provided or verification failed)."
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: "#/components/schemas/ErrorResponse"
|
||||||
|
examples:
|
||||||
|
challengeError:
|
||||||
|
summary: "Challenge failure example"
|
||||||
|
value:
|
||||||
|
status: "error"
|
||||||
|
error:
|
||||||
|
code: "api.auth.turnstile.missing"
|
||||||
|
context: {}
|
||||||
|
default:
|
||||||
|
description: "Unexpected error during token generation."
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: "#/components/schemas/ErrorResponse"
|
||||||
|
examples:
|
||||||
|
errorExample:
|
||||||
|
summary: "General error example"
|
||||||
|
value:
|
||||||
|
status: "error"
|
||||||
|
error:
|
||||||
|
code: "error.unknown"
|
||||||
|
context: {}
|
Loading…
Reference in a new issue