EDA API 使用详解

EDA(Edalitics)API 使用详解:JWT 登录认证、数据源管理与 SQL 直查、仪表盘 CRUD 共 66 个 REST 端点,全部 curl 实测回显(含 400/401/500 错误实测),OpenAPI 描述文件与 token 传参约定,基于 2026-10-30 实测镜像。

EDAEDABIMySQL2026/10/30

EDA API 使用详解

目标:把 EDA(Edalitics)的 REST API 讲到可编程调用——认证拿 token、管理数据源、SQL 直查取数、仪表盘增删查——每一步都给 curl 请求与实测响应。已在 2026-10-30 对 jortilles/eda:latest 镜像实测通过(API 内部版本声明 3.2.0 开发版,稳定发布 tag edalitics-3.1.2),环境搭建见《EDA Docker Compose 部署指南》。

一、环境信息

  • 实测服务:jortilles/eda:latest(2026-10-30 拉取),API 经 Web 层反代路径 /edapi/ 暴露,宿主端口 8134
  • API 自描述文件:镜像内 /eda/eda_api/openapi.json(title: "Enterprise Data Analytics (EDA) Documentation",version: 2.0.1,共 66 个路径)
  • 实测数据源:MySQL 8.4 样例库 salesdb(3 表 20 行销售数据,建库脚本见部署篇 4.1)
  • 客户端工具:curl + python3(解析 JSON)
  • 相关测试账号:默认管理员 eda@jortilles.com / default

二、前置条件

  • 已部署并启动 EDA(见《EDA Docker Compose 部署指南》),Web 端口可达;
  • 理解两个基地址:浏览器界面在 http://<host>:<port>/,API 在 http://<host>:<port>/edapi/(后者是 Apache 对内部 8666 端口的反代前缀,所有下文端点都以此为根);
  • 客户端工具任选:curl、HTTPie 或任一 OpenAPI 兼容工具(把镜像内 openapi.json 导出后可导入 Postman/Apifox 生成全部接口定义);
  • 提示:API 域与界面功能一一对应,操作前建议先在界面完成一遍"建数据源 → 建图表"以理解模型概念(见《EDA 配置参数详解》5.4 节的参数说明)。

三、API 总览

协议与风格:HTTP REST + JSON;认证走 JWT;除登录外的全部端点需要携带 token。

端点域清单(按 openapi.json 与路由表归纳,66 路径):

