首页
/ Dify Console API OpenAPI 契约文档精读:790 个管理端点、认证模型与自动文档生成管线

Dify Console API OpenAPI 契约文档精读:790 个管理端点、认证模型与自动文档生成管线

2026-09-06 16:14:49作者:虞亚竹Luna

api/openapi/markdown/console-openapi.md 是 Dify 控制台管理接口(Console API)的完整 OpenAPI 契约 Markdown 版本,共约 2.5 万行,覆盖账号、应用、工作空间、知识库、Agent 等全部后端管理端点及字段级 Schemas。本文基于该文档逐节拆解其端点全貌、认证与安全约束、典型接口签名,并结合 文档生成脚本规范导出器控制器注册入口 等仓库源码,说明这份文档是如何从 Flask-RESTX 路由“无损”生成、如何保证与实现同源,以及开发者应如何消费与再生成它。

一、文档定位:Console 管理面的机器可读契约

console-openapi.md 对应运行时的 JSON 契约 /console/api/openapi.json。从 规范导出器 可以看到四个 API 面的映射关系:

运行时规范地址 导出的 JSON 文件 导出的 Markdown 文件
/console/api/openapi.json console-openapi.json console-openapi.md
/api/openapi.json web-openapi.json web-openapi.md
/v1/openapi.json service-openapi.json service-openapi.md
/openapi/v1/openapi.json openapi-openapi.json openapi-openapi.md

四份文档同源、同管线生成,本文只聚焦其中的 console 面。该契约的标题与版本直接来自 控制器注册入口

bp = Blueprint("console", __name__, url_prefix="/console/api")

api = ExternalApi(
    bp,
    version="1.0",
    title="Console API",
    description="Console management APIs for app configuration, monitoring, and administration",
)

因此文档头部的 “Console management APIs for app configuration, monitoring, and administration” 与 “Version: 1.0” 不是手工维护的文案,而是 ExternalApi 初始化参数的直接投影——改代码即改文档,天然防止文档漂移。

1.1 文档的四大组成部分

按行号划分,console-openapi.md 的结构非常规整:

  1. 头部元信息(L1-L11):标题、描述、版本、可用授权方式;
  2. ## console 命名空间(L12 起,约 13000 行):790 个端点的完整签名,含参数表、请求体表、响应表;
  3. ## default 命名空间 + Schemas 附录(L13012 起):default 命名空间收录未挂到 /console 前缀下的端点(如 GET /explore/banners),随后 ### Schemas 附录从 L13031 一直排到文档主体末尾,给出全部 *Payload*Response 等模型的字段表,字段以 [AccountResponse](#accountresponse) 形式的锚点与端点表互相引用;
  4. ## FastOpenAPI Preview (OpenAPI 3.1) 附录(L25016 起):Dify 正在验证的 OpenAPI 3.1 新管线的 PoC 输出,目前仅含少量初始化类端点。

1.2 认证方式:Bearer 声明

文档头部明确声明:

Available authorizations — Bearer (HTTP, bearer):Use the Service API key as a Bearer token in the Authorization header. Bearer format: API_KEY

即把 API Key 原样放入 Authorization: Bearer <API_KEY>。从源码结构看,Console 命名空间同时存在两类准入路径:一类是 loginrefresh-tokenemail-register 等建立的会话流(见 auth 控制器),另一类是各资源接口上的准入装饰器,例如 spec.py 中的 @console_account_admission(),在返回 JSON 前完成账号级会话校验。消费该文档时,应以具体端点是否依赖登录态为准,而非只看头部授权声明。

二、端点全貌:按资源域划分的 790 个接口

对文档全部端点标题做统计后,各资源域(/console/api/<域>)的分布为:

资源域 端点数 典型能力
workspaces 223 成员、模型供应商、工具、插件、RBAC、端点密钥等管理面
apps 175 传统应用(chat/completion/workflow)的配置、日志、运行与统计
datasets 81 知识库、文档、分段、外部知识库
agent 57 新版 Agent 应用:清单、构建草稿、Composer、配置文件与技能包
rag 53 RAG 管线:数据源授权、内容预览、管线工作流与草稿变量
snippets 37 代码片段工作流及其草稿变量
installed-apps 27 已安装应用(模板市场安装物)管理
account 17 当前账号资料、改密、换邮箱、教育认证、注销
oauth 15 OAuth 2.1 设备码/OAuth Server 相关
trial-apps 14 试用应用目录与用量
auth 及其余(activateloginbillingtagsmcp 等) 约 80 登录激活、计费、标签、MCP 等

