Ghostfolio 3.90.0 API 使用详解
Ghostfolio 3.90.0 自托管 REST API 逐域实测:注册换令牌、账户、活动导入导出、组合持仓与 v2 绩效接口、自建资产档案,每条请求附真实响应与错误码
Ghostfolio 3.90.0 API 使用详解
目标:逐域实测 Ghostfolio 3.90.0 自托管 REST API——注册换令牌、账户、活动导入导出、组合分析与 v2 绩效接口,每条请求附真实响应。全部示例已在自托管实例(Ubuntu 22.04 + Docker Compose 栈)用 curl 实测通过。
一、环境信息
- Ghostfolio:3.90.0(Docker 镜像
ghostfolio/ghostfolio:3.90.0部署,API 基址http://127.0.0.1:3333) - 操作系统:Ubuntu 22.04 LTS(x86_64)
- 客户端工具:curl 7.81.0(系统自带)+ python3 -m json.tool(格式化)
- 认证样例:
JWT变量存放登录令牌(获取方式见四、) - 接口前缀:
/api/v1(绝大部分路由)与/api/v2(绩效等新路由,见 3.1)
二、前置条件
2.1 端点与客户端
API 与 Web 同端口同进程:http://<服务器IP>:3333/api/...。本文全部用系统 curl 发请求(无需额外 SDK),健康检查确认服务可用:
curl -s http://127.0.0.1:3333/api/v1/health
{"status":"OK"}
2.2 认证方式总述
两种凭据,全部经 Authorization: Bearer 头传递:
- authToken(JWT):登录后签发,有效期 30 天(实测签发载荷
"exp":签发+30天),API 调用首选; - accessToken(128 位访问令牌):注册时一次性领取的用户凭据,用于 Web 端登录与「令牌换发 JWT」。
Ghostfolio 3.90.0 无静态 API Key 体系(
POST /api/v1/api-keys属 Premium 权益,自托管实测 403,见八、8.3),机读一律走 JWT。
三、API 总览
3.1 版本与路由形态(实查源码控制器清单)
3.90.0 后端共 30+ 个控制器,主前缀 /api/v1。已实查的完整域清单:auth、user、account、account-balance、activities、activity、import、export、portfolio、access、asset-profiles、assets、asset、market-data、symbol、tags、watchlist、benchmarks、platform(s)、info、health、api-keys、admin、admin/queue、cache、logo、subscription、ai、public、data-providers/ghostfolio。
@Version('2') 标注的 v2 路由(实查源码):
GET /api/v2/portfolio/performance(组合绩效)data-providers/ghostfolio域 5 个端点(Premium 数据源 API)
⚠️ 混用版本会得到误导性 404:
GET /api/v1/portfolio/performance实测返回Cannot GET ...,正确路径是/api/v2/portfolio/performance。
3.2 认证与通用错误码约定
- 未带令牌访问受保护端点 →
401 {"message":"Unauthorized","statusCode":401}; - 令牌无效/盐变更后旧令牌 →
403 {"message":"Forbidden"}; - 请求体校验失败 →
400 {"error":"Bad Request","message":[...]}(message 为字段级错误数组); - 路由不存在 → NestJS 标准
404 {"message":"Cannot GET /api/v1/xxx","error":"Not Found","statusCode":404}; - 限流:注册端点挂
CustomThrottlerGuard(THROTTLE_SIGNUP_LIMIT控制),触发后返回 429。
四、认证域:注册与登录
4.1 注册(POST /api/v1/user)
自托管注册即「创建用户 + 领取访问令牌」,无邮箱字段;首个注册用户自动成为管理员:
curl -s -X POST http://127.0.0.1:3333/api/v1/user -H 'Content-Type: application/json' -d '{"languageCode":"en"}'
实测回显:
{"accessToken":"da5e8b1e580837b49ddb7e98ddb9e32104d2862da46b5fd4320df9e2e4dab851c099bfc71eb9a3fa026e016a1bdb089e29b24b2ddf73f70864aded4759e4bb0d","role":"ADMIN","authToken":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjI1OTk0ODEzLTMwNGMtNGNmMy04ZGM2LWNjMjRkYjA3OTAzNSIsImlhdCI6MTc5MjczOTk3MCwiZXhwIjoxNzk1MzMxOTcwfQ.TINiCPrIvIgzpnvUFWOMVguKpKOtvs8ANvrwxyVCGn8"}
字段说明:accessToken 为 128 位十六进制用户凭据(等价密码,妥善保存);authToken 即后续 API 用的 JWT。
传不认识的字段会被 400 拒绝(实测传 email/fullName/password 返回 "property email should not exist" 等三条校验错误)。
4.2 访问令牌换发 JWT(POST /api/v1/auth/anonymous)
JWT=$(curl -s -X POST http://127.0.0.1:3333/api/v1/auth/anonymous -H 'Content-Type: application/json' -d '{"accessToken":"<你的128位令牌>"}' | python3 -c 'import json,sys;print(json.load(sys.stdin)["authToken"])')
echo ${#JWT}
实测回显:
187
错误路径实测:令牌错误时返回 {"statusCode":403,"message":"Forbidden"};ACCESS_TOKEN_SALT 被更换后同样 403(盐参与令牌哈希,实测见配置篇 5.3)。
五、账户域(/api/v1/account)
5.1 查询账户列表(GET /api/v1/account)
curl -s http://127.0.0.1:3333/api/v1/account -H "Authorization: Bearer $JWT" | python3 -m json.tool | head -12
实测回显(注册时自动创建的默认账户):
[
{
"comment": null,
"createdAt": "2026-10-23T07:19:30.217Z",
"currency": "USD",
"id": "0ae9c74f-25d0-4693-8289-43d35d04d97f",
"name": "My Account",
"platformId": null,
"userId": "25994813-304c-4cf3-8dc6-cc24db079035"
}
]
5.2 创建账户(POST /api/v1/account)
curl -s -X POST http://127.0.0.1:3333/api/v1/account -H "Authorization: Bearer $JWT" -H 'Content-Type: application/json' -d '{"name":"券商A","currency":"USD","platformId":null,"comment":"D5 实测账户"}'
实测回显:
{"comment":"D5 实测账户","createdAt":"2026-10-23T07:40:04.996Z","currency":"USD","id":"79478b88-485e-43e8-93cf-0e6258480bb4","name":"券商A","platformId":null,"updatedAt":"2026-10-23T07:40:04.996Z","userId":"2599481..."}
同名域还提供 PUT /api/v1/account/:id(更新)、DELETE /api/v1/account/:id(删除)、GET /api/v1/account-balance(现金余额)。
六、活动与导入导出域
6.1 导入活动(POST /api/v1/import)
请求体四类数组:accounts、activities、assetProfiles、platforms、tags(后四者可选/必填混合,activities 必填)。活动字段:type(BUY/SELL/DIVIDEND…)、symbol、dataSource、date、quantity、unitPrice、fee、currency。
成功导入两笔(自建资产,创建方式见 8.1):
curl -s -X POST http://127.0.0.1:3333/api/v1/import -H "Authorization: Bearer $JWT" -H 'Content-Type: application/json' -d '{
"activities": [
{"type":"BUY","symbol":"GF_QZFUND1","dataSource":"MANUAL","date":"2025-01-15T00:00:00.000Z","quantity":100,"unitPrice":10.5,"fee":2,"currency":"USD","comment":"建仓"},
{"type":"DIVIDEND","symbol":"GF_QZFUND1","dataSource":"MANUAL","date":"2025-06-30T00:00:00.000Z","quantity":100,"unitPrice":0.15,"fee":0,"currency":"USD"}
]
}' | python3 -m json.tool | head -22
实测回显(节选):
{
"activities": [
{
"comment": "建仓",
"currency": "USD",
"date": "2025-01-15T00:00:00.000Z",
"fee": 2,
"id": "74d944d8-0ce1-46a5-833c-f89e91dec61e",
"quantity": 100,
"type": "BUY",
"value": 1050,
"valueInBaseCurrency": 1050
}
]
}
典型 400 错误实测(YAHOO 数据源无法解析符号,受限网络环境):
{"error":"Bad Request","message":["activities.0.symbol (\"AAPL\") cannot be resolved by the data source (\"YAHOO\")"]}
自建资产符号缺 GF_ 前缀实测:
{"error":"Bad Request","message":["activities.0.symbol (\"GF_QZFUND1\") must be a UUID or start with the prefix \"GF_\" for the data source (\"MANUAL\")"]}
6.2 导出全量数据(GET /api/v1/export)
curl -s http://127.0.0.1:3333/api/v1/export -H "Authorization: Bearer $JWT" | python3 -c "import json,sys; d=json.load(sys.stdin); print('meta:',d['meta']['version'],'| activities:',len(d['activities']),'| accounts:',len(d['accounts']))"
实测回显:
meta: 3.90.0 | activities: 2 | accounts: 1
导出 JSON 与导入格式同构,可直接回灌另一实例(跨实例迁移的官方姿势)。
同域还有 GET/POST/PUT/DELETE /api/v1/activities(单笔活动 CRUD,导入接口之外细粒度维护用)。
七、组合分析域(/api/v1/portfolio、/api/v2/portfolio/performance)
7.1 持仓明细(GET /api/v1/portfolio/holdings)
curl -s http://127.0.0.1:3333/api/v1/portfolio/holdings -H "Authorization: Bearer $JWT" | python3 -c "import json,sys; h=json.load(sys.stdin)['holdings'][0]; print(h['assetProfile']['symbol'], h['assetProfile']['name'], '| 数量', h['quantity'], '| 市值', h['valueInBaseCurrency'], '| 占比', h['allocationInPercentage'])"
实测回显:
GF_QZFUND1 青竹全球ETF | 数量 100.0 | 市值 1050.0 | 占比 1.0
7.2 组合总览(GET /api/v1/portfolio/details)
curl -s "http://127.0.0.1:3333/api/v1/portfolio/details?range=max" -H "Authorization: Bearer $JWT" | head -c 300
实测回显(节选):
{"accounts":{"0ae9c74f-25d0-4693-8289-43d35d04d97f":{"balance":0,"currency":"USD","name":"My Account","valueInBaseCurrency":0}},"createdAt":"2026-10-23T07:20:38.173Z","hasError":false,"holdings":[],...}
7.3 组合绩效(GET /api/v2/portfolio/performance)——注意 v2
curl -s "http://127.0.0.1:3333/api/v2/portfolio/performance?range=max" -H "Authorization: Bearer $JWT" | python3 -m json.tool | head -14
实测回显(导入 1050 美元建仓后):
{
"chart": [],
"hasErrors": false,
"performance": {
"currentNetWorth": 1050,
"currentValueInBaseCurrency": 1050,
"dividendInBaseCurrency": 15,
"netPerformance": 15,
"netPerformancePercentage": 0.01428571428571429,
"totalInvestment": 1050
}
}
range 取值:today/wtd/mtd/ytd/1y/5y/max;同域还有 GET /api/v1/portfolio/dividends(分红)、/investments(投入)、/report(静态风险分析)、/holding/:dataSource/:symbol(单持仓详情)。
八、管理与资产档案域
8.1 自建资产档案(POST/PATCH /api/v1/admin/profile-data/:dataSource/:symbol)
创建(符号必须 GF_ 前缀):
curl -s -X POST "http://127.0.0.1:3333/api/v1/admin/profile-data/MANUAL/GF_QZFUND1" -H "Authorization: Bearer $JWT" -H 'Content-Type: application/json' -d '{"currency":"USD"}' | head -c 200
实测回显(节选):
{"currency":"USD","dataGatheringFrequency":"DAILY","dataSource":"MANUAL","symbol":"GF_QZFUND1",...}
更新名称与分类(PATCH,实测返回 200):
curl -s -X PATCH "http://127.0.0.1:3333/api/v1/admin/profile-data/MANUAL/GF_QZFUND1" -H "Authorization: Bearer $JWT" -H 'Content-Type: application/json' -d '{"name":"青竹全球ETF","assetClass":"EQUITY","assetSubClass":"ETF"}' -o /dev/null -w '%{http_code}\n'
200
8.2 管理面板数据(GET /api/v1/admin)
curl -s http://127.0.0.1:3333/api/v1/admin -H "Authorization: Bearer $JWT" | head -c 320
实测回显(节选):
{"activitiesCount":2,"dataProviders":[{"dataSource":"COINGECKO","isPremium":false,"name":"CoinGecko"},{"dataSource":"GHOSTFOLIO","isPremium":true,"name":"Ghostfolio"},...]}
8.3 API Key 的权限边界(POST /api/v1/api-keys 实测 403)
curl -s -X POST http://127.0.0.1:3333/api/v1/api-keys -H "Authorization: Bearer $JWT" -H 'Content-Type: application/json' -d '{}'
实测回显:
{"statusCode":403,"message":"Forbidden"}
实测自托管 ADMIN 用户 permissions 数组中不含 createApiKey——数据源 API Key(GHOSTFOLIO 官方数据源)属 Ghostfolio Premium 订阅权益;自托管免费层机读一律走 30 天 JWT(四、)。
8.4 用户与系统信息
curl -s http://127.0.0.1:3333/api/v1/user -H "Authorization: Bearer $JWT" | head -c 260
实测回显(节选,权限矩阵):
{"activitiesCount":2,"id":"25994813-304c-4cf3-8dc6-cc24db079035","permissions":["accessAdminControl","accessAssistant","accessHoldingsChart","createAccess","createAccount","createAccountBalance","createActivity",...]}
curl -s http://127.0.0.1:3333/api/v1/info
实测回显:
{"benchmarks":[],"globalPermissions":["enableAuthToken","createUserAccount"],"baseCurrency":"USD","currencies":["USD","USX"]}
/api/v1/info 无需认证,可作为客户端探测实例能力的探针(globalPermissions 反映注册是否开放等)。
九、通用约定
9.1 过滤参数
组合分析域端点普遍支持过滤器查询参数(源码 GetPerformanceDto 实查):accounts(按账户)、assetClasses(资产大类)、dataSource、symbol、tags、groupBy(月/年聚合)、range(时间范围)、withExcludedAccounts。示例:只看指定账户的绩效:
curl -s "http://127.0.0.1:3333/api/v2/portfolio/performance?range=max&accounts=<账户ID>" -H "Authorization: Bearer $JWT" -o /dev/null -w '%{http_code}\n'
200
9.2 分页与响应形态
实测 3.90.0 组合/导出类端点为全量返回、无分页参数(个人财富管理场景数据量可控);活动列表经 /api/v1/activities 查询时支持按账户/标签/日期过滤。批量维护活动优先走导入接口(一次可挂数百笔,官方 CSV 导入亦经同一后端链路)。
9.3 数据源取值
活动与资产档案的 dataSource 只能取实例支持的值(实测为 YAHOO、MANUAL、COINGECKO,GHOSTFOLIO 需 Premium Key),传其他值在符号解析阶段 400。
十、常见问题(FAQ)
Q1:/api/v1/portfolio/performance 返回 404?
该路由在 v2:GET /api/v2/portfolio/performance。源码中该端点标注 @Version('2'),v1 前缀下不存在(实测对比见 3.1)。
Q2:注册接口传邮箱密码报错?
自托管注册不接受邮箱/密码字段(实测 400 property email should not exist),Ghostfolio 用户体系基于访问令牌(+可选 OIDC/Passkey),经 Web 界面或 POST /api/v1/user 创建。
Q3:令牌突然全部 403?
先查 ACCESS_TOKEN_SALT 是否被改动(盐变即凭据失效,实测见配置篇);再查 JWT_SECRET_KEY 是否变更(JWT 全部过期,重新用 accessToken 换发即可)。
Q4:导入报 symbol cannot be resolved?
默认数据源 YAHOO 需外网可达。受限网络改自建资产(8.1 建 GF_ 档案)或配 CoinGecko Key(配置篇 5.6)。
Q5:authToken 过期怎么办?
30 天有效期(签发载荷可解出 exp)。用保存的 accessToken 重新 POST /api/v1/auth/anonymous 换发;accessToken 本身遗失且无法登录时,管理员可在 Web 界面「用户」页为其重置访问令牌。
十一、参考链接
- 部署实操(本文 API 所测实例的搭建过程):《Ghostfolio 3.90.0 Docker Compose 部署指南》、《Ubuntu 22.04 安装 Ghostfolio 3.90.0 指南》
- 参数与安全配置:《Ghostfolio 3.90.0 配置参数详解》
- 路由清单实查依据:仓库
apps/api/src/app/(tag 3.90.0,查询日期 2026-10-23):https://github.com/ghostfolio/ghostfolio/tree/3.90.0/apps/api/src/app