{
  "openapi": "3.1.0",
  "info": {
    "title": "FastSaverAPI",
    "version": "1.0.0",
    "summary": "one get request returns media from 9 platforms as clean json",
    "description": "no proxies, no cookies, no bot blocks. read `ok`, not the status code. client errors are a 400, except an invalid key (401), a missing parameter (422) and a rate limit (429). running out of credits is a 400 - there is no 402. 503 means we are overloaded: retry after the Retry-After header, it costs nothing. 500 is our bug and the body carries a request_id for support.",
    "termsOfService": "https://api.fastsaver.io/terms",
    "contact": {
      "url": "https://api.fastsaver.io/docs"
    }
  },
  "servers": [
    {
      "url": "https://api.fastsaver.io"
    }
  ],
  "security": [
    {
      "apiKey": []
    }
  ],
  "components": {
    "securitySchemes": {
      "apiKey": {
        "type": "apiKey",
        "in": "header",
        "name": "X-Api-Key"
      }
    },
    "schemas": {
      "Failure": {
        "type": "object",
        "required": [
          "ok",
          "detail"
        ],
        "properties": {
          "ok": {
            "type": "boolean",
            "const": false
          },
          "detail": {
            "type": "string"
          },
          "request_id": {
            "type": "string"
          }
        }
      }
    },
    "responses": {
      "Failure": {
        "description": "failure - the body carries ok: false and a detail string",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Failure"
            }
          }
        }
      },
      "ValidationError": {
        "description": "a required parameter or the X-Api-Key header is missing - FastAPI's own body, without ok",
        "content": {
          "application/json": {
            "schema": {
              "type": "object",
              "required": [
                "detail"
              ],
              "properties": {
                "detail": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "loc": {
                        "type": "array",
                        "items": {
                          "type": [
                            "string",
                            "integer"
                          ]
                        }
                      },
                      "msg": {
                        "type": "string"
                      },
                      "type": {
                        "type": "string"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      },
      "InternalError": {
        "description": "our bug - detail is \"internal error\" and the body carries a request_id; send it to support",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Failure"
            }
          }
        }
      },
      "Overloaded": {
        "description": "we are overloaded (detail \"Service is busy. Please retry in a moment.\") - wait for Retry-After and retry; it costs nothing",
        "headers": {
          "Retry-After": {
            "description": "seconds to wait before retrying",
            "schema": {
              "type": "integer"
            }
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Failure"
            }
          }
        }
      }
    }
  },
  "paths": {
    "/v1/fetch": {
      "get": {
        "operationId": "fetch",
        "summary": "one link in, clean json out",
        "description": "paste a link from any supported platform. the response shape is the same everywhere: `ok`, `id`, `source`, `type`, then the media. multi-item posts (carousels, tiktok photo posts, pinterest idea pins) return `type: \"album\"` with an `items` array and NO top-level `download_url` - check `type` first. tiktok responses carry two extra fields, `music_url` and `music`. an unsupported host still costs 0.1 credit.",
        "tags": [
          "core"
        ],
        "x-credits": "varies",
        "x-credits-on-failure": 0.1,
        "responses": {
          "200": {
            "description": "success - the body always carries ok: true",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok"
                  ],
                  "additionalProperties": true,
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    }
                  }
                },
                "example": {
                  "ok": true,
                  "id": "DRsmm9UjKfH",
                  "source": "instagram.com",
                  "type": "video",
                  "download_url": "https://scontent-dfw6-2.cdninstagram.com/o1/v/t2/f2/m412/AQOqB7ZktoNZKYvIUuQU6ptpi3…",
                  "width": 1080,
                  "height": 1920,
                  "thumbnail_url": "https://scontent-dfw6-1.cdninstagram.com/v/t51.71878-15/588206701_85850229606866_n.jpg…",
                  "duration": 46,
                  "caption": "Ferrari 296 GTS top speed run…"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Failure"
          },
          "401": {
            "$ref": "#/components/responses/Failure"
          },
          "422": {
            "$ref": "#/components/responses/ValidationError"
          },
          "429": {
            "$ref": "#/components/responses/Failure"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/Overloaded"
          }
        },
        "parameters": [
          {
            "name": "url",
            "in": "query",
            "required": true,
            "description": "the media url. the scheme is optional.",
            "schema": {
              "type": "string"
            }
          }
        ]
      }
    },
    "/v1/youtube/info": {
      "get": {
        "operationId": "youtube_info",
        "summary": "video formats, or a community post with its media",
        "description": "metadata for a youtube video, including every downloadable format with its file size. use it to show the user what they are about to download. a community post link (`youtube.com/post/...`) works too, at the same price: then `is_post` is `true` and the body describes the post (see below). check `is_post` first.",
        "tags": [
          "youtube"
        ],
        "x-credits": 2,
        "x-credits-on-failure": 0.1,
        "responses": {
          "200": {
            "description": "success - the body always carries ok: true",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok"
                  ],
                  "additionalProperties": true,
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    }
                  }
                },
                "examples": {
                  "default": {
                    "summary": "response",
                    "value": {
                      "ok": true,
                      "is_post": false,
                      "video_id": "HanBb8FonWs",
                      "title": "Snails - Frogbass",
                      "author": "DubstepGutter",
                      "author_url": "https://www.youtube.com/channel/UCG6QEHCBfWZOnv7UVxappyw",
                      "thumbnail": "https://i.ytimg.com/vi/HanBb8FonWs/sddefault.jpg",
                      "duration": 234,
                      "thumbnails": {
                        "low": "https://i.ytimg.com/vi/HanBb8FonWs/mqdefault.jpg",
                        "max": "https://i.ytimg.com/vi/HanBb8FonWs/maxresdefault.jpg"
                      },
                      "formats": [
                        {
                          "type": "video",
                          "format": "144p",
                          "filesize": 6967209
                        },
                        {
                          "type": "video",
                          "format": "360p",
                          "filesize": 21096358
                        },
                        {
                          "type": "video",
                          "format": "720p",
                          "filesize": 60448393
                        }
                      ]
                    }
                  },
                  "alt": {
                    "summary": "response for a post",
                    "value": {
                      "ok": true,
                      "is_post": true,
                      "post_id": "UgkxB7POmB4C7U0I3kIEWRZpYfE2t-ieP9CA",
                      "url": "https://www.youtube.com/post/UgkxB7POmB4C7U0I3kIEWRZpYfE2t-ieP9CA",
                      "type": "image",
                      "author": {
                        "name": "MrBeast",
                        "channel_id": "UCX6OQ3DkcsbYNE6H8uQQuVA",
                        "handle": "@MrBeast",
                        "url": "https://www.youtube.com/channel/UCX6OQ3DkcsbYNE6H8uQQuVA",
                        "avatar": "https://yt3.googleusercontent.com/nxYrc_1_2f77DoBadyxMTmv7ZpRZapHR5jbuYe7PlPd5cIRJxtNNEYyOC0ZsxaDyJJzXrnJiuDE=s900-c-k-c0x00ffffff-no-rj-mo"
                      },
                      "text": "Some more fun wedding photos 🥰",
                      "links": [],
                      "hashtags": [],
                      "published_at": "2026-07-23T17:56:09Z",
                      "published_text": "2 months ago",
                      "edited": false,
                      "likes": 3432414,
                      "media": [
                        {
                          "type": "image",
                          "download_url": "https://lh3.googleusercontent.com/bFmb7RbyvsNTUS3otE4oc2tqI5CZyl3apwKmjnqnTjFuv1mwxWG7hWlZCuiWlRYrd3oCd_nAtBWVsw=s0",
                          "preview_url": "https://yt3.ggpht.com/bFmb7RbyvsNTUS3otE4oc2tqI5CZyl3apwKmjnqnTjFuv1mwxWG7hWlZCuiWlRYrd3oCd_nAtBWVsw=s1024-rj",
                          "width": 2641,
                          "height": 3734
                        },
                        {
                          "type": "image",
                          "download_url": "https://lh3.googleusercontent.com/1Oxcyk2wshlCOoZYiTWUFoixDaomfdtlcIKiGv_ozoT4Lfs9CZx-3VTxbNeQlJOOV_h7CdWjWF8QIA=s0",
                          "preview_url": "https://yt3.ggpht.com/1Oxcyk2wshlCOoZYiTWUFoixDaomfdtlcIKiGv_ozoT4Lfs9CZx-3VTxbNeQlJOOV_h7CdWjWF8QIA=s1024-rj",
                          "width": 1536,
                          "height": 2048
                        }
                      ],
                      "poll": null,
                      "playlist": null,
                      "shared_post": null
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Failure"
          },
          "401": {
            "$ref": "#/components/responses/Failure"
          },
          "422": {
            "$ref": "#/components/responses/ValidationError"
          },
          "429": {
            "$ref": "#/components/responses/Failure"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/Overloaded"
          }
        },
        "parameters": [
          {
            "name": "url",
            "in": "query",
            "required": true,
            "description": "youtube video or community post url",
            "schema": {
              "type": "string"
            }
          }
        ]
      }
    },
    "/v1/youtube/search": {
      "get": {
        "operationId": "youtube_search",
        "summary": "search youtube",
        "description": "paged search results with thumbnails and durations.",
        "tags": [
          "youtube"
        ],
        "x-credits": 2,
        "x-credits-on-failure": 0.1,
        "responses": {
          "200": {
            "description": "success - the body always carries ok: true",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok"
                  ],
                  "additionalProperties": true,
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    }
                  }
                },
                "example": {
                  "ok": true,
                  "page": 1,
                  "results": [
                    {
                      "video_id": "HgLfYfJtc8M",
                      "title": "The Weeknd - One Of The Girls",
                      "duration": "4:05",
                      "thumbnail": "https://i.ytimg.com/vi/HgLfYfJtc8M/mqdefault.jpg",
                      "thumbnail_max": "https://i.ytimg.com/vi/HgLfYfJtc8M/maxresdefault.jpg"
                    },
                    {
                      "video_id": "p8_ugAjWI5I",
                      "title": "The Weeknd - São Paulo",
                      "duration": "5:02",
                      "thumbnail": "https://i.ytimg.com/vi/p8_ugAjWI5I/mqdefault.jpg",
                      "thumbnail_max": "https://i.ytimg.com/vi/p8_ugAjWI5I/maxresdefault.jpg"
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Failure"
          },
          "401": {
            "$ref": "#/components/responses/Failure"
          },
          "422": {
            "$ref": "#/components/responses/ValidationError"
          },
          "429": {
            "$ref": "#/components/responses/Failure"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/Overloaded"
          }
        },
        "parameters": [
          {
            "name": "query",
            "in": "query",
            "required": true,
            "description": "what to search for",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "page",
            "in": "query",
            "required": true,
            "description": "1-based page number",
            "schema": {
              "type": "integer"
            }
          }
        ]
      }
    },
    "/v1/youtube/download": {
      "post": {
        "operationId": "youtube_download",
        "summary": "a direct link to the file",
        "description": "returns a `download_url` that points at our tunnel and is valid for 10 minutes. 1440p and 2160p cost 25 credits instead of 15 - they are bigger files and heavier to prepare.",
        "tags": [
          "youtube"
        ],
        "x-credits": 15,
        "x-credits-on-failure": 0.1,
        "responses": {
          "200": {
            "description": "success - the body always carries ok: true",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok"
                  ],
                  "additionalProperties": true,
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    }
                  }
                },
                "example": {
                  "ok": true,
                  "video_id": "6dG1WWjew8s",
                  "duration": 577,
                  "filename": "THE POWER OF TESTOSTERONE - LITVINOV FIT (2160p, av1, youtube).mp4",
                  "download_url": "https://api.fastsaver.io/v1/tunnel?id=UJLUoLGd1m2t1ScSTW1Lw...",
                  "thumbnails": {
                    "low": "https://i.ytimg.com/vi/6dG1WWjew8s/mqdefault.jpg",
                    "max": "https://i.ytimg.com/vi/6dG1WWjew8s/maxresdefault.jpg"
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Failure"
          },
          "401": {
            "$ref": "#/components/responses/Failure"
          },
          "422": {
            "$ref": "#/components/responses/ValidationError"
          },
          "429": {
            "$ref": "#/components/responses/Failure"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/Overloaded"
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "url",
                  "format"
                ],
                "properties": {
                  "url": {
                    "type": "string",
                    "description": "youtube video url"
                  },
                  "format": {
                    "type": "string",
                    "description": "audio, mp3, m4a, 144p, 240p, 360p, 480p, 720p, 1080p, 1440p or 2160p"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/youtube/audio/tg-bot": {
      "post": {
        "operationId": "youtube_audio_tg_bot",
        "summary": "audio straight into your telegram bot",
        "description": "we send the audio to your bot and hand back a `file_id`, so your bot forwards a file it already owns instead of uploading one. 7 credits when we have the track cached, 15 when we have to fetch it first. send `X-Return-File-Id: false` to get `channel_id` and `message_id` instead.",
        "tags": [
          "youtube"
        ],
        "x-credits": 7,
        "x-credits-on-failure": 0.1,
        "responses": {
          "200": {
            "description": "success - the body always carries ok: true",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok"
                  ],
                  "additionalProperties": true,
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    }
                  }
                },
                "example": {
                  "ok": true,
                  "file_id": "CQACAgIAAxkDAAIVKWk..."
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Failure"
          },
          "401": {
            "$ref": "#/components/responses/Failure"
          },
          "422": {
            "$ref": "#/components/responses/ValidationError"
          },
          "429": {
            "$ref": "#/components/responses/Failure"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/Overloaded"
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "video_id",
                  "bot_username"
                ],
                "properties": {
                  "video_id": {
                    "type": "string",
                    "description": "youtube video id (not the full url)"
                  },
                  "bot_username": {
                    "type": "string",
                    "description": "your bot, with the @"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/shazam/top": {
      "get": {
        "operationId": "shazam_top",
        "summary": "top charts by country",
        "description": "the current chart for a country, paged.",
        "tags": [
          "shazam"
        ],
        "x-credits": 1,
        "x-credits-on-failure": 0.1,
        "responses": {
          "200": {
            "description": "success - the body always carries ok: true",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok"
                  ],
                  "additionalProperties": true,
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    }
                  }
                },
                "example": {
                  "ok": true,
                  "results": [
                    {
                      "video_id": "7nVctvQVz0U",
                      "title": "Taylor Swift - The Fate of Ophelia",
                      "duration": "3:47",
                      "thumbnail_url": "https://i.ytimg.com/vi/7nVctvQVz0U/mqdefault.jpg"
                    },
                    {
                      "video_id": "9_bTl2vvYQg",
                      "title": "HUNTR/X - Golden",
                      "duration": "3:15",
                      "thumbnail_url": "https://i.ytimg.com/vi/9_bTl2vvYQg/mqdefault.jpg"
                    },
                    {
                      "video_id": "ZhM1BddhZ1c",
                      "title": "El Bogueto - Cuando No Era Cantante",
                      "duration": "3:32",
                      "thumbnail_url": "https://i.ytimg.com/vi/ZhM1BddhZ1c/mqdefault.jpg"
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Failure"
          },
          "401": {
            "$ref": "#/components/responses/Failure"
          },
          "422": {
            "$ref": "#/components/responses/ValidationError"
          },
          "429": {
            "$ref": "#/components/responses/Failure"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/Overloaded"
          }
        },
        "parameters": [
          {
            "name": "country",
            "in": "query",
            "required": true,
            "description": "iso country code, or `world`",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "page",
            "in": "query",
            "required": true,
            "description": "1-based page number",
            "schema": {
              "type": "integer"
            }
          }
        ]
      }
    },
    "/v1/shazam/identify": {
      "post": {
        "operationId": "shazam_identify",
        "summary": "name that track",
        "description": "send an audio clip as multipart form data and get the track back. up to 50 mb; a few seconds of audio is enough.",
        "tags": [
          "shazam"
        ],
        "x-credits": 5,
        "x-credits-on-failure": 0.1,
        "responses": {
          "200": {
            "description": "success - the body always carries ok: true",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok"
                  ],
                  "additionalProperties": true,
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    }
                  }
                },
                "example": {
                  "ok": true,
                  "id": "102147933",
                  "title": "Сердце пацана",
                  "artist": "YARMAK",
                  "thumbnail": "https://is1-ssl.mzs...",
                  "lyrics": "...",
                  "results": [
                    {
                      "video_id": "gDLlDcvTveU",
                      "title": "Inna - Amazing",
                      "duration": "3:51",
                      "thumbnail": "https://i.ytimg.com/vi/gDLlDcvTveU/mqdefault.jpg",
                      "thumbnail_max": "https://i.ytimg.com/vi/gDLlDcvTveU/maxresdefault.jpg"
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Failure"
          },
          "401": {
            "$ref": "#/components/responses/Failure"
          },
          "422": {
            "$ref": "#/components/responses/ValidationError"
          },
          "429": {
            "$ref": "#/components/responses/Failure"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/Overloaded"
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "file"
                ],
                "properties": {
                  "file": {
                    "type": "string",
                    "description": "audio clip, multipart/form-data"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/balance": {
      "get": {
        "operationId": "balance",
        "summary": "plan, credits and rate limit",
        "description": "free, and deliberately not written to your request log. poll it as often as you like, within its own 60/min budget.",
        "tags": [
          "account"
        ],
        "x-credits": 0,
        "x-credits-on-failure": 0,
        "responses": {
          "200": {
            "description": "success - the body always carries ok: true",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok"
                  ],
                  "additionalProperties": true,
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    }
                  }
                },
                "example": {
                  "ok": true,
                  "plan": "Pro",
                  "credits": 98500,
                  "plan_credits": 100000,
                  "rpm_limit": 60,
                  "balance": "12.50",
                  "auto_renew": true,
                  "plan_expires_at": "2026-08-19T19:56:37+00:00",
                  "expire_label": "Ends in 30 days"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Failure"
          },
          "401": {
            "$ref": "#/components/responses/Failure"
          },
          "422": {
            "$ref": "#/components/responses/ValidationError"
          },
          "429": {
            "$ref": "#/components/responses/Failure"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/Overloaded"
          }
        },
        "parameters": []
      }
    }
  }
}