下面按资源域继承原文档的关键端点签名(参数、请求体、响应表均摘自文档,未做删减改写)。

2.1 账号域(/account,17 个端点)

账号域是 Console 管理面的“自身管理”入口,文档给出如下端点集合:

方法与路径 请求体 成功响应
GET /account/avatar query:avatar(必填,Avatar file ID) 200 AvatarUrlResponse
POST /account/change-email ChangeEmailSendPayload 200 SimpleResultDataResponse
POST /account/change-email/check-email-unique CheckEmailUniquePayload 200 SimpleResultResponse
POST /account/change-email/reset ChangeEmailResetPayload 200 AccountResponse
POST /account/change-email/validity ChangeEmailValidityPayload 200 VerificationTokenResponse
POST /account/delete AccountDeletePayload 200 SimpleResultResponse
POST /account/delete/feedback AccountDeletionFeedbackPayload 200 SimpleResultResponse
GET /account/delete/verify 200 SimpleResultDataResponse
GET /account/education 200 EducationStatusResponse
POST /account/education EducationActivatePayload 200 EducationActivateResponse
GET /account/education/autocomplete query:keywords(必填)、limit(默认 20)、page 200 EducationAutocompleteResponse
GET /account/education/verify 200 EducationVerifyResponse
POST /account/init AccountInitPayload 200 SimpleResultResponse
GET /account/integrates 200 AccountIntegrateListResponse
POST /account/password AccountPasswordPayload 200 AccountResponse
GET /account/profile 200 AccountResponse
PATCH /account/profile AccountProfilePatchPayload 200 AccountResponse

值得注意的演进痕迹:文档中 5 个端点以删除线标记为 DEPRECATEDPOST /account/avatar/account/interface-language/account/interface-theme/account/name/account/timezone),并统一注明 “Use PATCH /account/profile instead”。这说明账号资料(昵称、界面语言、界面主题、时区、头像)已从多个单字段 POST 收敛为单个 PATCH 部分更新语义,而废弃端点仍保留在契约中以兼容存量客户端。全文共有 9 个此类废弃端点,阅读文档时看到 ~~[POST] ...~~ 加粗 DEPRECATED 标记即应改走替代端点。

2.2 激活与邀请:带安全语义的 /activate

邀请激活接口在文档中附带了少见的行为级安全说明(原文继承):

  • POST /activateAccept an invitation without letting an existing session act for another account。token-only 激活对旧客户端仍然可用;当请求已携带 Console 会话时,该会话必须属于邀请 token 所编码的账号,才会消费 token 或变更租户成员关系。请求体 ActivatePayload,成功返回 200 ActivationResponse,400 表示已激活或 token 无效。
  • GET /activate/check:校验激活 token 是否有效,query 参数 token(必填)、email(可选)、workspace_id(可选),返回 200 ActivationCheckResponse

这种“请求携带的会话身份必须与 token 内嵌身份一致”的约束,属于在 API 层防御会话混淆(session fixation / 账号切换竞态)的典型设计,文档把它直接写进端点描述而非隐藏在实现里,是这份契约的一个亮点。

2.3 应用清单:GET /agent 的参数表样例

新版 Agent 应用域(/agent,57 个端点)是文档中最完整的 CRUD + 子资源示例之一。以 GET /agent 的参数表为例(完整继承原文档):

参数 位置 说明 必填 类型
creator_ids query Filter by creator account IDs string[]
is_created_by_me query Filter by creator boolean
limit query Page size (1-100) integer,默认 20
mode query App mode filter string,可选值 "advanced-chat", "agent", "agent-chat", "all", "channel", "chat", "completion", "workflow",默认 all
name query Filter by app name string
page query Page number (1-99999) integer,默认 1
publication_status query 已发布/草稿 Agent 配置状态过滤 string,可选值 "drafts", "published"
sort_by query 排序 string,可选值 "earliest_created", "last_modified", "recently_created",默认 last_modified
tag_ids query Filter by tag IDs string[]

