AppFlowy 0.19.10 API 使用详解
AppFlowy Cloud 0.19.10 服务端 REST API 实测手册:认证与 JWT 调用闭环、用户/工作区/成员/文件存储/AI/聊天/导入等全 API 域路由表与请求响应示例,含错误码(422/1003/1017/1018)与未配置 AI 的行为实测,全部 curl 命令实测通过。
AppFlowy 0.19.10 API 使用详解
目标:面向自托管运维与集成开发,给出 AppFlowy Cloud 0.19.10 服务端 REST API 的完整路由总览与逐域调用示例——认证闭环、用户、工作区与成员、文件存储、AI、聊天、数据导入、共享协作。本文基于源码部署环境(Ubuntu 22.04,Nginx 80 统一入口)实测,全部 curl 命令与回显均实测通过;路由表提取自 0.19.10 源码快照(c5bcfd33)。
一、环境信息
- 服务端:AppFlowy Cloud 0.19.10(源码快照 c5bcfd33,2026-10-22 官方最新稳定版);
- 认证服务:GoTrue(AppFlowy-IO/auth 快照 7337e21c),JWT 签发;
- 测试入口:
http://127.0.0.1(Nginx 80 统一入口,反代规则见《Ubuntu 22.04 安装 AppFlowy 0.19.10 指南》4.9 节); - 测试账号:user1@example.com / admin@example.com,口令 q1w2e3r4(示例环境,生产请替换);
- 输出格式:全部业务接口返回统一包络
{"data":..., "code":0, "message":"..."},code为 0 表示成功,非 0 见第六章错误码表; - 官方二进制差异:0.19.10 官方二进制主服务健康检查为
/api/health(源码版为/health),其余路由一致。
二、前置条件
- 一套已部署并完成端到端验证的 AppFlowy 服务端(安装与验证见《Ubuntu 22.04 安装 AppFlowy 0.19.10 指南》第四章,或编排部署见《AppFlowy 0.19.10 Docker Compose 部署指南》);
curl与python3(本文用 python3 从 JSON 回显中提取 token);- 一个可登录的测试账号(注册方法见第四章);
- 服务健康自检(实测回显):
curl http://127.0.0.1/health
OK
curl http://127.0.0.1/gotrue/health
{"version":"","name":"GoTrue","description":"GoTrue is a user registration and authentication API"}
三、API 总览
AppFlowy Cloud 对外暴露 11 个 API 域,全部经 Nginx 80 端口访问(/metrics 除外,仅监听服务本机 8000):
| API 域 | 前缀 | 用途 | 认证 |
|---|---|---|---|
| 认证 | /gotrue/* | 注册、登录、token 刷新(GoTrue) | 匿名/JWT |
| 用户 | /api/user | 用户建档、资料、注销 | Bearer JWT |
| 工作区 | /api/workspace | 工作区 CRUD、成员、邀请 | Bearer JWT |
| 文件存储 | /api/file_storage | 附件上传(分片)、用量统计 | Bearer JWT |
| AI | /api/ai/{workspace_id} | 文本补全、行摘要/翻译、模型列表 | Bearer JWT |
| 聊天 | /api/chat/{workspace_id} | AI 聊天室与消息管理 | Bearer JWT |
| 搜索 | /api/search | 全文/语义文档检索 | Bearer JWT |
| 数据导入 | /api/import | Notion 等外部数据导入 | Bearer JWT |
| 访问申请 | /api/access-request | 工作区/视图访问审批 | Bearer JWT |
| 共享访客 | /api/sharing/workspace | 访客视图授权 | Bearer JWT |
| 服务器信息 | /api/server | 服务能力与版本信息 | 匿名 |
| 实时协作 | /ws/v1、/ws/v2/{workspace_id} | WebSocket 长连接(客户端场景) | Bearer JWT |
| 指标 | /metrics(本机 8000) | Prometheus 指标 | 匿名(仅内网) |
💡 说明:文档内容读写(视图/页面数据)走
/ws长连接与 collab 通道,不在 REST 范畴;/api/search、/api/access-request、/api/sharing主要由桌面客户端内部调用,本文给出路由表与实测要点。
四、认证与首次调用
4.1 注册(POST /gotrue/signup)
curl -s -X POST http://127.0.0.1/gotrue/signup \
-H "Content-Type: application/json" \
-d '{"email":"user1@example.com","password":"q1w2e3r4"}' | head -c 220
{"access_token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIzMDA2MWFmZi0yMmZkLTQzZDMtOGJlNy00M2VmNDhlMDAzYzIiLCJhdWQiOiIiLCJleHAiOjE3OTMyOTgwMzYsImlhdCI6MTc5MjY5MzIzNiwiZW1haWwiOiJ1c2VyMUBleGFtcGxlLmNvbSIsInBob25lIj ...(truncated)
返回 access_token(700+ 字符 JWT,本文截断展示)与 refresh_token。重复注册同一邮箱返回 422:
curl -s -w "\nHTTP %{http_code}\n" -X POST http://127.0.0.1/gotrue/signup \
-H "Content-Type: application/json" \
-d '{"email":"user1@example.com","password":"q1w2e3r4"}'
{"code":422,"error_code":"user_already_exists","msg":"User already registered"}
HTTP 422
4.2 密码登录(POST /gotrue/token?grant_type=password)
curl -s -X POST "http://127.0.0.1/gotrue/token?grant_type=password" \
-H "Content-Type: application/json" \
-d '{"email":"user1@example.com","password":"q1w2e3r4"}' > /tmp/u1.json
python3 -c "import json;d=json.load(open('/tmp/u1.json'));print({k:(str(v)[:40]+'...' if k=='access_token' else v) for k,v in d.items() if k in ('token_type','expires_in','expires_at')})"
{'token_type': 'bearer', 'expires_in': 604800, 'expires_at': 1793298036}
expires_in 604800 秒(7 天,对应 GOTRUE_JWT_EXP=604800)。后续所有业务接口用 Authorization: Bearer <access_token> 头。
4.3 首次建档(GET /api/user/verify/{access_token})
注册/登录拿到的 token 只存在于认证库,首次调用 verify 接口才会在业务库创建用户档案与默认工作区 My Workspace:
TOK=$(python3 -c "import json;print(json.load(open('/tmp/u1.json'))['access_token'])")
curl -s "http://127.0.0.1/api/user/verify/$TOK"
{"data":{"is_new":true},"code":0,"message":"Operation completed successfully."}
同一用户再次调用返回 is_new:false(实测):
{"data":{"is_new":false},"code":0,"message":"Operation completed successfully."}
⚠️ 注意:这是 AppFlowy 与通用 JWT 服务最大的差异点——拿到 token 后必须先调 verify 建档,否则
/api/user/profile报 Record not found(实测回显:{"code":-2,"message":"Record not found:Can't find the user profile for user: ..."})。
无效 token 的行为(实测):
curl -s "http://127.0.0.1/api/user/verify/not-a-token"
{"code":1003,"message":"invalid JWT: unable to parse or verify signature, token is malformed: token contains an invalid number of segments"}
4.4 缺失/无效认证头
curl -s -w "\nHTTP %{http_code}\n" http://127.0.0.1/api/user/profile
No Authorization header
HTTP 401
五、各 API 域详解
5.1 系统与观测(/api/server、/health、/metrics)
curl -s http://127.0.0.1/api/server
{"data":{"supported_client_features":[],"minimum_supported_client_version":null,"appflowy_web_url":"http://localhost"},"code":0,"message":"Operation completed successfully."}
appflowy_web_url 来自 APPFLOWY_WEB_URL 配置。Prometheus 指标仅暴露在服务本机 8000 端口(Nginx 未放行,属内网观测面):
curl -s http://127.0.0.1:8000/metrics | head -2
# HELP appflowy_cloud_requests_count number of requests.
# TYPE appflowy_cloud_requests_count counter
5.2 用户域(/api/user)
| 方法 | 路径 | 用途 |
|---|---|---|
| GET | /api/user/verify/{access_token} | 首次建档(4.3 节) |
| GET | /api/user/profile | 查询当前用户资料 |
| POST | /api/user/update | 更新资料(姓名、头像等) |
| GET | /api/user/workspace | 当前用户工作区概览 |
| POST | /api/user/asset/image | 上传用户图片资产 |
| GET | /api/user/asset/image/person/{person_id}/file/{file_id} | 读取图片资产 |
| DELETE | /api/user | 注销当前用户(带查询参数确认) |
TOK=$(python3 -c "import json;print(json.load(open('/tmp/u1.json'))['access_token'])")
curl -s http://127.0.0.1/api/user/profile -H "Authorization: Bearer $TOK" | head -c 260
{"data":{"uid":649641193512112128,"uuid":"30061aff-22fd-43d3-8be7-43ef48e003c2","email":"user1@example.com","password":"","name":"user1@example.com","metadata":{},"encryption_sign":null,"latest_workspace_id":"155a17bc-00c7-47f2-828a-b2271a153235","updated_at": ...(truncated)
uid(int64 主键)与 uuid(与 GoTrue 用户一致)均可用于后续成员管理接口;latest_workspace_id 即首次建档创建的 My Workspace。
5.3 工作区与成员域(/api/workspace)
| 方法 | 路径 | 用途 |
|---|---|---|
| GET / POST / PATCH | /api/workspace | 列表 / 创建 / 改名换图标 |
| DELETE | /api/workspace/{workspace_id} | 删除工作区 |
| PUT | /api/workspace/{workspace_id}/open | 打开(标记最近使用) |
| POST | /api/workspace/{workspace_id}/invite | 邮箱邀请成员(数组) |
| GET | /api/workspace/invite、/invite/{invite_id} | 查询收到的邀请 |
| POST | /api/workspace/accept-invite/{invite_id} | 接受邀请 |
| POST | /api/workspace/join-by-invite-code | 邀请码加入 |
| GET / PUT / DELETE | /api/workspace/{workspace_id}/member | 成员列表 / 改角色 / 移除 |
| POST | /api/workspace/{workspace_id}/leave | 退出工作区 |
| GET / POST | /api/workspace/{workspace_id}/settings | 工作区设置 |
创建工作区(请求体 workspace_name 可选,缺省自动命名):
TOK=$(python3 -c "import json;print(json.load(open('/tmp/login.json'))['access_token'])")
curl -s -X POST http://127.0.0.1/api/workspace \
-H "Authorization: Bearer $TOK" -H "Content-Type: application/json" \
-d '{"workspace_name":"Doc Test WS"}' | head -c 300
{"data":{"workspace_id":"93ed8817-5310-474b-8aec-9e989dacaf27","database_storage_id":"5f0fbaac-97e7-4042-9d34-2343bc9815da","owner_uid":649641193512112128,"owner_name":"user1@example.com","owner_email":"user1@example.com","workspace_type":0,"workspace_name":"Doc Test WS","created_at":"2026-10-22T18: ...(truncated)
列表(实测一个账号下 2 个工作区):
curl -s http://127.0.0.1/api/workspace -H "Authorization: Bearer $TOK" \
| python3 -c "import sys,json;d=json.load(sys.stdin)['data'];print(len(d),[w['workspace_name'] for w in d])"
2 ['My Workspace', 'Doc Test WS']
邀请成员(请求体为对象数组;skip_email_send:true 跳过邮件发送,适合未配 SMTP 的环境):
WID=93ed8817-5310-474b-8aec-9e989dacaf27
curl -s -X POST "http://127.0.0.1/api/workspace/$WID/invite" \
-H "Authorization: Bearer $TOK" -H "Content-Type: application/json" \
-d '[{"email":"user2@example.com","role":"Member","skip_email_send":true}]'
{"code":0,"message":"Operation completed successfully."}
被邀请人调用 POST /api/workspace/accept-invite/{invite_id} 接受后才出现在成员列表(实测接受前成员列表仅 Owner):
curl -s "http://127.0.0.1/api/workspace/$WID/member" -H "Authorization: Bearer $TOK"
{"data":[{"name":"user1@example.com","email":"user1@example.com","role":"Owner","avatar_url":null,"joined_at":"2026-10-22T18:20:44.050748Z"}],"code":0,"message":"Operation completed successfully."}
5.4 文件存储域(/api/file_storage)
| 方法 | 路径 | 用途 |
|---|---|---|
| PUT / GET / DELETE | /api/file_storage/{workspace_id}/blob/{file_id} | 小文件直传/下载/删除 |
| GET / PUT | /api/file_storage/{workspace_id}/metadata/{file_id} | 附件元数据 |
| GET | /api/file_storage/{workspace_id}/usage | 空间用量 |
| GET | /api/file_storage/{workspace_id}/blobs | 附件列表 |
| POST | /api/file_storage/{workspace_id}/create_upload | 创建分片上传任务 |
| PUT | /api/file_storage/{workspace_id}/upload_part/{parent_dir}/{file_id}/{upload_id}/{part_num} | 上传分片 |
| PUT | /api/file_storage/{workspace_id}/complete_upload | 完成分片合并 |
| PUT / GET | /api/file_storage/{workspace_id}/v1/blob/{parent_dir}… | v1 分目录通道 |
WID=93ed8817-5310-474b-8aec-9e989dacaf27
curl -s "http://127.0.0.1/api/file_storage/$WID/usage" -H "Authorization: Bearer $TOK"
{"data":{"consumed_capacity":0},"code":0,"message":"Operation completed successfully."}
💡 提示:桌面客户端上传大附件走 create_upload → upload_part → complete_upload 三步分片流程,最终文件落在对象存储(本文环境为 SeaweedFS 的 appflowy 桶),
consumed_capacity随上传增长。
5.5 AI 域(/api/ai/{workspace_id})
| 方法 | 路径 | 用途 |
|---|---|---|
| POST | /api/ai/{workspace_id}/complete/stream | 流式文本补全 |
| POST | /api/ai/{workspace_id}/v2/complete/stream | v2 流式补全 |
| POST | /api/ai/{workspace_id}/summarize_row、/translate_row | 行摘要/翻译 |
| GET | /api/ai/{workspace_id}/local/config、/model/list | 本地 AI 配置与模型列表 |
| POST | /api/ai/{workspace_id}/calculate_similarity | 相似度计算 |
completion_type 为整数枚举(传字符串会报 400,实测:Json deserialize error: invalid type: string "improve_writing", expected u8)。未配置 AI 时的行为(本文环境 AI_OPENAI_API_KEY 留空,实测):经 Nginx 调用补全接口返回 502(服务端在无 AI 后端时断开该连接),聊天与 AI 功能不可用,其余功能不受影响:
curl -s -w "\nHTTP %{http_code}\n" -X POST "http://127.0.0.1/api/ai/$WID/complete/stream" \
-H "Authorization: Bearer $TOK" -H "Content-Type: application/json" \
-d '{"text":"hello","completion_type":1}' | tail -1
HTTP 502
💡 提示:官方编排部署(B2 指南)自带 appflowy_ai 服务并预置本地模型;源码部署需配置 OpenAI 兼容接口(
AI_OPENAI_API_KEY等)后 AI 域才可用。
5.6 聊天域(/api/chat/{workspace_id})
| 方法 | 路径 | 用途 |
|---|---|---|
| POST / DELETE | /api/chat/{workspace_id}、/{chat_id} | 创建聊天室 / 删除(chat_id 必须为 UUID) |
| GET | /api/chat/{workspace_id}/{chat_id}/message?limit&offset | 分页拉取消息 |
| GET / POST | /api/chat/{workspace_id}/{chat_id}/settings | 聊天设置 |
| GET | /api/chat/{workspace_id}/{chat_id}/{message_id}/related_question | 相关问题推荐 |
| POST | /api/chat/{workspace_id}/{chat_id}/message/question、/answer | 写入问答消息 |
| POST | /api/chat/{workspace_id}/{chat_id}/{message_id}/v3/answer/stream | v3 流式回答 |
| POST | /api/chat/{workspace_id}/{chat_id}/context/text | 注入聊天上下文 |
创建聊天室时 chat_id 由调用方指定且必须是 UUID 格式,否则实测报错:
curl -s -X POST "http://127.0.0.1/api/chat/$WID" \
-H "Authorization: Bearer $TOK" -H "Content-Type: application/json" \
-d '{"chat_id":"doc-chat-001","name":"Doc Chat","rag_ids":[]}'
{"code":1018,"message":"invalid character: expected an optional prefix of `urn:uuid:` followed by [0-9a-fA-F-], found `o` at 2"}
改用 UUID 后创建成功并拉取消息(实测空聊天室):
CID=9e6bfec3-f1a0-4a15-9cc5-aec8d2c04a6a
curl -s -X POST "http://127.0.0.1/api/chat/$WID" \
-H "Authorization: Bearer $TOK" -H "Content-Type: application/json" \
-d "{\"chat_id\":\"$CID\",\"name\":\"Doc Chat\",\"rag_ids\":[]}"
{"code":0,"message":"Operation completed successfully."}
curl -s "http://127.0.0.1/api/chat/$WID/$CID/message?limit=10&offset=0" -H "Authorization: Bearer $TOK"
{"data":{"messages":[],"has_more":false,"total":0},"code":0,"message":"Operation completed successfully."}
5.7 数据导入域(/api/import)
| 方法 | 路径 | 用途 |
|---|---|---|
| POST | /api/import | 提交导入(multipart,承载 Notion 导出包等文件) |
| GET | /api/import | 查询导入任务列表(含状态) |
| POST | /api/import/create | 创建导入任务 |
该域为 multipart/form-data 上传(源码 handler 签名确认),由后台 worker(appflowy_worker)异步处理,桌面客户端「导入 Notion」功能即走此通道。APPFLOWY_WORKER_IMPORT_TICK_INTERVAL=30 决定 worker 的轮询间隔(秒)。
5.8 搜索、共享与实时协作域
| 方法 | 路径 | 域 | 用途 |
|---|---|---|---|
| GET | /api/search/{workspace_id} | 搜索 | 文档检索 |
| GET | /api/search/{workspace_id}/summary | 搜索 | 检索结果摘要 |
| POST / GET | /api/access-request、/{request_id}、/{request_id}/approve | 访问申请 | 申请/查询/批准 |
| GET | /api/sharing/workspace/{workspace_id}/view 等 | 共享访客 | 访客视图与授权管理 |
| GET | /api/invite-code-info | 邀请码 | 邀请码信息查询 |
| GET | /ws/v1、/ws/v2/{workspace_id} | 实时协作 | WebSocket 升级连接 |
| GET | /api/realtime/*(collab 通道) | 实时协作 | 协同编辑消息 |
💡 说明:以上接口由桌面客户端内部调用(WebSocket 与 collab 通道需专用客户端协议),运维排障时可通过本表确认路由归属;
/api/search依赖检索服务(源码部署未分发检索服务,官方编排部署自带 appflowy_search)。
六、通用约定
- 响应包络:业务接口统一
{"data":...,"code":N,"message":"..."};code=0成功。注意部分错误(如 4.3 节无效 token)以 HTTP 200 + 非 0 code 返回,调用方应以code字段而非 HTTP 状态码做成功判定;GoTrue 域(/gotrue/*)为 Supabase 风格裸 JSON(422 时返回{"code":422,"error_code":...,"msg":...}); - 认证:除 /gotrue/*、/api/server、/health 外全部要求
Authorization: Bearer <access_token>;缺失时 HTTP 401(实测回显No Authorization header); - 错误码速查(本文实测命中的):
| code | 含义 | 实测触发场景 |
|---|---|---|
| 0 | 成功 | — |
| 422 | user_already_exists | 重复注册(GoTrue 域) |
| 1003 | invalid JWT | token 格式错误/签名不符 |
| -2 | Record not found | 未 verify 建档先查 profile |
| 1017 | 数据库唯一键冲突 | chat_id 已被其他聊天室占用 |
| 1018 | UUID 解析失败 | chat_id 非法 |
- 分页:列表类接口用
limit+offset查询参数,响应带has_more; - UUID:chat_id 由客户端生成(UUID v4),workspace_id/user 资源 ID 由服务端生成,均按 UUID 校验;
- 幂等与删除:DELETE 类接口(删工作区、删聊天室、注销用户)为硬删除,调用前自行备份。
七、常见问题
Q1:登录成功但 /api/user/profile 报 Record not found(code -2)?
先调用 GET /api/user/verify/{access_token} 完成业务建档(is_new:true),再访问资料与工作区接口(见 4.3 节)。
Q2:所有业务接口都返回 401「No Authorization header」?
请求头缺少 Authorization: Bearer <token>。注意 Bearer 与 token 之间有一个空格;token 过期(默认 7 天)后需重新登录或用 GoTrue 的 refresh_token 换新。
Q3:创建聊天室报 code 1018 或 1017?
chat_id 必须是 UUID(如 9e6bfec3-f1a0-4a15-9cc5-aec8d2c04a6a),自定义字符串 ID 不被接受,报 code 1018(实测回显见 5.6 节);code 1017 表示该 chat_id 已被占用——实测确认 chat_id 是全局唯一主键(跨工作区),重复创建返回 duplicate key value violates unique constraint "af_chat_pkey",换一个新 UUID 即可。
Q4:AI 补全接口返回 502?
未配置 AI 后端。源码部署需在 appflowy.env 配置 AI_OPENAI_API_KEY(OpenAI 兼容接口)后重启 appflowy_cloud;官方编排部署自带 appflowy_ai 服务。配置参数详见《AppFlowy 0.19.10 配置参数详解》。
Q5:curl /metrics 返回 404?
/metrics 只在服务本机 8000 端口暴露(curl http://127.0.0.1:8000/metrics),未纳入 Nginx 反代是刻意的内网观测面设计;如需采集,请在服务器本机部署 Prometheus 抓取或自行增加仅内网可达的 location。
Q6:如何用 API 判断服务端版本?
GET /api/server 返回服务能力信息;健康检查 GET /health(源码版)或 GET /api/health(官方二进制)。版本本身以部署时的快照/发布物为准(0.19.10)。
Q7:邀请发出后成员列表里看不到被邀请人?
邀请需被邀请人调用 POST /api/workspace/accept-invite/{invite_id} 接受后才入列(5.3 节实测:接受前列表仅 Owner)。未配 SMTP 时邀请邮件不会发出,可在邀请请求中置 skip_email_send:true,并从 GET /api/workspace/invite(被邀请人视角)查到 invite_id。
八、参考链接
- AppFlowy 服务端源码(本文路由来源):https://github.com/AppFlowy-IO/AppFlowy-Cloud
- GoTrue 源码(认证域):https://github.com/AppFlowy-IO/auth
- AppFlowy 官网:https://appflowy.io
站内系列文档:
- 《AppFlowy 0.19.10 介绍与选型指南》——产品定位、功能矩阵与量化选型对比;
- 《Ubuntu 22.04 安装 AppFlowy 0.19.10 指南》——源码编译部署服务端与客户端安装;
- 《AppFlowy 0.19.10 Docker Compose 部署指南》——官方编排路线(11 服务一体部署);
- 《AppFlowy 0.19.10 配置参数详解》——全部配置参数逐项详解。