域前缀典型端点用途
认证/admin/userPOST /admin/user/login登录换 JWT;SSO 回调在 /auth/*
用户与组/admin/user、/admin/groupsGET /admin/user/me/{id}、GET /admin/groups/用户/角色/组管理(EDA_ADMIN)
数据源/datasourcePOST /add-data-source/、GET /names、GET /{id}、GET /check-connection/{id}、POST /remove-cache连接管理、缓存刷新
查询/dashboard/query、/dashboard/sql-query、/datasource/queryPOST模型查询与 SQL 直查
仪表盘/dashboardPOST /、GET /、GET /{id}、PUT /{id}、DELETE /{id}、POST /{id}/clone看板 CRUD 与克隆
文件/global/upload、/excel-sheetsPOST /global/upload、POST /excel-sheets/add-json-data-sourceCSV/Excel 导入(内建 DuckDB)
表补挂/addTablePOST /addTable/create、POST /addTable/insert向模型追加源表
邮件/mailPOST /mail/...触发邮件发送
AI/assistant、/ia、/arimaPOST /assistant/prompt、POST /ia/chat、POST /arima/predictAI 问数、MCP、时序预测
自定义/customHTML/{key}、/customActionCall/checkGET/POST自定义内容注入

认证约定(实测):token 以 query 参数 ?token=<JWT> 传递(所有受保护端点一致);无效或缺失 token 统一返回 401 {"status":401,"message":"Invalid Token"}(实测回显)。JWT 有效期 4 小时(源码 expiresIn: 14400)。

响应与错误码约定:

状态码语义实测触发方式
200成功各 GET / 查询端点
201创建成功POST /datasource/add-data-source/、POST /dashboard/
400参数/业务校验失败登录用户不存在:{"status":400,"message":"Incorrect user"}
401token 无效/缺失?token=badtoken 访问受保护端点
500服务端/查询错误SQL 语法错、连接失败、参数结构错

⚠️ 注意:EDA 的错误响应是小写状态对象 {"status":400,"message":"..."},与成功响应的 {ok:true,...} 风格不同;写客户端时按 HTTP 状态码判断,不要只看 body。

四、认证与首次调用

4.1 登录获取 token

curl -s -X POST http://localhost:8134/edapi/admin/user/login \
  -H "Content-Type: application/json" \
  -d '{"email":"eda@jortilles.com","password":"default"}'

实测回显(节选,token 长 308 字符):

{"user":{"_id":"135792467811111111111111","role":["135792467811111111111110"],"name":"EDA","email":"eda@jortilles.com","password":":)","...},"token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyIjoi...","id":"135792467811111111111111"}

把 token 存入变量供后续调用:

TOKEN=$(curl -s -X POST http://localhost:8134/edapi/admin/user/login \
  -H "Content-Type: application/json" \
  -d '{"email":"eda@jortilles.com","password":"default"}' \
  | python3 -c "import json,sys;print(json.load(sys.stdin)['token'])")
echo ${#TOKEN}    # 实测输出 308

4.2 登录错误实测

请求体字段写错(用 user 而不是 email):

{"status":400,"message":"Incorrect user"}

密码错误:

{"status":400,"message":"Incorrect credentials - password"}

4.3 当前用户信息

curl -s "http://localhost:8134/edapi/admin/user/me/135792467811111111111111?token=$TOKEN"

返回当前账号档案与角色组(role 数组里 135792467811111111111110 即 EDA_ADMIN 组 ID)。

五、各 API 域详解

5.1 数据源域(/datasource)

5.1.1 创建数据源 POST /datasource/add-data-source/?token=<JWT>

请求体为裸连接对象(14 字段语义见《EDA 配置参数详解》5.4 节):

curl -s -X POST "http://localhost:8134/edapi/datasource/add-data-source/?token=$TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name":"salesdb-mysql","type":"mysql","host":"eda-mysql","database":"salesdb","port":3306,"user":"edauser","password":"q1w2e3r4","warehouse":null,"schema":null,"poolLimit":10,"sid":1,"optimize":0,"allowCache":1,"ssl":false,"filter":null,"external":{}}'

实测回显(HTTP 201):

{"ok": true, "data_source_id": "6ae3ffe5ddadf93009f1d2e5"}

⚠️ 注意:实测把对象包成 {"datasource":{...}} 再传会得到 500 {"status":500,"message":"Cannot read properties of null (reading 'generateDataModel')"}——不要包装。另:API 创建的数据源 model.queries 为空(查询树未生成),需在界面打开该数据源「编辑」保存一次触发模型生成,或用 /addTable/create、/datasource/reload/{id} 补齐;界面操作则自动生成。

5.1.2 数据源列表 GET /datasource/names?token=<JWT>

实测回显:

{"ok":true,"ds":[{"_id":"6ae3ffe5ddadf93009f1d2e5","model_name":"salesdb-mysql"}]}

5.1.3 数据源详情 GET /datasource/{id}?token=<JWT>

实测回显(结构节选):

{"ok":true,"dataSource":{"_id":"6ae3ffe5ddadf93009f1d2e5","ds":{
  "connection":{"type":"mysql","host":"eda-mysql","database":"salesdb","port":3306,
                "user":"edauser","ssl":false,"poolLimit":10,...},
  "metadata":{...},"model":{"queries":[...]}}}}

(敏感提示:详情接口会回显连接配置,密码字段不在回显中,但接口本身要求 EDA 权限,生产应对该域做网络层管控。)

5.1.4 连接测试 GET /datasource/check-connection/{id}?token=<JWT>

保存前测试可用 POST /datasource/check-connection/(openapi 定义),按 ID 测已存连接用上式,返回连接可达性与错误详情——数据源连接失败排查第一步(错误树见部署篇 FAQ Q4)。

5.1.5 缓存刷新 POST /datasource/remove-cache?token=<JWT>(body 传数据源 ID)

开启 allowCache 的数据源强制清缓存,等效于界面「刷新缓存」。

5.2 查询域(SQL 直查与模型查询)

5.2.1 SQL 直查 POST /dashboard/sql-query?token=<JWT>

请求体:model_id(数据源 ID)+ query 对象(SQLexpression 必填,filters 必须给空数组):

DS=6ae3ffe5ddadf93009f1d2e5
curl -s -X POST "http://localhost:8134/edapi/dashboard/sql-query?token=$TOKEN" \
  -H "Content-Type: application/json" \
  -d "{\"model_id\":\"$DS\",\"query\":{\"SQLexpression\":\"SELECT r.region_name AS region, SUM(s.amount) AS total FROM sales s JOIN regions r ON s.region_id = r.region_id GROUP BY r.region_name ORDER BY total DESC\",\"filters\":[],\"queryMode\":\"sql\"}}"

实测回显(矩阵格式:首行为列名):

[["region","total"],[["华南",46045],["华东",39381],["华北",36529],["西南",21230]]]

实测省略 filters 的报错(HTTP 500):

{"status":500,"message":"Database query error: Cannot read properties of undefined (reading 'forEach')"}

💡 说明:查询实时下推到源库执行(EDA 不存业务数据),SQLexpression 的方言跟 model_id 指向的数据源类型走(本例 MySQL);"select ... from A, B" 逗号连接多表的老式写法不支持(服务端明确拒绝),一律用 JOIN。

5.2.2 模型化查询 POST /dashboard/query?token=<JWT> 与 POST /datasource/query?token=<JWT>

两者按"数据模型查询树"执行:请求体 {model_id, query},query 为模型查询对象(select 数组、filters、queryMode 等),由界面图表生成的查询对象结构可先用 GET /dashboard/getQuey 对照调试。适合让界面先画好图、再抓查询对象程序化重放;纯 SQL 场景直接用 5.2.1。

5.3 仪表盘域(/dashboard)

5.3.1 创建 POST /dashboard/?token=<JWT>

curl -s -X POST "http://localhost:8134/edapi/dashboard/?token=$TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"config":{"title":"区域销售总览","visible":"private","connectionProperties":null},"group":null}'

实测回显(HTTP 201):

{"ok": true, "dashboard": {"_id":"6ae40046ddadf93009f1d2e7","config":{"title":"区域销售总览","visible":"private","connectionProperties":null,"author":"EDA"},"user":"135792467811111111111111","group":[],"__v":0}}

⚠️ 注意:API 裸建的 dashboard config 只有标题等最小字段,缺布局/图表定义时,GET /dashboard/ 列表接口会因后续处理读取不到字段而返回 400(实测复现:{"status":400,"message":"Some error occurred loading dashboards"})。程序化建看板的正确姿势是:界面建好一个样板看板 → GET /dashboard/{id} 取完整 config → 改标题/图表定义后 POST 或 PUT 回去。删除测试看板后列表即恢复(实测)。

5.3.2 列表与详情 GET /dashboard/?token=<JWT>

实测回显(无看板时):

{"ok":true,"dashboards":[],"group":[],"publics":[],"shared":[],"isAdmin":true,"isDataSourceCreator":false}

返回按可见性分桶:dashboards(自己的)、group(组共享)、publics(公开)、shared(共享给我),并带 isAdmin/isDataSourceCreator 标志。

5.3.3 删除 DELETE /dashboard/{id}?token=<JWT>

实测回显(HTTP 200):

{"ok":true,"dashboard":{"_id":"6ae40046ddadf93009f1d2e7","config":{...}}}

5.3.4 其他:PUT /dashboard/{id} 全量更新、POST /dashboard/{id}/clone 克隆、GET /dashboard/{id}/visibility 查询公开状态(公开看板无需 token 即可经 view-query 取数——对外分享的看板接口不要暴露在内网之外,用反代层加访问控制)。

六、分页/过滤/排序通用约定

EDA API 没有统一的分页框架:列表类端点(datasource/names、dashboard/、admin/groups/)一次返回全量;行级数据由查询本身的 LIMIT/ORDER BY 控制(SQL 直查写在 SQLexpression 里,模型查询写在 query.limit)。缓存的模型查询受全局 MAX_STORED_ROWS: 5000 上限保护(见《EDA 配置参数详解》5.3 节)。做增量同步类集成时,按 _id/时间字段自行过滤,不要依赖服务端分页。

七、常见问题(FAQ)

Q1:token 放 header 行不行?

官方客户端(前端界面)与 openapi 定义均以 ?token= query 参数为准,实测可行;未实测 Authorization header 路径,集成时统一用 query 参数最稳。JWT 4 小时过期,客户端应实现 401 自动重登。

Q2:add-data-source 返回 500 generateDataModel?

请求体被包了一层({"datasource":{...}})。裸对象直传即可(见 5.1.1 实测对照)。

Q3:SQL 直查 500 'forEach' 错?

query 对象缺 filters 字段,补 "filters":[](见 5.2.1 实测对照)。

Q4:API 建的数据源在界面里看不到表?

API 创建不生成查询树(model.queries 为空,5.1.1 已说明)。界面打开该数据源编辑保存一次即可触发模型生成;或调 POST /addTable/create 显式挂表。

Q5:如何批量管理用户与组?

/admin/user/ 与 /admin/groups/ 域提供 CRUD(POST /admin/user/ 创建、PUT /admin/user/{id} 更新、GET /admin/groups/ 列表、GET /admin/user/is-admin/{id} 判权),需要 EDA_ADMIN token;角色就是三个固定组(EDA_ADMIN/EDA_DATASOURCE_CREATOR/EDA_RO),把用户 ID 挂进组即可。

Q6:还有哪些没讲到的端点?

完整清单以镜像内 /eda/eda_api/openapi.json 为准(66 路径,含 SSO 回调 /auth/*、文件上传 /global/upload、Excel 导入 /excel-sheets、AI /assistant /ia /arima)。本文覆盖的是自托管运维与集成最高频的认证、数据源、查询、看板四域,其余端点参数结构可从该文件直读。

八、参考链接