成功返回 200 AgentAppPagination。写操作的错误语义同样完整:

  • POST /agent(创建):请求体 AgentAppCreatePayload;201 返回 AgentAppDetailWithSite,400 参数非法,403 权限不足,409 名称已存在;
  • PUT /agent/{agent_id}(更新):200 AgentAppDetailWithSite,400/403 同上;
  • DELETE /agent/{agent_id}:204 成功(无响应体),403 权限不足;
  • POST /agent/{agent_id}/copy(复制):201 返回新应用详情,400/403 同上。

/agent/{agent_id} 下的子资源覆盖了 Agent 应用的一整套生命周期能力,均按“资源/动作”子路径组织:

  • Service API 访问GET /api-accessPOST /api-enable(请求体 AgentApiStatusPayload)、GET|POST /api-keys(POST 201 返回 ApiKeyItem,400 表示超出最大 key 数)、DELETE /api-keys/{api_key_id}(204);
  • 音频转写POST /audio-to-text 使用 multipart/form-datafile 二进制 + draft_type 可选 debug_build|draft,默认 draft),错误码区分 400(语音转文字未启用或音频不支持)、404(Agent 或构建草稿不存在)、413(音频过大);
  • 构建草稿(build-draft)GET|PUT|DELETE /build-draftPOST /build-draft/apply(应用草稿)、POST /build-draft/checkout(检出,请求体 AgentBuildDraftCheckoutPayload)、POST /build-chat/finalize(运行一轮“让 Agent 推送配置更新”的构建对话);
  • ComposerGET|PUT /composerGET /composer/candidatesPOST /composer/validate,请求体统一为 ComposerSavePayload
  • 配置文件与技能包GET|POST /config/filesDELETE /config/files/{name}GET /config/files/{name}/download|previewGET /config/manifestGET /config/skillsPOST /config/skills/upload(multipart 上传 zip 技能包)、DELETE /config/skills/{name}GET /config/skills/{name}/inspect|download 以及技能包内文件的 content|preview|downloaddownload/preview 需带 path 参数指向 zip 内归一化成员路径)。这些端点普遍支持 draft_type(省略或 draft 为普通草稿,debug_build 为构建草稿)与 version_id(只读查看已发布快照)两个 query 参数,形成“草稿面 × 版本面”的双维寻址;
  • 消息与会话GET /chat-messages(必填 conversation_idfirst_id + limit(1-100,默认 20)做无限滚动分页,返回 MessageInfiniteScrollPaginationResponse)、GET /chat-messages/{message_id}/suggested-questionsPOST /chat-messages/{task_id}/stop(停止生成中任务)。

2.4 工作空间域:管理面的最大体量

/workspaces 域贡献了全部 223 个端点中的最大份额,覆盖成员管理(邀请、转移 Owner、RBAC)、模型与工具供应商配置、插件管理、端点密钥、模型负载均衡(load_balancing_config)等。文档中同样收录了静态资源型端点,例如 GET /workspaces/{tenant_id}/model-providers/{provider}/{icon_type}/{lang} 返回模型供应商图标(200,无 JSON 响应体)。这些端点的控制器分布在 controllers/console/workspace/ 目录下,与文档一一对应。

2.5 default 命名空间

## default 段(L13012)收录了不挂在 console 命名空间路径下的端点,目前为 GET /explore/banners(query:language,默认 en-US,返回 BannerListResponse)。随后 L13031 的 ### Schemas 附录给出全部被引用的请求/响应模型字段表,例如 AIModelEntity 字段包括 fetch_fromlabel(i18n 对象)、modelmodel_propertiesmodel_typeparameter_rulespricing 等,与端点表通过锚点链接([PriceConfig](#priceconfig))构成可跳转的交叉引用网络。

三、FastOpenAPI Preview:OpenAPI 3.1 预览段

文档末尾(L25016 起)是 ## FastOpenAPI Preview (OpenAPI 3.1) 段,标题即 “FastOpenAPI proof of concept for Dify API”。这一段不是手工补写的,而是由独立管线生成后降级标题两档追加到 console 文档末尾的(见 生成脚本_append_fastopenapi_markdown)。当前 PoC 段收录的端点与模型如下(完整继承原文档):

