diff --git a/docs/api.md b/docs/api.md index 72930c18..35744a2d 100644 --- a/docs/api.md +++ b/docs/api.md @@ -1,8 +1,15 @@ # cobalt api documentation -this document provides info about methods and acceptable variables for all cobalt api requests. +methods, acceptable values, headers, responses and everything else related to making and parsing requests from a cobalt api instance. > [!IMPORTANT] -> hosted api instances (such as `api.cobalt.tools`) use bot protection and are **not** intended to be used in other projects without explicit permission. if you want to access the cobalt api reliably, you should [host your own instance](/docs/run-an-instance.md) or ask an instance owner for access. +> hosted api instances (such as `api.cobalt.tools`) use bot protection and are **not** intended to be used in other projects without explicit permission. if you want to use the cobalt api, you should [host your own instance](/docs/run-an-instance.md) or ask an instance owner for access. + +- [POST /](#post) +- [POST /session](#post-session) +- [GET /](#get) +- [GET /tunnel](#get-tunnel) + +all endpoints (except for `GET /`) are rate limited and return current rate limiting status in `RateLimit-*` headers, according to the ["RateLimit Header Fields for HTTP" spec](https://www.ietf.org/archive/id/draft-polli-ratelimit-headers-02.html#name-header-specifications). ## authentication an api instance may be configured to require you to authenticate yourself. @@ -40,14 +47,11 @@ challenge, if the instance has turnstile configured. the resulting token is pass Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9... ``` -## POST: `/` +## POST `/` cobalt's main processing endpoint. -request body type: `application/json` -response body type: `application/json` - > [!IMPORTANT] -> you must include `Accept` and `Content-Type` headers with every `POST /` request. +> you must include correct `Accept` and `Content-Type` headers with every `POST /` request. ``` Accept: application/json @@ -55,103 +59,132 @@ Content-Type: application/json ``` ### request body -| key | type | expected value(s) | default | description | -|:-----------------------------|:----------|:-----------------------------------|:----------|:--------------------------------------------------------------------------------| -| `url` | `string` | URL to download | -- | **must** be included in every request. | -| `videoQuality` | `string` | `144 / ... / 2160 / 4320 / max` | `1080` | `720` quality is recommended for phones. | -| `audioFormat` | `string` | `best / mp3 / ogg / wav / opus` | `mp3` | | -| `audioBitrate` | `string` | `320 / 256 / 128 / 96 / 64 / 8` | `128` | specifies the bitrate to use for the audio. applies only to audio conversion. | -| `filenameStyle` | `string` | `classic / pretty / basic / nerdy` | `classic` | changes the way files are named. previews can be seen in the web app. | -| `downloadMode` | `string` | `auto / audio / mute` | `auto` | `audio` downloads only the audio, `mute` skips the audio track in videos. | -| `youtubeVideoCodec` | `string` | `h264 / av1 / vp9` | `h264` | `h264` is recommended for phones. | -| `youtubeDubLang` | `string` | `en / ru / cs / ja / es-US / ...` | -- | specifies the language of audio to download when a youtube video is dubbed. | -| `alwaysProxy` | `boolean` | `true / false` | `false` | tunnels all downloads through the processing server, even when not necessary. | -| `disableMetadata` | `boolean` | `true / false` | `false` | disables file metadata when set to `true`. | -| `tiktokFullAudio` | `boolean` | `true / false` | `false` | enables download of original sound used in a tiktok video. | -| `allowH265` | `boolean` | `true / false` | `false` | allows h265 videos when enabled. applies to tiktok & xiaohongshu. | -| `convertGif` | `boolean` | `true / false` | `true` | changes whether mute looping videos are converted to .gif | -| `youtubeHLS` | `boolean` | `true / false` | `false` | specifies whether to use HLS for downloading video or audio from youtube. | +body type: `application/json` + +not a fan of reading tables of text? +you can read [the api schema](/api/src/processing/schema.js) directly from code instead! + +### api schema +all keys except for `url` are optional. value options are separated by `/`. + +#### general +| key | type | description/value | default | +|:-----------------------|:----------|:----------------------------------------------------------------|:-----------| +| `url` | `string` | source URL | *required* | +| `audioBitrate` | `string` | `320 / 256 / 128 / 96 / 64 / 8` (kbps) | `128` | +| `audioFormat` | `string` | `best / mp3 / ogg / wav / opus` | `mp3` | +| `downloadMode` | `string` | `auto / audio / mute` | `auto` | +| `filenameStyle` | `string` | `classic / pretty / basic / nerdy` | `basic` | +| `videoQuality` | `string` | `max / 4320 / 2160 / 1440 / 1080 / 720 / 480 / 360 / 240 / 144` | `1080` | +| `disableMetadata` | `boolean` | title, artist, and other info will not be added to the file | `false` | +| `alwaysProxy` | `boolean` | always tunnel all files, even when not necessary | `false` | +| `localProcessing` | `boolean` | remux/transcode files locally instead of the server | `false` | + +#### service-specific options +| key | type | description/value | default | +|:-----------------------|:----------|:--------------------------------------------------|:--------| +| `youtubeVideoCodec` | `string` | `h264 / av1 / vp9` | `h264` | +| `youtubeDubLang` | `string` | any valid language code, such as: `en` or `zh-CN` | *none* | +| `convertGif` | `boolean` | convert twitter gifs to the actual GIF format | `true` | +| `allowH265` | `boolean` | allow H265/HEVC videos from tiktok/xiaohongshu | `false` | +| `tiktokFullAudio` | `boolean` | download the original sound used in a video | `false` | +| `youtubeBetterAudio` | `boolean` | prefer higher quality youtube audio if possible | `false` | +| `youtubeHLS` | `boolean` | use HLS formats when downloading from youtube | `false` | ### response -the response will always be a JSON object containing the `status` key, which will be one of: -- `error` - something went wrong -- `picker` - we have multiple items to choose from -- `redirect` - you are being redirected to the direct service URL -- `tunnel` - cobalt is proxying the download for you +body type: `application/json` + +the response will always be a JSON object containing the `status` key, which is one of: +- `tunnel`: cobalt is proxying and/or remuxing/transcoding the file for you. +- `local-processing`: cobalt is proxying the files for you, but you have to remux/transcode them locally. +- `redirect`: cobalt will redirect you to the direct service URL. +- `picker`: there are multiple items to choose from, a picker should be shown. +- `error`: something went wrong, here's an error code. ### tunnel/redirect response -| key | type | values | -|:-------------|:---------|:------------------------------------------------------------| -| `status` | `string` | `tunnel / redirect` | -| `url` | `string` | url for the cobalt tunnel, or redirect to an external link | -| `filename` | `string` | cobalt-generated filename for the file being downloaded | +| key | type | value | +|:-------------|:---------|:-----------------------------------------------------------| +| `status` | `string` | `tunnel / redirect` | +| `url` | `string` | url for the cobalt tunnel, or redirect to an external link | +| `filename` | `string` | cobalt-generated filename for the file being downloaded | + +### local processing response +| key | type | value | +|:-------------|:-----------|:--------------------------------------------------------------| +| `status` | `string` | `local-processing` | +| `type` | `string` | `merge`, `mute`, `audio`, or `gif` | +| `service` | `string` | origin service (`youtube`, `twitter`, `instagram`, etc) | +| `tunnel` | `string[]` | array of tunnel URLs | +| `output` | `object` | details about the output file ([see below](#output-object)) | +| `audio` | `object` | audio-specific details (optional, [see below](#audio-object)) | +| `isHLS` | `boolean` | whether the output is in HLS format (optional) | + +#### output object +| key | type | value | +|:-----------|:---------|:----------------------------------------------------------------------------------| +| `type` | `string` | mime type of the output file | +| `filename` | `string` | filename of the output file | +| `metadata` | `object` | metadata associated with the file (optional, [see below](#outputmetadata-object)) | + +#### output.metadata object +all keys in this table are optional. + +| key | type | description | +|:------------|:---------|:-------------------------------------------| +| `album` | `string` | album name or collection title | +| `copyright` | `string` | copyright information or ownership details | +| `title` | `string` | title of the track or media file | +| `artist` | `string` | artist or creator name | +| `track` | `string` | track number or position in album | +| `date` | `string` | release date or creation date | + +#### audio object +| key | type | value | +|:----------|:----------|:-------------------------------------------| +| `copy` | `boolean` | defines whether audio codec data is copied | +| `format` | `string` | output audio format | +| `bitrate` | `string` | preferred bitrate of audio format | ### picker response -| key | type | values | -|:----------------|:---------|:-------------------------------------------------------------------------------------------------| -| `status` | `string` | `picker` | -| `audio` | `string` | **optional** returned when an image slideshow (such as on tiktok) has a general background audio | -| `audioFilename` | `string` | **optional** cobalt-generated filename, returned if `audio` exists | -| `picker` | `array` | array of objects containing the individual media | +| key | type | value | +|:----------------|:---------|:-----------------------------------------------------------------------------------------------| +| `status` | `string` | `picker` | +| `audio` | `string` | returned when an image slideshow (such as on tiktok) has a general background audio (optional) | +| `audioFilename` | `string` | cobalt-generated filename, returned if `audio` exists (optional) | +| `picker` | `array` | array of objects containing the individual media | #### picker object -| key | type | values | -|:-------------|:----------|:------------------------------------------------------------| -| `type` | `string` | `photo` / `video` / `gif` | -| `url` | `string` | | -| `thumb` | `string` | **optional** thumbnail url | +| key | type | value | +|:-------------|:----------|:--------------------------| +| `type` | `string` | `photo` / `video` / `gif` | +| `url` | `string` | | +| `thumb` | `string` | thumbnail url (optional) | ### error response -| key | type | values | -|:-------------|:---------|:------------------------------------------------------------| -| `status` | `string` | `error` | -| `error` | `object` | contains more context about the error | +| key | type | value | +|:-------------|:---------|:------------------------------| +| `status` | `string` | `error` | +| `error` | `object` | error code & optional context | #### error object -| key | type | values | -|:-------------|:---------|:------------------------------------------------------------| -| `code` | `string` | machine-readable error code explaining the failure reason | -| `context` | `object` | **optional** container for providing more context | +| key | type | value | +|:-------------|:---------|:----------------------------------------------------------| +| `code` | `string` | machine-readable error code explaining the failure reason | +| `context` | `object` | additional error context (optional) | #### error.context object -| key | type | values | -|:-------------|:---------|:---------------------------------------------------------------------------------------------------------------| -| `service` | `string` | **optional**, stating which service was being downloaded from | -| `limit` | `number` | **optional** number providing the ratelimit maximum number of requests, or maximum downloadable video duration | - -## GET: `/` -returns current basic server info. -response body type: `application/json` - -### response body -| key | type | variables | -|:------------|:---------|:---------------------------------------------------------| -| `cobalt` | `object` | information about the cobalt instance | -| `git` | `object` | information about the codebase that is currently running | - -#### cobalt object -| key | type | description | -|:----------------|:-----------|:-----------------------------------------------| -| `version` | `string` | current version | -| `url` | `string` | server url | -| `startTime` | `string` | server start time in unix milliseconds | -| `durationLimit` | `number` | maximum downloadable video length in seconds | -| `services` | `string[]` | array of services which this instance supports | - -#### git object -| key | type | variables | -|:------------|:---------|:------------------| -| `commit` | `string` | commit hash | -| `branch` | `string` | git branch | -| `remote` | `string` | git remote | - -## POST: `/session` +| key | type | value | +|:-------------|:---------|:----------------------------------------------------------------------------| +| `service` | `string` | origin service (optional) | +| `limit` | `number` | the maximum downloadable video duration or the rate limit window (optional) | +## POST `/session` used for generating JWT tokens, if enabled. currently, cobalt only supports generating tokens when a [turnstile](run-an-instance.md#list-of-all-environment-variables) challenge solution is submitted by the client. the turnstile challenge response is submitted via the `cf-turnstile-response` header. + ### response body | key | type | description | |:----------------|:-----------|:-------------------------------------------------------| @@ -159,3 +192,48 @@ the turnstile challenge response is submitted via the `cf-turnstile-response` he | `exp` | `number` | number in seconds indicating the token lifetime | on failure, an [error response](#error-response) is returned. + +## GET `/` +provides basic instance info. + +### response +body type: `application/json` + +| key | type | description | +|:------------|:---------|:---------------------------------------------------------| +| `cobalt` | `object` | information about the cobalt instance | +| `git` | `object` | information about the codebase that is currently running | + +#### cobalt object +| key | type | description | +|:-------------------|:-----------|:-----------------------------------------------| +| `version` | `string` | cobalt version | +| `url` | `string` | instance url | +| `startTime` | `string` | instance start time in unix milliseconds | +| `turnstileSitekey` | `string` | site key for a turnstile widget (optional) | +| `services` | `string[]` | array of services which this instance supports | + +#### git object +| key | type | description | +|:------------|:---------|:------------| +| `commit` | `string` | commit hash | +| `branch` | `string` | git branch | +| `remote` | `string` | git remote | + +## GET `/tunnel` +endpoint for file tunnels (proxy/remux/transcode). the response is a file stream. all errors are reported via +[HTTP status codes](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Status). + +### returned headers +- `Content-Length`: file size, in bytes. returned when exact final file size is known. +- `Estimated-Content-Length`: estimated file size, in bytes. returned when real `Content-Length` is not known. +a rough estimate which should NOT be used for strict size verification. +can be used to show approximate download progress in UI. + +### possible HTTP status codes +- 200: OK +- 401: Unauthorized +- 403: Bad Request +- 404: Not Found +- 429: Too Many Requests (rate limit exceeded, check [RateLimit-* headers](https://www.ietf.org/archive/id/draft-polli-ratelimit-headers-02.html#name-header-specifications)) +- 500: Internal Server Error.