This commit is contained in:
krau
2026-09-03 00:27:48 +00:00
parent 06617f0235
commit f0b27d4c06
5 changed files with 49 additions and 23 deletions
+23 -10
View File
@@ -63,10 +63,10 @@ Authorization: Bearer <your-token>
[api] enable = true host = "0.0.0.0" # 监听地址,默认 0.0.0.0 port = 8080 # 监听端口,默认 8080 token = "your-token" # 鉴权 Token,强烈建议设置 也可通过环境变量覆盖(前缀 SAVEANY_):
环境变量 对应配置项 SAVEANY_API_ENABLE api.enable SAVEANY_API_HOST api.host SAVEANY_API_PORT api.port SAVEANY_API_TOKEN api.token 若 `token` 为空,API 服务将**不进行任何鉴权**即可访问,存在安全风险。 鉴权 # 当配置了 token 时,所有 API 请求均需在 HTTP 请求头中携带 Bearer Token
Authorization: Bearer <your-token> 鉴权失败时返回 401
{ "error": "unauthorized", "message": "invalid token" } 错误响应格式 # 所有错误均使用统一的 JSON 格式:'><meta property="og:locale" content="zh"><meta property="og:type" content="article"><meta property="article:section" content="usage"><meta property="article:modified_time" content="2026-03-11T19:37:25+08:00"><title>HTTP API | Save Any Bot</title><link rel=icon href=/favicon.png><link rel=manifest href=/manifest.json><link rel=canonical href=https://sabot.unv.app/usage/api/><link rel=alternate hreflang=en href=https://sabot.unv.app/en/usage/api/ title="HTTP API"><link rel=stylesheet href=/book.min.a22f4c7d8c2bdc5e3d6e34ba11cb59ab50ea5772594e71305bfd5a595dc78b7e.css integrity="sha256-oi9MfYwr3F49bjS6EctZq1DqV3JZTnEwW/1aWV3Hi34=" crossorigin=anonymous></head><body dir=ltr><input type=checkbox class="hidden toggle" id=menu-control>
{ "error": "unauthorized", "message": "invalid token" } 错误响应格式 # 所有错误均使用统一的 JSON 格式:'><meta property="og:locale" content="zh"><meta property="og:type" content="article"><meta property="article:section" content="usage"><meta property="article:modified_time" content="2026-09-02T14:52:34+07:00"><title>HTTP API | Save Any Bot</title><link rel=icon href=/favicon.png><link rel=manifest href=/manifest.json><link rel=canonical href=https://sabot.unv.app/usage/api/><link rel=alternate hreflang=en href=https://sabot.unv.app/en/usage/api/ title="HTTP API"><link rel=stylesheet href=/book.min.a22f4c7d8c2bdc5e3d6e34ba11cb59ab50ea5772594e71305bfd5a595dc78b7e.css integrity="sha256-oi9MfYwr3F49bjS6EctZq1DqV3JZTnEwW/1aWV3Hi34=" crossorigin=anonymous></head><body dir=ltr><input type=checkbox class="hidden toggle" id=menu-control>
<input type=checkbox class="hidden toggle" id=toc-control><main class="container flex"><aside class=book-menu><div class=book-menu-content><nav><h2 class=book-brand><a class="flex align-center" href=/><img src=/logo.png alt=Logo class=book-icon><span>Save Any Bot</span></a></h2><ul class=book-languages><li><input type=checkbox id=languages class=toggle>
<label for=languages class=flex><a role=button class="flex flex-auto"><img src=/svg/translate.svg class=book-icon alt=Languages>
简体中文</a></label><ul><li><a href=/en/usage/api/>English</a></li></ul></li></ul><ul><li><a href=https://github.com/krau/SaveAny-Bot target=_blank rel=noopener>🔗 GitHub</a></li></ul><ul><li><span>部署指南</span><ul><li><a href=/deployment/installation/>安装与更新</a></li><li><a href=/deployment/configuration/>配置说明</a><ul><li><a href=/deployment/configuration/storages/>存储端配置</a></li></ul></li></ul></li><li><a href=/usage/>使用帮助</a><ul><li><a href=/usage/silent/>静默模式</a></li><li><a href=/usage/rules/>存储规则</a></li><li><a href=/usage/watch/>监听聊天</a></li><li><a href=/usage/directlinks/>直接下载链接</a></li><li><a href=/usage/aria2/>Aria2 下载</a></li><li><a href=/usage/ytdlp/>yt-dlp 视频下载</a></li><li><a href=/usage/transfer/>存储间传输</a></li><li><a href=/usage/parsers/>转存 Telegram 之外的文件</a></li><li><a href=/usage/config/>文件命名与重名策略</a></li><li><a href=/usage/api/ class=active>HTTP API</a></li><li><a href=/usage/cli/>命令行子命令</a></li></ul></li><li><a href=/help/>常见问题</a><ul></ul></li><li><a href=/contribute/>参与开发</a><ul></ul></li></ul></nav><script>(function(){var e=document.querySelector("aside .book-menu-content");addEventListener("beforeunload",function(){localStorage.setItem("menu.scrollTop",e.scrollTop)}),e.scrollTop=localStorage.getItem("menu.scrollTop")})()</script></div></aside><div class=book-page><header class=book-header><div class="flex align-center justify-between"><label for=menu-control><img src=/svg/menu.svg class=book-icon alt=Menu></label><h3>HTTP API</h3><label for=toc-control><img src=/svg/toc.svg class=book-icon alt="Table of Contents"></label></div><aside class="hidden clearfix"><nav id=TableOfContents><ul><li><a href=#启用-api>启用 API</a></li><li><a href=#鉴权>鉴权</a></li><li><a href=#错误响应格式>错误响应格式</a></li><li><a href=#接口列表>接口列表</a><ul><li><a href=#get-health--健康检查>GET /health — 健康检查</a></li><li><a href=#get-apiv1storages--列出存储>GET /api/v1/storages — 列出存储</a></li><li><a href=#get-apiv1task-types--列出支持的任务类型>GET /api/v1/task-types — 列出支持的任务类型</a></li><li><a href=#post-apiv1tasks--创建任务>POST /api/v1/tasks — 创建任务</a></li><li><a href=#get-apiv1tasks--列出所有任务>GET /api/v1/tasks — 列出所有任务</a></li><li><a href=#get-apiv1taskstask_id--查询任务>GET /api/v1/tasks/{task_id} — 查询任务</a></li><li><a href=#delete-apiv1taskstask_id--取消任务>DELETE /api/v1/tasks/{task_id} — 取消任务</a></li></ul></li><li><a href=#任务状态>任务状态</a></li><li><a href=#webhook-回调>Webhook 回调</a></li></ul></nav></aside></header><article class="markdown book-article"><h1 id=http-api>HTTP API
简体中文</a></label><ul><li><a href=/en/usage/api/>English</a></li></ul></li></ul><ul><li><a href=https://github.com/krau/SaveAny-Bot target=_blank rel=noopener>🔗 GitHub</a></li></ul><ul><li><span>部署指南</span><ul><li><a href=/deployment/installation/>安装与更新</a></li><li><a href=/deployment/configuration/>配置说明</a><ul><li><a href=/deployment/configuration/storages/>存储端配置</a></li></ul></li></ul></li><li><a href=/usage/>使用帮助</a><ul><li><a href=/usage/silent/>静默模式</a></li><li><a href=/usage/rules/>存储规则</a></li><li><a href=/usage/watch/>监听聊天</a></li><li><a href=/usage/directlinks/>直接下载链接</a></li><li><a href=/usage/aria2/>Aria2 下载</a></li><li><a href=/usage/ytdlp/>yt-dlp 视频下载</a></li><li><a href=/usage/transfer/>存储间传输</a></li><li><a href=/usage/parsers/>转存 Telegram 之外的文件</a></li><li><a href=/usage/config/>文件命名与重名策略</a></li><li><a href=/usage/api/ class=active>HTTP API</a></li><li><a href=/usage/cli/>命令行子命令</a></li></ul></li><li><a href=/help/>常见问题</a><ul></ul></li><li><a href=/contribute/>参与开发</a><ul></ul></li></ul></nav><script>(function(){var e=document.querySelector("aside .book-menu-content");addEventListener("beforeunload",function(){localStorage.setItem("menu.scrollTop",e.scrollTop)}),e.scrollTop=localStorage.getItem("menu.scrollTop")})()</script></div></aside><div class=book-page><header class=book-header><div class="flex align-center justify-between"><label for=menu-control><img src=/svg/menu.svg class=book-icon alt=Menu></label><h3>HTTP API</h3><label for=toc-control><img src=/svg/toc.svg class=book-icon alt="Table of Contents"></label></div><aside class="hidden clearfix"><nav id=TableOfContents><ul><li><a href=#启用-api>启用 API</a></li><li><a href=#鉴权>鉴权</a></li><li><a href=#错误响应格式>错误响应格式</a></li><li><a href=#接口列表>接口列表</a><ul><li><a href=#get-health--健康检查>GET /health — 健康检查</a></li><li><a href=#get-apiv1storages--列出存储>GET /api/v1/storages — 列出存储</a></li><li><a href=#get-apiv1task-types--列出支持的任务类型>GET /api/v1/task-types — 列出支持的任务类型</a></li><li><a href=#get-apiv1media-metadata--媒体元数据查询>GET /api/v1/media-metadata — 媒体元数据查询</a></li><li><a href=#post-apiv1tasks--创建任务>POST /api/v1/tasks — 创建任务</a></li><li><a href=#get-apiv1tasks--列出所有任务>GET /api/v1/tasks — 列出所有任务</a></li><li><a href=#get-apiv1taskstask_id--查询任务>GET /api/v1/tasks/{task_id} — 查询任务</a></li><li><a href=#delete-apiv1taskstask_id--取消任务>DELETE /api/v1/tasks/{task_id} — 取消任务</a></li></ul></li><li><a href=#任务状态>任务状态</a></li><li><a href=#webhook-回调>Webhook 回调</a></li></ul></nav></aside></header><article class="markdown book-article"><h1 id=http-api>HTTP API
<a class=anchor href=#http-api>#</a></h1><p>SaveAny-Bot 提供了一套 HTTP API,允许你通过程序化方式创建下载/转存任务、查询任务状态、取消任务等,无需通过 Telegram 操作。</p><h2 id=启用-api>启用 API
<a class=anchor href=#%e5%90%af%e7%94%a8-api>#</a></h2><p><code>config.toml</code> 中添加或修改以下配置:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-toml data-lang=toml><span style=display:flex><span>[<span style=color:#a6e22e>api</span>]
</span></span><span style=display:flex><span><span style=color:#a6e22e>enable</span> = <span style=color:#66d9ef>true</span>
@@ -103,7 +103,17 @@ Authorization: Bearer <your-token> 鉴权失败时返回 401
</span></span><span style=display:flex><span> <span style=color:#e6db74>&#34;transfer&#34;</span>
</span></span><span style=display:flex><span> ]
</span></span><span style=display:flex><span>}
</span></span></code></pre></div><hr><h3 id=post-apiv1tasks--创建任务>POST /api/v1/tasks — 创建任务
</span></span></code></pre></div><hr><h3 id=get-apiv1media-metadata--媒体元数据查询>GET /api/v1/media-metadata — 媒体元数据查询
<a class=anchor href=#get-apiv1media-metadata--%e5%aa%92%e4%bd%93%e5%85%83%e6%95%b0%e6%8d%ae%e6%9f%a5%e8%af%a2>#</a></h3><p>对 Telegram 消息链接、直链音视频地址或其他 yt-dlp 支持的媒体链接进行探测,在不完整下载文件的情况下返回标题、缩略图、上传者和音视频时长等可用元数据。</p><p>请求:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-bash data-lang=bash><span style=display:flex><span>curl -X GET <span style=color:#e6db74>&#34;http://localhost:8080/api/v1/media-metadata?url=https%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3Dxxx&#34;</span> <span style=color:#ae81ff>\
</span></span></span><span style=display:flex><span><span style=color:#ae81ff></span> -H <span style=color:#e6db74>&#34;Authorization: Bearer YOUR_TOKEN&#34;</span>
</span></span></code></pre></div><p>响应:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-json data-lang=json><span style=display:flex><span>{
</span></span><span style=display:flex><span> <span style=color:#f92672>&#34;url&#34;</span>: <span style=color:#e6db74>&#34;https://www.youtube.com/watch?v=xxx&#34;</span>,
</span></span><span style=display:flex><span> <span style=color:#f92672>&#34;title&#34;</span>: <span style=color:#e6db74>&#34;示例标题&#34;</span>,
</span></span><span style=display:flex><span> <span style=color:#f92672>&#34;thumbnail&#34;</span>: <span style=color:#e6db74>&#34;https://example.com/thumb.jpg&#34;</span>,
</span></span><span style=display:flex><span> <span style=color:#f92672>&#34;uploader&#34;</span>: <span style=color:#e6db74>&#34;示例上传者&#34;</span>,
</span></span><span style=display:flex><span> <span style=color:#f92672>&#34;duration_seconds&#34;</span>: <span style=color:#ae81ff>213.0</span>
</span></span><span style=display:flex><span>}
</span></span></code></pre></div><p>当缺少 <code>url</code> 参数时返回 <code>400 invalid_request</code>;当 Telegram、直链探测和 yt-dlp 都无法获取该链接时返回 <code>400 metadata_extraction_failed</code></p><hr><h3 id=post-apiv1tasks--创建任务>POST /api/v1/tasks — 创建任务
<a class=anchor href=#post-apiv1tasks--%e5%88%9b%e5%bb%ba%e4%bb%bb%e5%8a%a1>#</a></h3><p><strong>请求头:</strong></p><pre tabindex=0><code>Content-Type: application/json
Authorization: Bearer &lt;token&gt;
</code></pre><p><strong>请求体:</strong></p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-json data-lang=json><span style=display:flex><span>{
@@ -194,7 +204,7 @@ Authorization: Bearer &lt;token&gt;
</span></span><span style=display:flex><span> }
</span></span><span style=display:flex><span>}
</span></span></code></pre></div><table><thead><tr><th>params 字段</th><th>类型</th><th>必填</th><th>说明</th></tr></thead><tbody><tr><td><code>source_storage</code></td><td>string</td><td></td><td>源存储名</td></tr><tr><td><code>source_path</code></td><td>string</td><td></td><td>源存储中的路径,须包含至少一个文件</td></tr><tr><td><code>target_storage</code></td><td>string</td><td></td><td>目标存储名</td></tr><tr><td><code>target_path</code></td><td>string</td><td></td><td>目标存储中的路径</td></tr></tbody></table><hr><h3 id=get-apiv1tasks--列出所有任务>GET /api/v1/tasks — 列出所有任务
<a class=anchor href=#get-apiv1tasks--%e5%88%97%e5%87%ba%e6%89%80%e6%9c%89%e4%bb%bb%e5%8a%a1>#</a></h3><p>返回所有 API 创建的任务(仅在内存中保留,重启后清空)。</p><p><strong>响应 <code>200 OK</code></strong></p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-json data-lang=json><span style=display:flex><span>{
<a class=anchor href=#get-apiv1tasks--%e5%88%97%e5%87%ba%e6%89%80%e6%9c%89%e4%bb%bb%e5%8a%a1>#</a></h3><p>返回所有 API 创建的任务,按创建时间由新到旧排序(仅在内存中保留,重启后清空)。已进入终态的任务在最后一次更新 24 小时后也会被清理,清理任务每 10 分钟执行一次。</p><p><strong>响应 <code>200 OK</code></strong></p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-json data-lang=json><span style=display:flex><span>{
</span></span><span style=display:flex><span> <span style=color:#f92672>&#34;tasks&#34;</span>: [
</span></span><span style=display:flex><span> {
</span></span><span style=display:flex><span> <span style=color:#f92672>&#34;task_id&#34;</span>: <span style=color:#e6db74>&#34;abc123xyz&#34;</span>,
@@ -209,18 +219,21 @@ Authorization: Bearer &lt;token&gt;
</span></span><span style=display:flex><span> <span style=color:#f92672>&#34;progress&#34;</span>: {
</span></span><span style=display:flex><span> <span style=color:#f92672>&#34;total_bytes&#34;</span>: <span style=color:#ae81ff>10485760</span>,
</span></span><span style=display:flex><span> <span style=color:#f92672>&#34;downloaded_bytes&#34;</span>: <span style=color:#ae81ff>5242880</span>,
</span></span><span style=display:flex><span> <span style=color:#f92672>&#34;percent&#34;</span>: <span style=color:#ae81ff>50.0</span>
</span></span><span style=display:flex><span> <span style=color:#f92672>&#34;total_files&#34;</span>: <span style=color:#ae81ff>3</span>,
</span></span><span style=display:flex><span> <span style=color:#f92672>&#34;downloaded_files&#34;</span>: <span style=color:#ae81ff>1</span>,
</span></span><span style=display:flex><span> <span style=color:#f92672>&#34;percent&#34;</span>: <span style=color:#ae81ff>50.0</span>,
</span></span><span style=display:flex><span> <span style=color:#f92672>&#34;speed_mbps&#34;</span>: <span style=color:#ae81ff>12.5</span>
</span></span><span style=display:flex><span> }
</span></span><span style=display:flex><span> }
</span></span><span style=display:flex><span> ],
</span></span><span style=display:flex><span> <span style=color:#f92672>&#34;total&#34;</span>: <span style=color:#ae81ff>1</span>
</span></span><span style=display:flex><span>}
</span></span></code></pre></div><p><code>progress</code> 字段<code>total_bytes > 0</code> 时出现<code>error</code> 字段仅在有错误时出现。</p><hr><h3 id=get-apiv1taskstask_id--查询任务>GET /api/v1/tasks/{task_id} — 查询任务
</span></span></code></pre></div><p><code>progress</code> 字段在 <code>total_bytes</code><code>total_files</code> 大于 0 时出现,其内部字段为 0 时会被省略。<code>percent</code> 在已知字节总量时按字节计算,否则回退为按文件数计算。<code>speed_mbps</code> 是任务开始运行以来的平均速度,而非瞬时速度<code>error</code> 字段仅在有错误时出现。</p><hr><h3 id=get-apiv1taskstask_id--查询任务>GET /api/v1/tasks/{task_id} — 查询任务
<a class=anchor href=#get-apiv1taskstask_id--%e6%9f%a5%e8%af%a2%e4%bb%bb%e5%8a%a1>#</a></h3><p><strong>路径参数:</strong> <code>task_id</code> — 创建任务时返回的 ID。</p><p><strong>响应 <code>200 OK</code></strong> 同上列表中的单个任务对象。</p><p><strong>错误响应:</strong></p><ul><li><code>400 invalid_request</code> — 路径中未提供 task_id</li><li><code>404 task_not_found</code> — 任务不存在</li></ul><hr><h3 id=delete-apiv1taskstask_id--取消任务>DELETE /api/v1/tasks/{task_id} — 取消任务
<a class=anchor href=#delete-apiv1taskstask_id--%e5%8f%96%e6%b6%88%e4%bb%bb%e5%8a%a1>#</a></h3><p><strong>路径参数:</strong> <code>task_id</code></p><p><strong>响应 <code>200 OK</code></strong></p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-json data-lang=json><span style=display:flex><span>{ <span style=color:#f92672>&#34;message&#34;</span>: <span style=color:#e6db74>&#34;task cancelled successfully&#34;</span> }
</span></span></code></pre></div><p><strong>错误响应:</strong></p><ul><li><code>400 invalid_request</code> — 路径中未提供 task_id</li><li><code>404 task_not_found</code> — 任务不存在</li><li><code>500 cancel_failed</code> — 取消操作失败</li></ul><hr><h2 id=任务状态>任务状态
<a class=anchor href=#%e4%bb%bb%e5%8a%a1%e7%8a%b6%e6%80%81>#</a></h2><table><thead><tr><th>状态值</th><th>含义</th></tr></thead><tbody><tr><td><code>queued</code></td><td>已入队,等待执行</td></tr><tr><td><code>running</code></td><td>正在执行</td></tr><tr><td><code>completed</code></td><td>已成功完成</td></tr><tr><td><code>failed</code></td><td>执行失败</td></tr><tr><td><code>cancelled</code></td><td>已通过 DELETE 接口取消</td></tr></tbody></table><hr><h2 id=webhook-回调>Webhook 回调
<a class=anchor href=#webhook-%e5%9b%9e%e8%b0%83>#</a></h2><p>创建任务时可设置 <code>webhook</code> 字段。当任务进入终态(<code>completed</code><code>failed</code><code>cancelled</code>时,Bot 会向该地址发送一个 <code>POST</code> 请求。</p><p><strong>回调请求头:</strong></p><pre tabindex=0><code>Content-Type: application/json
<a class=anchor href=#webhook-%e5%9b%9e%e8%b0%83>#</a></h2><p>创建任务时可设置 <code>webhook</code> 字段。当任务进入 <code>completed</code><code>failed</code> 状态时,Bot 会向该地址发送一个 <code>POST</code> 请求。</p><blockquote class="book-hint info">被取消的任务**不会**触发 Webhook——取消操作的发起方已经知晓结果。每个任务最多只会发送一次回调。</blockquote><p>回调为异步发送,不会因为回调地址响应缓慢或不可达而阻塞任务。</p><p><strong>回调请求头:</strong></p><pre tabindex=0><code>Content-Type: application/json
User-Agent: SaveAny-Bot/1.0
</code></pre><p><strong>回调请求体:</strong></p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-json data-lang=json><span style=display:flex><span>{
</span></span><span style=display:flex><span> <span style=color:#f92672>&#34;task_id&#34;</span>: <span style=color:#e6db74>&#34;abc123xyz&#34;</span>,
@@ -231,6 +244,6 @@ User-Agent: SaveAny-Bot/1.0
</span></span><span style=display:flex><span> <span style=color:#f92672>&#34;completed_at&#34;</span>: <span style=color:#e6db74>&#34;2026-03-11T10:01:00Z&#34;</span>,
</span></span><span style=display:flex><span> <span style=color:#f92672>&#34;error&#34;</span>: <span style=color:#e6db74>&#34;&#34;</span>
</span></span><span style=display:flex><span>}
</span></span></code></pre></div><p><code>completed_at</code> 仅在状态为 <code>completed</code><code>failed</code> 时出现。<code>error</code> 仅在有错误时出现。</p><p><strong>重试机制:</strong> 最多试 3 次重试间隔依次为 1 秒、2 秒、3 秒。每次请求超时为 30 秒。</p></article><footer class=book-footer><div class="flex flex-wrap justify-between"><div><a class="flex align-center" href=https://github.com/krau/saveany-bot/commit/38355dfd142f0f1a819a8837875b33da0d3a81b7 title='最后修改者 krau | 2026/03/11' target=_blank rel=noopener><img src=/svg/calendar.svg class=book-icon alt>
<span>2026/03/11</span></a></div><div><a class="flex align-center" href=https://github.com/krau/saveany-bot/edit/main/docs/content/zh/usage/api.md target=_blank rel=noopener><img src=/svg/edit.svg class=book-icon alt>
<span>编辑本页</span></a></div></div><script>(function(){function e(e){const t=window.getSelection(),n=document.createRange();n.selectNodeContents(e),t.removeAllRanges(),t.addRange(n)}document.querySelectorAll("pre code").forEach(t=>{t.addEventListener("click",function(){if(window.getSelection().toString())return;e(t.parentElement),navigator.clipboard&&navigator.clipboard.writeText(t.parentElement.textContent)})})})()</script></footer><div class=book-comments></div><label for=menu-control class="hidden book-menu-overlay"></label></div><aside class=book-toc><div class=book-toc-content><nav id=TableOfContents><ul><li><a href=#启用-api>启用 API</a></li><li><a href=#鉴权>鉴权</a></li><li><a href=#错误响应格式>错误响应格式</a></li><li><a href=#接口列表>接口列表</a><ul><li><a href=#get-health--健康检查>GET /health — 健康检查</a></li><li><a href=#get-apiv1storages--列出存储>GET /api/v1/storages — 列出存储</a></li><li><a href=#get-apiv1task-types--列出支持的任务类型>GET /api/v1/task-types — 列出支持的任务类型</a></li><li><a href=#post-apiv1tasks--创建任务>POST /api/v1/tasks — 创建任务</a></li><li><a href=#get-apiv1tasks--列出所有任务>GET /api/v1/tasks — 列出所有任务</a></li><li><a href=#get-apiv1taskstask_id--查询任务>GET /api/v1/tasks/{task_id} — 查询任务</a></li><li><a href=#delete-apiv1taskstask_id--取消任务>DELETE /api/v1/tasks/{task_id} — 取消任务</a></li></ul></li><li><a href=#任务状态>任务状态</a></li><li><a href=#webhook-回调>Webhook 回调</a></li></ul></nav></div></aside></main></body></html>
</span></span></code></pre></div><p><code>completed_at</code> 仅在状态为 <code>completed</code><code>failed</code> 时出现。<code>error</code> 仅在有错误时出现。</p><p><strong>重试机制:</strong> 最多试 3 次。响应非 2xx 或请求出错时会重试间隔依次为 100 毫秒、400 毫秒。每次请求超时为 30 秒。</p></article><footer class=book-footer><div class="flex flex-wrap justify-between"><div><a class="flex align-center" href=https://github.com/krau/saveany-bot/commit/ae0ec2fba82bc7d7177db7fd1b3724973686b956 title='最后修改者 Ilham Syahid S | 2026/09/02' target=_blank rel=noopener><img src=/svg/calendar.svg class=book-icon alt>
<span>2026/09/02</span></a></div><div><a class="flex align-center" href=https://github.com/krau/saveany-bot/edit/main/docs/content/zh/usage/api.md target=_blank rel=noopener><img src=/svg/edit.svg class=book-icon alt>
<span>编辑本页</span></a></div></div><script>(function(){function e(e){const t=window.getSelection(),n=document.createRange();n.selectNodeContents(e),t.removeAllRanges(),t.addRange(n)}document.querySelectorAll("pre code").forEach(t=>{t.addEventListener("click",function(){if(window.getSelection().toString())return;e(t.parentElement),navigator.clipboard&&navigator.clipboard.writeText(t.parentElement.textContent)})})})()</script></footer><div class=book-comments></div><label for=menu-control class="hidden book-menu-overlay"></label></div><aside class=book-toc><div class=book-toc-content><nav id=TableOfContents><ul><li><a href=#启用-api>启用 API</a></li><li><a href=#鉴权>鉴权</a></li><li><a href=#错误响应格式>错误响应格式</a></li><li><a href=#接口列表>接口列表</a><ul><li><a href=#get-health--健康检查>GET /health — 健康检查</a></li><li><a href=#get-apiv1storages--列出存储>GET /api/v1/storages — 列出存储</a></li><li><a href=#get-apiv1task-types--列出支持的任务类型>GET /api/v1/task-types — 列出支持的任务类型</a></li><li><a href=#get-apiv1media-metadata--媒体元数据查询>GET /api/v1/media-metadata — 媒体元数据查询</a></li><li><a href=#post-apiv1tasks--创建任务>POST /api/v1/tasks — 创建任务</a></li><li><a href=#get-apiv1tasks--列出所有任务>GET /api/v1/tasks — 列出所有任务</a></li><li><a href=#get-apiv1taskstask_id--查询任务>GET /api/v1/tasks/{task_id} — 查询任务</a></li><li><a href=#delete-apiv1taskstask_id--取消任务>DELETE /api/v1/tasks/{task_id} — 取消任务</a></li></ul></li><li><a href=#任务状态>任务状态</a></li><li><a href=#webhook-回调>Webhook 回调</a></li></ul></nav></div></aside></main></body></html>