方法与路径 说明 请求体 / 参数 成功响应
GET /console/api/init Get initialization validation status 200 InitStatusResponse
POST /console/api/init Validate initialization password InitValidatePayload 201 InitValidateResponse
GET /console/api/ping Health check endpoint for connection testing 200 PingResponse
GET /console/api/setup 获取系统安装状态;设计上未认证——首次引导期还没有管理员账号,前端初始化必须能在任何登录流存在之前查询安装进度,因此只允许返回 bootstrap-safe 的状态信息 200 SetupStatusResponse
POST /console/api/setup 以管理员账号初始化系统;设计上未认证,仅限自托管版(COMMUNITYENTERPRISE),由一次性安装守卫与 init-password 校验而非用户会话来保护 SetupRequestPayload 201 SetupResponse
GET /console/api/version 检查应用版本更新 query:current_version(必填) 200 VersionResponse

对应模型定义了首装引导的完整字段契约:SetupRequestPayloademail 必填、name 必填且最长 30 字符、password 必填、language 可选)、SetupStatusResponsestep 枚举 finished|not_startedsetup_at 为 ISO 时间)、InitStatusResponsestatus 枚举 finished|not_started)、VersionResponseversion + release_notes)、ErrorSchemadetails/message/status/type 错误四元组)。值得注意的是,文档把“该端点为何不认证”直接写进端点描述——这类安全边界说明通常只存在于内部设计文档,出现在自动生成的契约里对 Agent 调用方与第三方集成者都有直接价值。

四、文档如何生成:从路由到 Markdown 的完整管线

理解“文档为什么长这样”,关键在于 api/dev/ 下三个脚本的协作。整条管线刻意不启动完整后端,这也是文档与代码保持同源却又不依赖运行环境的设计核心。

4.1 第一步:不启动后端导出 OpenAPI JSON

generate_swagger_specs.py 的 docstring 说明了动机:正常后端启动会急加载数据库、Redis、Celery 与存储扩展,而导出契约只需要序列化 Flask-RESTX 的 /openapi.json。其 create_spec_app() 的做法是:

  1. 通过 apply_runtime_defaults() 注入最小配置(SECRET_KEY=spec-export、本地存储路径、强制 SWAGGER_UI_ENABLED=True);
  2. 新建一个裸 Flask 应用,仅注册 controllers.consolecontrollers.webcontrollers.service_apicontrollers.openapi 四个 blueprint,让路由装饰器在导入期完成登记;
  3. 对每个 namespace 调用 _materialize_inline_model_definitions(),把遗留代码里匿名的 fields.Nested({...}) 内联字段映射,用 SHA-1 签名指纹改写成稳定命名的 _AnonymousInlineModel_<12位摘要> 命名模型,保证输出确定且可 diff;
  4. app.test_request_context(target.route) 中调用 Swagger(api).as_dict(),再经 flask_restx_compat.finalize_openapi_payload 排序数组后落盘为键序稳定的 console-openapi.json 等四个文件。

4.2 第二步:swagger-markdown 转换与三处定点修补

