Databag 0.1.18 API 使用详解
Databag 0.1.18 服务端 HTTP API 全链路实战:三种认证、节点管理、账号生命周期、频道消息与错误码,122 条路由逐域实测。
Databag 0.1.18 API 使用详解
目标:把 Databag 0.1.18 服务端的 HTTP API 完整跑通一遍——三种认证方式、节点管理、账号生命周期、资料、频道与消息、事件推送,每条请求与响应均来自 2026-10-25 在 Ubuntu 22.04 真实服务器上的实测回显,照抄未加工。
一、环境信息
- 操作系统:Ubuntu 22.04 LTS(amd64)
- 组件版本:Databag 服务端 0.1.18(源码编译安装,见《Ubuntu 22.04 安装 Databag 0.1.18 指南》)
- 服务端点:
http://127.0.0.1:7000(systemd 托管,监听 7000 端口) - 节点域名:
databag.example.com(已通过管理 API 配置,见 4.4 节) - 客户端工具:
curl+python3(仅用于格式化 JSON 输出)
二、前置条件
- Databag 服务已启动且健康:
curl -s -o /dev/null -w '%{http_code}' http://127.0.0.1:7000/返回200 - 已知管理员口令(本文统一用
q1w2e3r4演示) - 知道三种身份的边界:管理员(管节点与账号)、账号创建令牌(一次性,用于自助建号)、账号用户(handle+口令,登录后持 agent 令牌调用业务接口)
三、API 总览
Databag 服务端是纯 HTTP 服务,共 122 条 REST 路由(源码 net/server/internal/routers.go 实测统计),按路径前缀分布如下:
| 域 | 路由数 | 用途 | 认证 |
|---|---|---|---|
/content/* | 31 | 频道(channel)与消息(topic)、附件、标签 | agent 令牌 |
/account/* | 27 | 账号自身:登录、令牌、MFA、seal、通知 | Basic / agent / reset 令牌 |
/contact/* | 22 | 联系人(cards):建立、断开、联邦互认 | agent / contact 令牌 |
/admin/* | 17 | 节点管理:账号 CRUD、节点配置、状态、MFA | 管理员会话令牌 |
/attribute/* | 7 | 属性文章(按分组共享的发布内容) | agent 令牌 |
/profile/* | 6 | 账号资料查看与更新 | agent 令牌 |
/alias/* | 5 | 分组(联系人分组,便于批量共享) | agent 令牌 |
/talk/* | 4 | 音视频通话与响铃 | agent 令牌 |
/status | 1 | WebSocket 事件推送(增量同步入口) | agent 令牌 |
/signal | 1 | WebRTC 信令交换 | agent 令牌 |
/authorize | 1 | 联邦节点间授权 | 节点签名 |
通用约定:
- 协议与格式:HTTP + JSON;无
/v1之类版本前缀,版本随服务端整体升级 - 认证传参:令牌一律走 URL 查询参数(
?token=/?agent=)或Authorization: Bearer,用户名口令走Authorization: Basic或自定义Credentials头(见 4.2 节的坑) - 限流:无应用层限流;登录类接口失败时服务端会固定 sleep 一小段时间再返回 401(源码
APPUsernameWait),暴力破解成本被抬高 - 增量同步:所有业务对象带
revision计数器,客户端用/statusWebSocket 收变更事件,再按 revision 拉增量(详见 5.4 节)
四、认证与首次调用
Databag 有三种认证形态,对应三类调用者,逐个实测。
4.1 管理员会话令牌(管节点)
管理员口令通过 PUT /admin/access 换取会话令牌:
curl -s -X PUT "http://127.0.0.1:7000/admin/access?token=q1w2e3r4"
实测回显(返回一个 32 位十六进制会话令牌,JSON 字符串):
"bf3b8c048ca815d6bb9ae61b082d95cf"
后续所有 /admin/* 接口用 ?token=<会话令牌> 调用。口令错误时返回 401 且无响应体:
curl -s -w "\nHTTP:%{http_code}\n" -X PUT "http://127.0.0.1:7000/admin/access?token=wrong-pass"
HTTP:401
会话令牌存于 SQLite configs 表的 admin_session 键,重启后失效需重新获取;节点启用 TOTP MFA 后本接口还需带动态码(见《Databag 0.1.18 配置参数详解》MFA 小节)。
4.2 账号创建令牌 + Credentials 头(自助建号)
Databag 默认关闭开放注册,建号分两步:管理员签发一次性创建令牌,用户持令牌自助建号。
第一步,管理员签发创建令牌:
SESSION=bf3b8c048ca815d6bb9ae61b082d95cf
curl -s -X POST "http://127.0.0.1:7000/admin/accounts?token=$SESSION"
实测回显(12 位十六进制,一次性、有有效期):
"c16b92da0110"
第二步,用户持令牌建号。注意坑:建号接口读的是自定义请求头 Credentials: Basic base64(user:pass),不是标准的 Authorization 头——用 curl -u 会被拒(401 invalid credentials)。正确写法:
curl -s -w "\nHTTP:%{http_code}\n" -X POST \
"http://127.0.0.1:7000/account/profile?token=c16b92da0110" \
-H "Credentials: Basic $(echo -n 'dave:q1w2e3r4' | base64)"
实测回显(建号成功,服务端为账号生成 RSA 身份密钥对,guid 即公钥指纹、终身不变):
{"guid":"4481af30c846eb9c6df1e04e249debd8d5bcf1ff1c2366925a6f992ff24e9fc4","handle":"dave","revision":1,"version":"0.1.0","node":"databag.example.com"}
HTTP:200
两种失败形态实测:不带 Credentials 头 → HTTP:401;创建令牌用第二次 → HTTP:401(一次性,用完即焚)。节点开启开放注册后,不带 token 参数直接调本接口即可建号(见 5.1 节末尾)。
4.3 用户登录取 agent 令牌(业务调用)
账号用户用标准 Basic Auth 调 POST /account/apps 登录,返回的 appToken 就是后续所有业务接口的令牌:
curl -s -X POST "http://127.0.0.1:7000/account/apps" -u dave:q1w2e3r4
实测回显:
{
"guid": "4481af30c846eb9c6df1e04e249debd8d5bcf1ff1c2366925a6f992ff24e9fc4",
"appToken": "4481af30c846eb9c6df1e04e249debd8d5bcf1ff1c2366925a6f992ff24e9fc4.5ddc130bf220a46474f5fd13a4f3d08e",
"created": 1792904610,
"pushSupported": true
}
要点:appToken 已是完整的 guid.token 格式,直接当 ?agent= 的值用,不要再拼接(拼两次会被判格式错误)。每次登录生成一个独立令牌,一个账号可多个客户端同时在线。口令错误返回 401 无响应体:
curl -s -o /dev/null -w "HTTP:%{http_code}\n" -X POST "http://127.0.0.1:7000/account/apps" -u dave:wrong-pass
HTTP:401
业务接口的令牌传参:?agent=<appToken>(也接受 Authorization: Bearer <appToken>)。拿到令牌先验证一下——查自己的资料:
AGENT=4481af30c846eb9c6df1e04e249debd8d5bcf1ff1c2366925a6f992ff24e9fc4.5ddc130bf220a46474f5fd13a4f3d08e
curl -s "http://127.0.0.1:7000/profile?agent=$AGENT"
{
"guid": "4481af30c846eb9c6df1e04e249debd8d5bcf1ff1c2366925a6f992ff24e9fc4",
"handle": "dave",
"revision": 1,
"version": "0.1.0",
"node": "databag.example.com"
}
4.4 首次调用建议顺序
新节点的自动化初始化顺序(每步接口在第五章详解):
PUT /admin/access拿管理员会话PUT /admin/config设节点域名与配额(联邦与客户端识别依赖 domain)POST /admin/accounts签发创建令牌 → 用户POST /account/profile建号- 用户
POST /account/apps登录 → 持 agent 令牌调业务接口
五、各 API 域详解
5.1 节点管理域 /admin
读写节点配置。GET /admin/config 回读当前配置:
curl -s "http://127.0.0.1:7000/admin/config?token=$SESSION"
实测回显(已配置域名与 1GiB 配额的节点):
{
"domain": "databag.example.com",
"enableImage": true,
"enableAudio": true,
"enableVideo": true,
"enableBinary": true,
"enableIce": false,
"iceService": "",
"iceUrl": "",
"iceUsername": "",
"icePassword": "",
"keyType": "RSA2048",
"accountStorage": 1073741824,
"transformSupported": true,
"allowUnsealed": true,
"pushSupported": true
}
PUT /admin/config 修改配置,是全量覆盖语义——请求体里没带的字段会被重置成零值,实测:
curl -s -w "\nHTTP:%{http_code}\n" -X PUT \
"http://127.0.0.1:7000/admin/config?token=$SESSION" \
-H 'Content-Type: application/json' \
-d '{"domain":"databag.example.com","accountStorage":1073741824,"allowUnsealed":true,"enableImage":true,"enableAudio":true,"enableVideo":true,"enableBinary":true,"keyType":"RSA2048","pushSupported":true,"enableIce":false,"iceService":"","iceUrl":"","iceUsername":"","icePassword":""}'
HTTP:200
⚠️ 改配置前先
GET全量、改完字段再整体PUT回去,漏字段就丢配置。字段逐项含义见《Databag 0.1.18 配置参数详解》。
账号列表。GET /admin/accounts 看全节点账号:
curl -s "http://127.0.0.1:7000/admin/accounts?token=$SESSION"
[
{
"accountId": 2,
"guid": "4481af30c846eb9c6df1e04e249debd8d5bcf1ff1c2366925a6f992ff24e9fc4",
"handle": "dave",
"name": "Dave",
"description": "databag api walkthrough",
"location": "Shanghai",
"seal": "",
"disabled": false,
"storageUsed": 0
}
]
禁用与启用账号。PUT /admin/accounts/{accountId}/status,注意请求体是裸 JSON 布尔(-d 'true',不是 {"disabled":true}):
curl -s -w "\nHTTP:%{http_code}\n" -X PUT \
"http://127.0.0.1:7000/admin/accounts/2/status?token=$SESSION" \
-H 'Content-Type: application/json' -d 'true'
null
HTTP:200
禁用后该账号的 agent 令牌调用业务接口返回 410(登录接口仍能发令牌,但令牌不可用):
curl -s -o /dev/null -w "HTTP:%{http_code}\n" "http://127.0.0.1:7000/content/channels?agent=$AGENT"
HTTP:410
恢复启用把布尔改 false 即可(同样返回 null + 200,令牌立即恢复可用)。
重置用户口令。两步:管理员 POST /admin/accounts/{accountId}/auth 签发重置令牌,用户持重置令牌以 Bearer 方式调 PUT /account/auth 改密:
# 管理员签发(实测返回 "8c0406df8b00")
curl -s -X POST "http://127.0.0.1:7000/admin/accounts/2/auth?token=$SESSION"
# 用户改密:重置令牌放 Authorization: Bearer,新口令放 Credentials 头
curl -s -w "\nHTTP:%{http_code}\n" -X PUT "http://127.0.0.1:7000/account/auth" \
-H "Authorization: Bearer 8c0406df8b00" \
-H "Credentials: Basic $(echo -n 'dave:q1w2e3r4-new' | base64)"
null
HTTP:200
改密后立即生效:旧口令登录 401,新口令登录 200。注意重置令牌必须放 Bearer 头,放查询参数 ?reset= 会 401(实测踩坑,两个接口的取令牌位置不同)。
删除账号。DELETE /admin/accounts/{accountId},不可逆,账号数据与频道一并清除:
curl -s -w "\nHTTP:%{http_code}\n" -X DELETE \
"http://127.0.0.1:7000/admin/accounts/2?token=$SESSION"
curl -s "http://127.0.0.1:7000/admin/accounts?token=$SESSION"
null
HTTP:200
[]
节点状态。GET /admin/status 返回节点是否待初始化(布尔),实测已配置节点返回 false。
开放注册(免令牌建号)。节点开启开放注册后,任何人可自助建号。剩余名额查询无需认证:
curl -s -w "\nHTTP:%{http_code}\n" "http://127.0.0.1:7000/account/available"
3
HTTP:200
未开放注册时无令牌建号会被拒:
curl -s -o /dev/null -w "HTTP:%{http_code}\n" -X POST \
"http://127.0.0.1:7000/account/profile" \
-H "Credentials: Basic $(echo -n 'mallory:q1w2e3r4' | base64)"
HTTP:403
开放后同一请求返回 200 与新账号 guid。0.1.18 的开放注册开关无法经 PUT /admin/config 落库(版本坑),开启方法见《Databag 0.1.18 配置参数详解》5.7 节。
5.2 资料域 /profile
查看资料上面 4.3 节已演示。更新资料用 PUT /profile/data,只更新提交的字段:
curl -s -w "\nHTTP:%{http_code}\n" -X PUT \
"http://127.0.0.1:7000/profile/data?agent=$AGENT" \
-H 'Content-Type: application/json' \
-d '{"name":"Dave","location":"Shanghai","description":"databag api walkthrough"}'
实测回显(返回更新后的完整资料,revision 从 1 变 2):
{"guid":"4481af30c846eb9c6df1e04e249debd8d5bcf1ff1c2366925a6f992ff24e9fc4","handle":"dave","name":"Dave","description":"databag api walkthrough","location":"Shanghai","revision":2,"version":"0.1.0","node":"databag.example.com"}
HTTP:200
头像走 PUT /profile/image(multipart 上传,服务端用 ImageMagick 生成缩略图),此处从略。
5.3 内容域 /content(频道与消息)
频道(channel)是会话的载体,消息(topic)挂在频道下。最大的坑:内容字段必须是 {"dataType":"...","data":"..."} 结构,data 是字符串(E2E 加密载荷位,明文场景下塞 JSON 字符串)。直接传 {"subject":"general"} 这类平铺字段会被静默忽略——接口返回 200 但内容为空。错误示范实测:
curl -s -X POST "http://127.0.0.1:7000/content/channels?agent=$AGENT" \
-H 'Content-Type: application/json' -d '{"subject":"general"}'
返回的频道里 "dataType": ""、"data": ""(200 但载荷丢了)。正确写法:
curl -s -X POST "http://127.0.0.1:7000/content/channels?agent=$AGENT" \
-H 'Content-Type: application/json' \
-d '{"dataType":"superbasic","data":"{\"subject\":\"general\",\"cardIds\":[],\"groupId\":\"\"}"}'
实测回显(节选关键字段,频道 id acc3b9e4-…):
{
"id": "acc3b9e4-1755-49b6-bb90-17cfb44b49a5",
"revision": 2,
"data": {
"detailRevision": 2,
"topicRevision": 2,
"channelSummary": {
"lastTopic": { "guid": "", "dataType": "", "data": "", "created": 0, "updated": 0, "status": "" }
},
"channelDetail": {
"dataType": "superbasic",
"data": "{\"subject\":\"general\",\"cardIds\":[],\"groupId\":\"\"}",
"created": 1792904610,
"updated": 1792904610,
"enableImage": true, "enableAudio": true, "enableVideo": true, "enableBinary": true,
"contacts": { "groups": null, "cards": null },
"members": []
}
}
}
发消息(往频道下发 topic),同样用 dataType/data 结构:
curl -s -X POST \
"http://127.0.0.1:7000/content/channels/acc3b9e4-1755-49b6-bb90-17cfb44b49a5/topics?agent=$AGENT" \
-H 'Content-Type: application/json' \
-d '{"dataType":"text","data":"{\"message\":\"hello databag api\"}"}'
实测回显:
{
"id": "1651579c-bee9-4b9f-b739-9c6780ae9633",
"revision": 3,
"data": {
"detailRevision": 3,
"tagRevision": 3,
"topicDetail": {
"guid": "4481af30c846eb9c6df1e04e249debd8d5bcf1ff1c2366925a6f992ff24e9fc4",
"dataType": "text",
"data": "{\"message\":\"hello databag api\"}",
"created": 1792904610,
"updated": 1792904610,
"status": "unconfirmed",
"transform": "complete"
}
}
}
读取用三个端点:GET /content/channels(频道列表)、GET /content/channels/{id}/detail(频道详情)、GET /content/channels/{id}/topics(消息列表)、GET /content/channels/{id}/topics/{tid}/detail(消息详情)。频道详情实测:
curl -s "http://127.0.0.1:7000/content/channels/acc3b9e4-1755-49b6-bb90-17cfb44b49a5/detail?agent=$AGENT"
{
"dataType": "superbasic",
"data": "{\"subject\":\"general\",\"cardIds\":[],\"groupId\":\"\"}",
"created": 1792904610,
"updated": 1792904610,
"enableImage": true, "enableAudio": true, "enableVideo": true, "enableBinary": true,
"contacts": { "groups": null, "cards": null },
"members": []
}
删除频道:DELETE /content/channels/{id}?agent=$AGENT,实测返回 null + 200。列表接口支持 ?revision= 参数做增量拉取(见六、通用约定)。
5.4 事件推送域 /status
/status?agent=<appToken> 是 WebSocket 端点,客户端升级连接后接收资料/联系人/频道/消息的变更事件,事件里带 revision,客户端再按 revision 调 REST 拉增量——这是官方客户端的同步模型,避免轮询。用普通 GET 访问(不带升级头)实测:
curl -s -w "\nHTTP:%{http_code}\n" "http://127.0.0.1:7000/status?agent=$AGENT"
Bad Request
HTTP:400
纯 curl 无法演示 WebSocket 会话,客户端开发时用任意 WebSocket 库带 agent 参数连接即可。
5.5 其他域速览
/contact/cards(22 条):联系人管理,联邦互认通过交换签名 connect 消息建立,建立后对方以 contact 令牌拉取你共享的频道与属性/alias/groups(5 条):联系人分组,频道可按分组批量共享/attribute/articles(7 条):属性文章,账号发布、按分组共享的长内容/talk+/signal(5 条):音视频通话信令,需先配置 TURN/STUN(配置项见《Databag 0.1.18 配置参数详解》5.5 节)
六、通用约定
错误码实测汇总:
| 状态码 | 场景 | 实测触发 |
|---|---|---|
| 400 | 参数缺失/格式错误 | ?agent=garbage(无点号)、不带 agent 调业务接口、WebSocket 端点不带升级头 |
| 401 | 认证失败 | 管理员口令错、用户口令错、无 Credentials 建号、创建令牌复用、重置令牌放错位置、管理接口不带 token |
| 403 | 权限不足 | 未开放注册时无令牌建号 |
| 404 | 资源不存在 | 删除不存在的 accountId |
| 410 | 账号已禁用 | 禁用账号的 agent 令牌调业务接口 |
| 409 | 冲突 | 用户名含空白、用户名已被占用(源码定义) |
认证参数位置速查:
| 身份 | 位置 | 示例 |
|---|---|---|
| 管理员会话 | ?token= | /admin/accounts?token=$SESSION |
| 创建令牌 | ?token= | /account/profile?token=$CT |
| agent 令牌 | ?agent= 或 Bearer | /profile?agent=$AGENT |
| 重置令牌 | 仅 Authorization: Bearer | PUT /account/auth |
| 用户名口令 | Authorization: Basic(登录)/ Credentials: Basic(建号、改密) | -u dave:pass |
增量同步:profile、cards、groups、attributes、channels 各自维护 revision 计数器;频道内 topic 与频道共享同一计数(发一条消息,频道和消息的 revision 一起前进,见 5.3 节回显中 revision: 3)。客户端记录上次同步点 X,拉 revision > X 的对象即可增量同步;删除通过「空值 slot」表达(同步到空 data 即视为已删)。
七、常见问题
Q1:curl -u 建号返回 401 invalid credentials?
建号与改密接口读的是自定义头 Credentials: Basic base64(user:pass),不是标准 Authorization 头。用 -H "Credentials: Basic $(echo -n 'user:pass' | base64)"。登录接口 POST /account/apps 才用标准 -u。
Q2:appToken 调接口报令牌格式错误?
POST /account/apps 返回的 appToken 已是完整的 guid.token 形式,直接当 ?agent= 的值。不要再拼一次 guid——拼成 guid.guid.token 会被判格式错误。
Q3:创建频道/发消息返回 200 但内容为空?
内容字段必须是 {"dataType":"...","data":"..."} 结构,平铺的 {"subject":...}、{"message":...} 会被静默忽略。data 是字符串类型,明文场景下把 JSON 序列化后塞进去(见 5.3 节)。
Q4:PUT /admin/config 之后配置丢了? 该接口是全量覆盖语义,未提交的字段重置为零值。先 GET 全量、改字段、整体 PUT 回去。
Q5:禁用账号的接口不生效?
PUT /admin/accounts/{id}/status 的请求体是裸 JSON 布尔 -d 'true',不是 {"disabled":true}。禁用生效后该账号调业务接口返回 410。
Q6:管理员签发的重置令牌怎么用都 401?
重置令牌必须放在 Authorization: Bearer 头里调 PUT /account/auth,放 ?reset= 查询参数不识别(两个接口取令牌的位置不同,实测确认)。
Q7:0.1.18 开启开放注册后仍 403?
0.1.18 的 PUT /admin/config 不持久化 enableOpenAccess 字段(main 源码已修复、0.1.18 发布版未含),需直改 SQLite:open_access 的 bool_value=1、account_limit 的 num_value=N(注意一个是布尔列一个是数值列),步骤见《Databag 0.1.18 配置参数详解》5.7 节。
八、参考链接
- 官方仓库(服务端源码与路由定义):
https://github.com/balzack/databag - 设计文档(数据模型/令牌体系/E2E):
https://github.com/balzack/databag/blob/main/doc/design_overview.md - 本专栏安装篇:《Ubuntu 22.04 安装 Databag 0.1.18 指南》
- 本专栏配置篇:《Databag 0.1.18 配置参数详解》