Databag 0.1.18 API 使用详解

Databag 0.1.18 服务端 HTTP API 全链路实战:三种认证、节点管理、账号生命周期、频道消息与错误码,122 条路由逐域实测。

DatabagDatabag端到端加密即时通信自托管去中心化2026/10/25

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 令牌
/status1WebSocket 事件推送(增量同步入口)agent 令牌
/signal1WebRTC 信令交换agent 令牌
/authorize1联邦节点间授权节点签名

通用约定:

  • 协议与格式:HTTP + JSON;无 /v1 之类版本前缀,版本随服务端整体升级
  • 认证传参:令牌一律走 URL 查询参数(?token= / ?agent=)或 Authorization: Bearer,用户名口令走 Authorization: Basic 或自定义 Credentials 头(见 4.2 节的坑)
  • 限流:无应用层限流;登录类接口失败时服务端会固定 sleep 一小段时间再返回 401(源码 APPUsernameWait),暴力破解成本被抬高
  • 增量同步:所有业务对象带 revision 计数器,客户端用 /status WebSocket 收变更事件,再按 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 首次调用建议顺序

新节点的自动化初始化顺序(每步接口在第五章详解):

  1. PUT /admin/access 拿管理员会话
  2. PUT /admin/config 设节点域名与配额(联邦与客户端识别依赖 domain)
  3. POST /admin/accounts 签发创建令牌 → 用户 POST /account/profile 建号
  4. 用户 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: BearerPUT /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 节。

八、参考链接