generate_swagger_markdown_docs.pyswagger-markdown@3.0.0npx --yes swagger-markdown@3.0.0 -i <spec> -o <out>)做 JSON→Markdown 转换,并在转换前后做四件确定性的修补,这些细节直接解释了本文档的版式特征:

  • 去 null 值_drop_null_values_for_markdown):仅对转换器临时输入剔除 null 成员,避免空字段干扰渲染;
  • union 类型回填_patch_union_schema_markdown):swagger-markdownoneOf/anyOf 联合类型会把表格单元格留空,脚本会解析 spec 中每个 schema 的属性与联合变体,把 [Ref](#anchor) 形式的类型链接回填进表格——这就是文中大量 [ string ]string, **Available values:** "a", "b" 写法由生成器统一产出的原因;
  • 通配媒体类型防误渲染_patch_wildcard_media_type_markdown):把 ***/*** 改写为 `*/*`,防止 Markdown 把 */* 当强调符;
  • 行尾空白清理_strip_trailing_line_whitespace):仅去尾随空白,不改变行结构,保证产物可稳定 diff。

对 FastOpenAPI 的 spec 则走 _append_fastopenapi_markdown():先把其 Markdown 的标题统一降级两档(####),再挂到 console 文档的 ## FastOpenAPI Preview (OpenAPI 3.1) 之下;同时删除历史遗留的合并版 api-reference.mdSTALE_COMBINED_MARKDOWN_FILENAME),防止双份文档并存。

4.3 本地再生成与校验命令

文档头部没有手工维护项,官方推荐的再生产与校验方式是(摘自 API_SCHEMA_GUIDE.md 的 “Verifying Swagger” 一节):

# schema 与文档相关单元测试
uv run --project . pytest tests/unit_tests/controllers/common/test_schema.py
uv run --project . pytest tests/unit_tests/commands/test_generate_swagger_specs.py tests/unit_tests/controllers/test_swagger.py

# 重新导出 OpenAPI JSON 并抽查
uv run --project . dev/generate_swagger_specs.py --output-dir /tmp/dify-openapi-check

生成 Markdown 全量文档(含 FastOpenAPI 追加段)则运行:

cd api && uv run python dev/generate_swagger_markdown_docs.py \
  --openapi-dir openapi --markdown-dir openapi/markdown --keep-swagger-json

其中 --keep-swagger-json 会保留中间 JSON spec 便于比对;--openapi-dir/--markdown-dir 分别控制 JSON 与 Markdown 的落盘目录(默认 openapi/openapi/markdown/,即本文档所在目录)。指南同时给出 jq 抽查清单:GET 参数必须是 in: query、请求体只出现在有 body 的端点、响应引用期望的 *Response schema、响应 schema 使用公开序列化名而非 inputs_dict 之类内部校验别名。

4.4 契约与实现同源的命名与注册约定

文档里 *Payload/*Query/*Response 的系统化命名不是格式巧合,而是 API_SCHEMA_GUIDE.md 强约束的实现模式:请求体用 Payload 后缀的 Pydantic 模型,query 参数用 Query 后缀模型并通过 query_params_from_model(...) 展开(禁止对 GET 使用 @ns.expect,那会把 query 参数错标成请求体),响应 DTO 继承 fields.base.ResponseModel 并经 dump_response(...) 显式序列化。运行时校验与 Swagger 文档绑定在同一个 Pydantic 模型上——这正是 console-openapi.md 中每个端点的参数表、请求体表能与真实校验行为完全一致的根本原因。

五、消费这份文档的三种姿势

  1. 集成开发(面向人):以本文为端点目录与字段字典,按资源域定位能力;所有枚举、默认值、取值范围(如 limit 1-100、page 1-99999)直接来自 Pydantic 约束,可原样用于客户端代码生成与请求构造;
  2. 面向 LLM/Agent 的工具调用:文档的“端点 → 参数表 → 响应 Schema 锚点”结构天然适合检索式消费——按资源域前缀检索端点,再顺锚点跳转到 Schemas 附录取字段定义。FastOpenAPI 3.1 段的出现意味着未来将有一份原生 3.1 JSON 契约可供更强的代码生成链路消费;
  3. 变更审查(面向维护者):由于文档是生成物,任何 PR 只要改动控制器模型或路由,重跑 4.3 节的管线即可在 diff 中看到契约变化;这也是仓库选择“CI 与本地再生成都走同一转换器”的原因——转换器不兼容的 OpenAPI 输出会在再生成阶段被提前暴露。

六、小结

console-openapi.md 不是一篇需要人工维护的 API 手册,而是 Dify Console 管理面(790 个端点、四个 API 面之一)在 Flask-RESTX 路由与 Pydantic 模型之上自动投影出的机器可读契约:端点签名、枚举、默认值、废弃标记(9 个)与安全语义说明(如 /activate 的会话一致性约束、/setup 的免认证引导边界)全部与实现同源。配合 文档生成脚本规范导出器API 模式指南,本文给出了从“读懂这份 2.5 万行契约”到“再生成、校验与消费它”的完整路径。

登录后查看全文
热门项目推荐
相关项目推荐