{
    "openapi": "3.0.3",
    "info": {
        "title": "Video Download API",
        "version": "1.0.0",
        "description": "REST API for downloading YouTube and other supported videos/audio in many\nformats and qualities.\n\nThe Video Download API REST API lets you submit a video URL, pick an output\nformat (audio, video, or subtitles), and retrieve a direct download URL. Long jobs\nreturn an `id` you can poll via the Progress endpoint until the file is ready.\n\n## Authentication\n\nEvery request to the Download endpoint must include your personal `apikey`\nquery parameter. The Subtitles endpoint uses the same key via the `api`\nquery parameter. Create an account to generate one or use the support form at\n[video-download-api.com/contact/form](https://video-download-api.com/contact/form) if you need help before signup.\nThe Progress endpoint does not require an API key — only the job `id` returned\nfrom a previous submit call.\n\n## Pricing model\n\nCredits are deducted from your API-key balance based on the chosen `format`.\nQueued download and subtitle jobs are charged when the API accepts the request\nand returns a job `id`, before the file is ready. Streaming downloads, including\n`/api/v2/download`, are charged when the prepared file link is saved; a streaming\ndownload that fails before its file is prepared is not charged. The Download\nendpoint can use either charge point, depending on the URL and current routing,\nso plan your budget as if every accepted `id` is charged. A request rejected\nbefore a job is accepted (for example \"Not enough balance\", invalid input, or no\navailable worker) returns no job `id` and is not charged. An accepted job that\nfails later can still use balance; charges are not reversed automatically.\n\nAn accepted `id` is not a finished file. Only `progress == 1000` with `success`\n`1` or `true` and a non-empty `download_url` is a finished file. A client timeout\ndoes not cancel an accepted job: keep the `id` and continue to poll the Progress\nendpoint. Do not send the same request again, because a new request creates a\nnew job and can be charged again.\n\nVideo formats beyond the \"base duration limit\" (e.g. videos longer than\n180 minutes at 1080p or 30 minutes at MP4 4K/8K) cost extra if `allow_extended_duration=1` is set; otherwise\nthose jobs are rejected. See the `ExtendedDuration` schema and the hosted\ndocumentation page for the full pricing matrix.\n",
        "contact": {
            "name": "Video Download API Support",
            "url": "https://video-download-api.com/contact/form"
        },
        "termsOfService": "https://video-download-api.com/",
        "license": {
            "name": "Proprietary",
            "url": "https://video-download-api.com/"
        }
    },
    "servers": [
        {
            "url": "https://{host}",
            "description": "Production endpoint",
            "variables": {
                "host": {
                    "default": "p.savenow.to",
                    "description": "API hostname for requests. p.savenow.to is the default shared API host; use the custom account-specific hostname shown in your dashboard when applicable."
                }
            }
        }
    ],
    "tags": [
        {
            "name": "Download",
            "description": "Submit a new download job and receive a job id."
        },
        {
            "name": "Subtitles",
            "description": "Submit a new subtitles/transcript job and receive a job id."
        },
        {
            "name": "Progress",
            "description": "Poll a download or subtitle job and read its terminal outcome."
        },
        {
            "name": "Info",
            "description": "Fetch provider-supplied metadata for a YouTube URL without creating a media job."
        }
    ],
    "security": [
        {
            "ApiKeyAuth": []
        }
    ],
    "paths": {
        "/ajax/api.php": {
            "get": {
                "tags": [
                    "Info"
                ],
                "summary": "Fetch YouTube video metadata",
                "operationId": "getYouTubeVideoInfo",
                "security": [
                    {
                        "InfoApiKeyAuth": []
                    }
                ],
                "description": "Calls the legacy API dispatcher with `function=i`. The info function accepts YouTube URLs,\nreturns available provider-supplied metadata directly, and does not create a download job.\nFresh successful lookups use the configured info price; cached results can be returned\nwithout another charge. Optional metadata fields can be absent. `download_cost_estimates`\ndescribes configured output costs and is not a list of source streams or available qualities.\n",
                "parameters": [
                    {
                        "name": "function",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string",
                            "enum": [
                                "i"
                            ]
                        },
                        "example": "i",
                        "description": "Select the YouTube info function."
                    },
                    {
                        "name": "api",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "example": "YOUR_API_KEY",
                        "description": "Personal API key. Keep it on your server."
                    },
                    {
                        "name": "u",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string",
                            "format": "uri"
                        },
                        "example": "https://www.youtube.com/watch?v=VIDEO_ID",
                        "description": "YouTube watch, Shorts, or youtu.be URL."
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Available video metadata and configured output cost estimates.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/InfoResponse"
                                },
                                "example": {
                                    "id": "VIDEO_ID",
                                    "title": "Video title",
                                    "duration": 120,
                                    "durationString": "2:00",
                                    "thumbnail": "https://i.ytimg.com/vi/VIDEO_ID/hqdefault.jpg",
                                    "channel": "Example channel",
                                    "download_cost_estimates": {
                                        "mp3": {
                                            "name": "MP3",
                                            "base_price": 0.0002,
                                            "multiplier": 1,
                                            "final_price": 0.0002
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Missing API key, insufficient balance, unsupported URL, or invalid video id.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ErrorResponse"
                                }
                            }
                        }
                    },
                    "500": {
                        "description": "Metadata providers could not return a usable result.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ErrorResponse"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/ajax/download.php": {
            "get": {
                "tags": [
                    "Download"
                ],
                "summary": "Create a download job",
                "operationId": "createDownload",
                "description": "Submits a new download job for the given `url` in the requested `format`.\nReturns a unique `id` you can pass to the Progress endpoint to poll for\ncompletion and retrieve the final download URL.\n",
                "parameters": [
                    {
                        "name": "format",
                        "in": "query",
                        "required": true,
                        "example": "mp44k",
                        "description": "Accepted audio values: `mp3`, `m4a`, `webm`, `aac`, `flac`, `opus`,\n`ogg`, `vorbis`, and `wav`. Accepted video values: `144`, `240`, `360`,\n`480`, `720`, `1080`, `1440`, `MOV360`, `MOV480`, `MOV720`,\n`MOV1080`, `MOV1440`, `4k`, `8k`, `mp44k`, and `mp48k`.\n\nStandard video formats such as `360`, `720`, `1080`, and `1440`\nhave a 180-minute configured base duration limit. High-resolution\nWEBM key `8k` and MP4 keys `4k`/`mp44k`/`mp48k` have a 30-minute\nconfigured base duration limit.\n",
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "name": "url",
                        "in": "query",
                        "required": true,
                        "example": "https://www.youtube.com/watch?v=K1Pu75yJUOE",
                        "description": "The URL-encoded URL of the video to download (YouTube and other supported sources).",
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "name": "apikey",
                        "in": "query",
                        "required": true,
                        "example": "YOUR_API_KEY",
                        "description": "Your personal API key.",
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "name": "add_info",
                        "in": "query",
                        "required": false,
                        "example": "1",
                        "description": "Set to `1` to include the `info` object (title + thumbnail) in the response. Defaults to `0` when omitted.",
                        "schema": {
                            "type": "integer"
                        }
                    },
                    {
                        "name": "audio_quality",
                        "in": "query",
                        "required": false,
                        "example": "128",
                        "description": "Audio bitrate in kbps. Common values include `128`, `192`, `256`, `320`.",
                        "schema": {
                            "type": "integer"
                        }
                    },
                    {
                        "name": "allow_extended_duration",
                        "in": "query",
                        "required": false,
                        "example": "1",
                        "description": "Set to `1` to permit downloads whose video duration exceeds the format's\nbase duration limit. Extended-duration jobs are charged a multiplier of\nthe base price (see the `ExtendedDuration` response object). Defaults to\n`0` when omitted.\n",
                        "schema": {
                            "type": "integer"
                        }
                    },
                    {
                        "name": "max_duration",
                        "in": "query",
                        "required": false,
                        "example": "240",
                        "description": "Maximum video duration in minutes for extended-duration downloads. Use\nwith `allow_extended_duration=1` to cap accepted video length and prevent\nunexpected costs; videos longer than this limit are rejected. When omitted,\nno maximum duration cap is applied.\n",
                        "schema": {
                            "type": "integer",
                            "minimum": 1
                        }
                    },
                    {
                        "name": "no_merge",
                        "in": "query",
                        "required": false,
                        "example": "0",
                        "description": "If set to `1`, audio and video streams are **not** merged. The client\nreceives a zip file containing the separate streams. Defaults to `0`\n(streams are merged into a single file).\n",
                        "schema": {
                            "type": "integer"
                        }
                    },
                    {
                        "name": "audio_language",
                        "in": "query",
                        "required": false,
                        "example": "en",
                        "description": "YouTube only. Selects the audio track language by BCP-47 / YouTube\nlanguage code. If the requested track is not available on the video,\nthe default track is used instead. No additional cost.\n\nSupported codes: `af, az, id, ms, bs, ca, cs, da, de, et, en-IN, en-GB,\nen, es, es-419, es-US, eu, fil, fr, fr-CA, gl, hr, zu, is, it, sw, lv,\nlt, hu, nl, no, uz, pl, pt-PT, pt, ro, sq, sk, sl, sr-Latn, fi, sv, vi,\ntr, be, bg, ky, kk, mk, mn, ru, sr, uk, el, hy, iw, ur, ar, fa, ne, mr,\nhi, as, bn, pa, gu, or, ta, te, kn, ml, si, th, lo, my, ka, am, km,\nzh-CN, zh-TW, zh-HK, ja, ko`.\n",
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "name": "start_time",
                        "in": "query",
                        "required": false,
                        "example": "30",
                        "description": "Optional. Start time (in seconds) of a cut/segment download. When\n`start_time`/`end_time` are supplied, progress is not reported — the\nProgress endpoint only returns initialization and the final success /\nfailure status.\n",
                        "schema": {
                            "type": "integer"
                        }
                    },
                    {
                        "name": "end_time",
                        "in": "query",
                        "required": false,
                        "example": "90",
                        "description": "Optional. End time (in seconds) of a cut/segment download.",
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Job accepted. Use the returned `id` with the Progress endpoint to poll for the final download URL.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/DownloadResponse"
                                },
                                "examples": {
                                    "standard": {
                                        "summary": "Standard download",
                                        "value": {
                                            "success": true,
                                            "id": "abc123xyz789",
                                            "content": "PGRpdiBjbGFzcz0iZG93bmxvYWQtY29udGVudCI+Li4uPC9kaXY+",
                                            "info": {
                                                "image": "https://i.ytimg.com/vi/K1Pu75yJUOE/maxresdefault.jpg",
                                                "title": "Amazing Video Title - 4K Quality"
                                            }
                                        }
                                    },
                                    "extended": {
                                        "summary": "Extended-duration download (premium)",
                                        "value": {
                                            "success": true,
                                            "id": "abc123xyz789",
                                            "content": "PGRpdiBjbGFzcz0iZG93bmxvYWQtY29udGVudCI+Li4uPC9kaXY+",
                                            "info": {
                                                "image": "https://i.ytimg.com/vi/K1Pu75yJUOE/maxresdefault.jpg",
                                                "title": "Amazing Video Title - 4K Quality"
                                            },
                                            "extended_duration": {
                                                "multiplier": 3,
                                                "original_price": 0.00035,
                                                "final_price": 0.00105
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Missing or invalid parameters (for example, missing `url`, unknown `format`, or a video that exceeds the base duration without `allow_extended_duration=1`).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ErrorResponse"
                                }
                            }
                        }
                    },
                    "500": {
                        "description": "Server error.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ErrorResponse"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/ajax/subtitles": {
            "get": {
                "tags": [
                    "Subtitles"
                ],
                "summary": "Create a subtitles/transcript job",
                "operationId": "createSubtitles",
                "security": [
                    {
                        "SubtitleApiKeyAuth": []
                    }
                ],
                "description": "Submits a subtitles/transcript job for the given `url`. Returns a unique\n`id` and an absolute `progress_url`. Poll it using the shared Progress\ncontract: values below 1000 are pending regardless of `success`. At\n`progress == 1000`, the subtitle file is ready only when `success` is `1`\nor `true` and `download_url` is non-empty. Otherwise, stop polling and\nsurface `text` or `message`, using a generic failure message if neither\nis present. RapidAPI clients receive clean JSON without the optional\nlegacy HTML `content` card. Poll `progress_url` directly without\nRapidAPI headers or the API key. A ready `download_url` points to the\ngenerated `.vtt` or `.srt` file. Non-2xx responses are request errors.\n",
                "parameters": [
                    {
                        "name": "url",
                        "in": "query",
                        "required": true,
                        "example": "https://www.youtube.com/watch?v=K1Pu75yJUOE",
                        "description": "The URL-encoded URL of the video to generate subtitles/transcripts for.",
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "name": "lang",
                        "in": "query",
                        "required": false,
                        "example": "en",
                        "description": "Optional subtitle language code.",
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "name": "format",
                        "in": "query",
                        "required": false,
                        "example": "vtt",
                        "description": "Optional subtitle output format.",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "vtt",
                                "srt"
                            ]
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Job accepted. Poll the returned `progress_url` using the shared Progress state rules.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/SubtitleResponse"
                                },
                                "examples": {
                                    "standard": {
                                        "summary": "Standard API-key subtitle request",
                                        "value": {
                                            "success": true,
                                            "id": "subtitle-job-123",
                                            "title": "Amazing Video Title",
                                            "progress_url": "https://YOUR_API_HOST/ajax/progress.php?id=subtitle-job-123",
                                            "content": "PGRpdiBjbGFzcz0ic3VidGl0bGUtY29udGVudCI+Li4uPC9kaXY+"
                                        }
                                    },
                                    "rapidapi": {
                                        "summary": "RapidAPI subtitle request",
                                        "value": {
                                            "success": true,
                                            "id": "subtitle-job-123",
                                            "title": "Amazing Video Title",
                                            "progress_url": "https://p.savenow.to/ajax/progress.php?id=subtitle-job-123"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Missing or invalid parameters.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ErrorResponse"
                                }
                            }
                        }
                    },
                    "500": {
                        "description": "Server error.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ErrorResponse"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/ajax/progress": {
            "get": {
                "tags": [
                    "Progress"
                ],
                "summary": "Check download or subtitle progress",
                "operationId": "getProgress",
                "security": [],
                "description": "Polls the status of a previously-submitted download or subtitle job.\nA progress value below 1000 is pending, regardless of `success`.\nAt `progress == 1000`, the job is ready only when `success` is `1` or\n`true` and `download_url` is a non-empty URL. Otherwise, stop polling\nand surface `text` or `message` as a terminal failure, using a generic\nfailure message if neither is present. Non-2xx responses are request\nerrors, not job states.\n",
                "parameters": [
                    {
                        "name": "id",
                        "in": "query",
                        "required": true,
                        "example": "YOUR_JOB_ID",
                        "description": "The job id returned by the Download or Subtitles endpoint.",
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Current progress of the download or subtitle job.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ProgressResponse"
                                },
                                "examples": {
                                    "finished": {
                                        "summary": "Download finished",
                                        "value": {
                                            "success": 1,
                                            "progress": 1000,
                                            "download_url": "https://YOUR_API_HOST/storage/downloads/abc123xyz789/video.mp4",
                                            "text": "Finished",
                                            "message": "Need product or integration help? Use the support form at https://video-download-api.com/contact/form"
                                        }
                                    },
                                    "subtitleFinished": {
                                        "summary": "Subtitle file ready",
                                        "value": {
                                            "success": 1,
                                            "progress": 1000,
                                            "download_url": "https://p.savenow.to/storage/downloads/subtitle-job-123/subtitles.en.srt",
                                            "text": "Finished"
                                        }
                                    },
                                    "inProgress": {
                                        "summary": "Still pending when success is 0",
                                        "value": {
                                            "success": 0,
                                            "progress": 400,
                                            "download_url": "",
                                            "text": "Downloading"
                                        }
                                    },
                                    "finishedBoolean": {
                                        "summary": "Download finished with boolean success",
                                        "value": {
                                            "success": true,
                                            "progress": 1000,
                                            "download_url": "https://YOUR_API_HOST/storage/downloads/abc123xyz789/video.mp4",
                                            "text": "Finished"
                                        }
                                    },
                                    "failed": {
                                        "summary": "Terminal failure without a download URL",
                                        "value": {
                                            "success": false,
                                            "progress": 1000,
                                            "download_url": null,
                                            "text": "Failed",
                                            "message": "Download link unavailable. Please start a new conversion."
                                        }
                                    },
                                    "failedNumeric": {
                                        "summary": "Terminal failure with numeric success 0",
                                        "value": {
                                            "success": 0,
                                            "progress": 1000,
                                            "download_url": null,
                                            "text": "Failed",
                                            "message": "Download link unavailable. Please start a new conversion."
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Missing or invalid `id`.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ErrorResponse"
                                }
                            }
                        }
                    },
                    "500": {
                        "description": "Server error.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ErrorResponse"
                                }
                            }
                        }
                    }
                }
            }
        }
    },
    "components": {
        "securitySchemes": {
            "ApiKeyAuth": {
                "type": "apiKey",
                "in": "query",
                "name": "apikey",
                "description": "Pass your API key as the `apikey` query parameter on every Download request."
            },
            "SubtitleApiKeyAuth": {
                "type": "apiKey",
                "in": "query",
                "name": "api",
                "description": "Pass your API key as the `api` query parameter on every Subtitles request."
            },
            "InfoApiKeyAuth": {
                "type": "apiKey",
                "in": "query",
                "name": "api",
                "description": "Pass your API key as the `api` query parameter on YouTube Info requests."
            }
        },
        "schemas": {
            "InfoResponse": {
                "type": "object",
                "description": "Provider-supplied metadata varies by source. Optional fields can be absent.",
                "additionalProperties": true,
                "properties": {
                    "id": {
                        "type": "string",
                        "description": "YouTube video id."
                    },
                    "title": {
                        "type": "string",
                        "nullable": true
                    },
                    "duration": {
                        "type": "number",
                        "nullable": true,
                        "description": "Duration in seconds when supplied by the provider."
                    },
                    "durationString": {
                        "type": "string",
                        "nullable": true,
                        "description": "Human-readable duration when supplied by the provider."
                    },
                    "views": {
                        "oneOf": [
                            {
                                "type": "integer"
                            },
                            {
                                "type": "string"
                            }
                        ],
                        "nullable": true
                    },
                    "viewCount": {
                        "oneOf": [
                            {
                                "type": "integer"
                            },
                            {
                                "type": "string"
                            }
                        ],
                        "nullable": true
                    },
                    "uploaded": {
                        "type": "string",
                        "nullable": true
                    },
                    "uploadDate": {
                        "type": "string",
                        "nullable": true
                    },
                    "thumbnail": {
                        "type": "string",
                        "format": "uri",
                        "nullable": true
                    },
                    "channel": {
                        "type": "string",
                        "nullable": true
                    },
                    "download_cost_estimates": {
                        "type": "object",
                        "description": "Configured output pricing estimates, not source formats or available stream URLs.",
                        "additionalProperties": {
                            "type": "object",
                            "properties": {
                                "name": {
                                    "type": "string"
                                },
                                "base_price": {
                                    "type": "number"
                                },
                                "multiplier": {
                                    "type": "number"
                                },
                                "final_price": {
                                    "type": "number"
                                }
                            }
                        }
                    }
                }
            },
            "DownloadResponse": {
                "type": "object",
                "required": [
                    "success",
                    "id"
                ],
                "properties": {
                    "success": {
                        "type": "boolean",
                        "description": "`true` when the job was accepted, `false` on error."
                    },
                    "id": {
                        "type": "string",
                        "description": "Unique identifier for the job. Pass this to the Progress endpoint."
                    },
                    "content": {
                        "type": "string",
                        "description": "Base64-encoded HTML snippet you can render to show a progress/download UI."
                    },
                    "info": {
                        "$ref": "#/components/schemas/InfoObject"
                    },
                    "extended_duration": {
                        "$ref": "#/components/schemas/ExtendedDuration"
                    }
                }
            },
            "InfoObject": {
                "type": "object",
                "description": "Extra metadata about the downloaded content. Only present when `add_info=1`.",
                "properties": {
                    "image": {
                        "type": "string",
                        "format": "uri",
                        "description": "URL of a thumbnail image for the content."
                    },
                    "title": {
                        "type": "string",
                        "description": "Title of the content."
                    }
                }
            },
            "SubtitleResponse": {
                "type": "object",
                "required": [
                    "success",
                    "id",
                    "progress_url"
                ],
                "properties": {
                    "success": {
                        "type": "boolean",
                        "description": "`true` when the subtitles/transcript job was accepted, `false` on error."
                    },
                    "id": {
                        "type": "string",
                        "description": "Unique identifier for the job. Pass this to the Progress endpoint."
                    },
                    "title": {
                        "type": "string",
                        "description": "Title of the content."
                    },
                    "progress_url": {
                        "type": "string",
                        "format": "uri",
                        "description": "Absolute URL to poll for progress."
                    },
                    "content": {
                        "type": "string",
                        "description": "Optional base64-encoded HTML snippet for legacy UI rendering. RapidAPI responses omit this field. API clients should poll `progress_url` instead."
                    }
                }
            },
            "ExtendedDuration": {
                "type": "object",
                "description": "Pricing detail returned when `allow_extended_duration=1` **and** the video\nexceeds the format's base duration limit.\n",
                "properties": {
                    "multiplier": {
                        "type": "integer",
                        "description": "Price multiplier applied because of the video's duration (e.g. `3` means 3x pricing).",
                        "example": 3
                    },
                    "original_price": {
                        "type": "number",
                        "format": "float",
                        "description": "Base per-download price for the selected format, before the multiplier.",
                        "example": 0.00035
                    },
                    "final_price": {
                        "type": "number",
                        "format": "float",
                        "description": "Final per-download price after the multiplier is applied.",
                        "example": 0.00105
                    }
                }
            },
            "ProgressResponse": {
                "type": "object",
                "required": [
                    "success",
                    "progress"
                ],
                "properties": {
                    "success": {
                        "oneOf": [
                            {
                                "type": "integer",
                                "enum": [
                                    0,
                                    1
                                ]
                            },
                            {
                                "type": "boolean"
                            }
                        ],
                        "description": "Observed values are numeric 0 or 1, and boolean false or true. Interpret success together with progress; success 0 below progress 1000 is still pending."
                    },
                    "progress": {
                        "type": "integer",
                        "minimum": 0,
                        "maximum": 1000,
                        "description": "Progress in thousandths. `1000` means 100% complete."
                    },
                    "download_url": {
                        "type": "string",
                        "nullable": true,
                        "description": "May be null or empty while pending. At progress 1000, use it only when success is 1 or true and it is a non-empty URL."
                    },
                    "text": {
                        "type": "string",
                        "nullable": true,
                        "description": "Human-readable status (for example `Downloading`, `Finished`, `Failed`)."
                    },
                    "message": {
                        "type": "string",
                        "description": "Informational message from the API."
                    }
                }
            },
            "ErrorResponse": {
                "type": "object",
                "properties": {
                    "success": {
                        "type": "boolean",
                        "example": false
                    },
                    "error": {
                        "type": "string",
                        "description": "Human-readable error message."
                    }
                }
            }
        }
    }
}