接入文档
把版本检查接进桌面软件,只需要一次 GET 请求。下面从零开始,包含完整的字段说明、错误处理建议和四种语言的可用代码。
三分钟接入
-
注册并创建应用
打开 控制台,注册后点「新建应用」,系统会生成一串app_key,形如app_8ee7d6c2…。 -
把 app_key 写进客户端
它只是个标识,不是密码,可以打包进 exe。但它不能用来发布版本——发布需要登录后的 token。 -
启动时请求一次
用下面的接口查一次,拿到has_update决定要不要提示用户。
查询接口
GET https://bump.tinyaii.cn/api/v1/check?app_key=app_xxx¤t_version=1.0.0
参数
| 参数 | 必填 | 说明 |
|---|---|---|
app_key | 是 | 控制台里每个应用的唯一标识 |
current_version | 是 | 客户端当前的版本号,纯数字点分,例如 1.0.2 |
channel | 否 | 发布通道,不传默认 stable。内测客户端传 beta |
响应
没有新版本时只返回一个字段:
{"has_update": false}
有新版本时:
{
"has_update": true,
"latest_version": "1.0.10",
"release_notes": "修复了崩溃问题",
"force_update": false,
"publish_time": "2026-10-28",
"platform": "windows",
"download_url": "https://example.com/app-1.0.10.exe"
}
| 字段 | 类型 | 说明 |
|---|---|---|
has_update | bool | 有没有新版本。这是唯一保证存在的字段 |
latest_version | string | 最新版本号,has_update 为 false 时不会出现 |
release_notes | string | 更新说明,发布时没填就是空字符串 |
force_update | bool | 是否必须更新,规则见强制更新 |
publish_time | string | 发布日期,格式 YYYY-MM-DD,东八区 |
platform | string | 发布时标的平台,没标就是 all;可能为空 |
download_url | string | 下载地址,发布时没填就没有这个字段 |
sha256 | string | 安装包哈希,发布时没填就没有。只用于发现文件损坏,不是安全防线 |
channel | string | 这个版本属于哪个通道,通常是 stable 或 beta |
platform 和 download_url 当成可选,不要因为缺字段就崩掉。
错误处理
| 状态码 | error | 含义 | 客户端该怎么做 |
|---|---|---|---|
| 200 | — | 正常 | 读 has_update |
| 400 | invalid_parameter | 缺参数 | 你代码写错了,看日志修 |
| 400 | invalid_version | 版本号格式不对 | 检查是不是传了 v1.0.0 或 1.0.0-beta |
| 404 | app_key_not_found | 没有这个 app_key | key 写错了或应用被删了,不要弹窗 |
| 429 | too_many_requests | 你的 IP 请求太频繁 | 看 Retry-After 等几秒再试;正常使用不会触发 |
| 500 | internal_error | 服务端故障 | 静默跳过,下次启动再说 |
建议给请求加 3 秒超时。网络慢的地区,5 秒也够,但不要不设上限——否则断网时启动会卡住。
强制更新
force_update 不是一个「这个版本是否强制」的开关,而是一条下限。
你在控制台里设「最低支持版本 1.0.2」,那么:
| 客户端版本 | 最新版 | 返回 |
|---|---|---|
| 1.0.0 | 1.0.10 | has_update: true,force_update: true |
| 1.0.5 | 1.0.10 | has_update: true,force_update: false |
| 1.0.10 | 1.0.10 | has_update: false |
| 2.0.0(内测版) | 1.0.10 | has_update: false —— 永远不提示降级 |
好处是你不用为每个版本单独配策略。设一次下限,所有比它老的客户端自动被强制,比它新的用户看到的还是可选更新。
发布通道
想先给少数人试新版本,又不想让普通用户看到,用通道。每个通道各自维护一个「最新版」。
| 客户端 | 请求 | 拿到 |
|---|---|---|
| 普通用户 | check?app_key=…¤t_version=1.0.0 | stable 的最新版 |
| 内测用户 | check?app_key=…¤t_version=1.0.0&channel=beta | beta 的最新版 |
发布时带上 channel,不传就是 stable。
min_supported_version,或者等它转正。
测好了想让所有人用?把那个版本改成 stable 就行——它会自动成为 stable 的最新版,原来的退位。 版本号在一个应用内唯一,不会出现「同一个 1.0.2 既是 beta 又是 stable」的情况。
版本号规则
- 2 到 4 段,每段都是纯数字:
1.0、1.0.2、1.2.3.4都行 - 不接受
v1.0.0、1.0.0-beta、1.0.0.0.0,会返回 400 - 按数字逐段比较,不是按字符串:
1.0.9小于1.0.10 - 段数不同时补 0:
1.0等于1.0.0
current_version 用同一个来源,别手写两遍。
代码示例
C#
using System.Net.Http.Json; using System.Text.Json.Serialization; public class UpdateInfo { [JsonPropertyName("has_update")] public bool HasUpdate { get; set; } [JsonPropertyName("latest_version")] public string? LatestVersion { get; set; } [JsonPropertyName("release_notes")] public string? ReleaseNotes { get; set; } [JsonPropertyName("force_update")] public bool ForceUpdate { get; set; } [JsonPropertyName("publish_time")] public string? PublishTime { get; set; } [JsonPropertyName("download_url")] public string? DownloadUrl { get; set; } } public static class Updater { // 从控制台复制,或写成常量由打包脚本替换 private const string AppKey = "app_xxx"; private static readonly HttpClient Http = new() { Timeout = TimeSpan.FromSeconds(3) }; public static async Task<UpdateInfo?> CheckAsync(string currentVersion) { try { var url = $"https://bump.tinyaii.cn/api/v1/check?app_key={AppKey}¤t_version={currentVersion}"; return await Http.GetFromJsonAsync<UpdateInfo>(url); } catch { return null; // 断网、超时、服务挂了:当作没有更新 } } }
Python
import requests APP_KEY = "app_xxx" URL = "https://bump.tinyaii.cn/api/v1/check" def check_update(current_version: str) -> dict | None: """返回 None 表示查不到,调用方按「没有更新」处理。""" try: r = requests.get( URL, params={"app_key": APP_KEY, "current_version": current_version}, timeout=3, ) r.raise_for_status() return r.json() except Exception: return None
JavaScript / TypeScript
const APP_KEY = 'app_xxx' async function checkUpdate(currentVersion) { const url = new URL('https://bump.tinyaii.cn/api/v1/check') url.searchParams.set('app_key', APP_KEY) url.searchParams.set('current_version', currentVersion) try { const res = await fetch(url, { signal: AbortSignal.timeout(3000) }) if (!res.ok) return null return await res.json() } catch { return null } }
Go
type checkResp struct { HasUpdate bool `json:"has_update"` LatestVersion string `json:"latest_version"` ReleaseNotes string `json:"release_notes"` ForceUpdate bool `json:"force_update"` PublishTime string `json:"publish_time"` DownloadURL string `json:"download_url"` } func checkUpdate(appKey, current string) (*checkResp, error) { ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second) defer cancel() u := fmt.Sprintf("https://bump.tinyaii.cn/api/v1/check?app_key=%s¤t_version=%s", appKey, current) req, _ := http.NewRequestWithContext(ctx, http.MethodGet, u, nil) res, err := http.DefaultClient.Do(req) if err != nil { return nil, err } defer res.Body.Close() var out checkResp if err := json.NewDecoder(res.Body).Decode(&out); err != nil { return nil, err } return &out, nil }
自动发版(CI 与 AI)
在控制台点发布适合手动操作。如果你用 tag 发版,或者想让 AI 直接改版本号,用 API 密钥。
1. 创建一个密钥
控制台 → API 密钥 → 创建。勾选权限时只勾需要的——自动发版只要
release:write,别顺手把「删除应用」也勾上。有效期有 7 / 30 / 90 天和永不过期,
默认 30 天:CI 用的密钥定期换一个比设成永久安全。密钥只显示一次,复制完存进仓库的 secret。
2. GitHub Actions
在仓库里配两个东西:secret BUMP_API_KEY 和 variable BUMP_APP_KEY。
# .github/workflows/release.yml name: release on: push: tags: ['v*'] jobs: publish: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: 构建 run: echo "换成你自己的构建命令" - name: 通知 BumpAPI env: BUMP_API_KEY: ${{ secrets.BUMP_API_KEY }} BUMP_APP_KEY: ${{ vars.BUMP_APP_KEY }} run: | VERSION="${GITHUB_REF_NAME#v}" curl -fsS -X POST https://bump.tinyaii.cn/api/admin/release \ -H "X-API-Key: $BUMP_API_KEY" \ -H "Content-Type: application/json" \ -d "{ \"app_key\": \"$BUMP_APP_KEY\", \"new_version\": \"$VERSION\", \"notes\": \"见 release 页面\", \"download_url\": \"https://github.com/$GITHUB_REPOSITORY/releases/tag/$GITHUB_REF_NAME\" }"
curl -f 是关键:接口返回 4xx/5xx 时让这一步直接失败,而不是悄悄跑过去。
发版失败却显示绿色的 CI,比不发版更糟。
3. 让 AI 帮你写
不想自己改 workflow,把下面这段丢给 ChatGPT 或 Claude:
我在用 BumpAPI 做版本检查。这是我的信息: 接口:https://bump.tinyaii.cn app_key:app_xxx API 密钥:bp_xxx(权限只有 release:write) 请帮我写一个 GitHub Actions workflow: 1. 推送 v* tag 时触发 2. 从 tag 里取版本号(去掉 v 前缀) 3. 调 POST /api/admin/release 发布,notes 用本次 commit 信息的前 500 字 4. 密钥从 secrets.BUMP_API_KEY 读,app_key 从 vars.BUMP_APP_KEY 读,都不要写死在文件里 5. 请求失败要让 job 失败,不要吞错 先告诉我要在仓库里配哪些 secret 和 variable,再给完整 yaml。
.env 并加进
.gitignore。泄露了去控制台点撤销,旧密钥立刻失效,换一个新的就好。
4. 让 AI 自己读接口
这里有一份 OpenAPI 3.1 定义: https://bump.tinyaii.cn/openapi.json。 把它交给任何支持 OpenAPI 的工具(ChatGPT Actions、Postman、Apifox、代码生成器), 或者直接让 AI 打开这个 URL,它就能知道每个字段的含义、约束和示例,不用你转述。
更省事的做法:控制台创建密钥成功后,弹窗里有个「复制给 AI 的说明」按钮。 复制出来的那段文字已经带上了密钥、接口地址、OpenAPI 链接和可用的 curl 示例, 粘给 ChatGPT / Claude / Cursor 就能直接干活。
常见问题
用户断网了怎么办?
当作没有更新。不要缓存上次的结果去拦截用户,也不要弹「检查更新失败」——用户开软件是为了用软件,不是为了看你报错。
能不能做增量更新 / 差分包?
不能。这个服务只告诉你「有没有新版本、新版本号和下载地址」,二进制分发要你自己做。想做断点续传和差分,得另找方案。
一个软件有 Windows 和 macOS 两个版本怎么办?
目前最稳的做法是建两个应用,一个叫「XX-Windows」一个叫「XX-macOS」,各自有独立的 app_key 和版本线。
platform 字段现在只是标记,查询接口还没按它过滤——这一点会改进,届时按平台建应用的方式依然兼容。
app_key 能公开吗?会不会被盗用?
能公开。它只能用来查版本,不能发布,也不能读取你的其他数据。真被人拿去刷接口了,控制台里点「重置 key」换一个就行,旧 key 立刻失效。
发布的新版本多久生效?
发布即失效缓存,下一次请求就能看到。HTTP 层有 10 秒的 Cache-Control,如果前面挂了 CDN,最坏情况 10 秒内看到旧值。
请求量有上限吗?
有,按 IP 算:查询接口每分钟 120 次,注册每小时 5 次,登录每分钟 10 次。 正常使用完全碰不到——你的软件启动时查一次,几千台机器共用一个出口 IP 也够。 超了会返回 429 并告诉你还要等几秒,客户端按「没有更新」处理就行。
它挡的是「有人写个 for 循环刷接口」,挡不住真正的 DDoS——那种得靠 CDN 和云防火墙。这里说实话,不吹。