mirror of
https://github.com/wukko/cobalt.git
synced 2025-03-03 15:38:49 +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