# Fitflare Personal API

> 此文件由 common/api_docs.py 生成。请修改接口目录后运行 python3 scripts/docs.py。

基础路径：`/api/public/v1`。全部 24 个接口均为 GET。

## 快速开始

通过 /me 直接读取自己的账户，无需档案 ID。私有模式先在仪表盘登录；YOUR_HOST 替换为部署域名。命令行示例未携带登录会话。

```sh
curl -fsS 'https://YOUR_HOST/api/public/v1/me'
```

## 访问与隐私

public/v1 只提供 GET 读取，不会主动发起 Google Health 同步。缺失或过期的派生缓存可能在读取时本地重建。

所有 /me 接口始终读取本站唯一账户，不需要选择或填写档案 ID。公开模式下任何人可匿名读取，无需登录；私有模式要求本站登录会话。文档页顶部标注当前部署的模式，文档始终可读。

这里不提供 API Key 或 Bearer Token。私有模式请先在仪表盘登录，再使用同源浏览器请求；cURL 与 Python 示例默认不带会话。

匿名公开版 API 允许跨域读取；私有模式和管理员会话响应不开放 CORS。所有 API 响应使用 private, no-store，不应在共享缓存中保存健康数据。

公开响应不包含内部 files 路径及 OAuth 凭据文件，但账户快照仍可能包含个人资料、设备和饮食记录；这不是匿名化数据。

## 范围与分页

series 与 SVG 的 limit 表示最后 N 个记录点，不等于 N 个日历天；省略时不截断。日、周、月分别由 daily、weekly、monthly 选择。

datasets 从完整本地结构化数据集的 offset 开始取 limit 条，默认 200；tables 从仪表盘内已缓存的表格分页，默认 100，不保证包含完整历史。两者 offset 默认 0，limit 上限 1000。

分页结果位于 data.rows，meta 包含 total、offset、limit、count。下一页使用 offset + count；count 为 0 或 offset + count >= total 时结束。

整数参数的空值或无法解析值回退到默认值，超出边界会被截到允许范围。未知查询参数被忽略；具体边界见接口参数表。

metrics 按逗号分隔，只选择当前数据中存在的数值指标。省略时取全部可用指标；全部名称都不匹配时也回退到全部可用指标，不返回 400。

SVG 对各指标分别归一化，适合比较走势，不适合读取绝对值。需要绝对值请使用 series JSON。

## 指标与趋势

指标卡的 latest 为最近一次有效记录（latest_date 为其日期）；avg7 / avg30 为最近 7 / 30 条有效记录的均值，按记录计数而非日历天，缺失的日子不计入。未佩戴设备的日子（无步数、无睡眠和心率）记为缺失。

trend 比较最近 7 条有效记录与再往前 7 条有效记录的均值（两段不重叠）：delta 与 percent 为差值和百分比；direction 是数值方向 up / down / flat；assessment 结合指标好坏方向给出 improving / worsening / stable，例如静息心率下降为 improving。变化幅度在指标容差内时为 flat / stable。

睡眠估算得分由 Fitflare 本地按时长、效率、睡眠结构与清醒时间计算，不是 Google 或 Fitbit 官方分数。

## 响应与错误

成功 JSON 使用 api_version、resource、generated_at、data 包装，profile_id、meta、links 按接口出现。generated_at 是派生缓存生成时间，不保证每个上游数据源同一时刻更新；空值表示缺失，不应当作 0。

业务错误通常包含 error.code 和 error.message；访问控制层也可能返回字符串 error 及顶层 code。调用端应兼容两种格式，并先检查 HTTP 状态和 Content-Type。

401 表示私有数据需要登录；404 表示资源不存在或对当前访问者不可见；服务异常可能返回 500 和文本响应。不要对认证错误无限重试。

SVG 成功返回 image/svg+xml，Markdown 返回 text/markdown，HTML 文档返回 text/html，OpenAPI 返回规范对象，均不使用业务 JSON 包装。

### 成功响应示例（合成数据）

```json
{
  "api_version": "v1",
  "resource": "series",
  "generated_at": "2026-01-02T08:00:00",
  "profile_id": "me",
  "data": {
    "granularity": "daily",
    "dimension": "date",
    "metrics": [
      {
        "key": "steps",
        "label": "步数",
        "unit": "步",
        "tone": "green"
      }
    ],
    "points": [
      {
        "date": "2026-01-01",
        "steps": 5200
      },
      {
        "date": "2026-01-02",
        "steps": null
      }
    ]
  },
  "meta": {
    "count": 2,
    "available_metrics": [
      "steps"
    ]
  }
}
```

## 账户与指标

### API 索引

`GET /api/public/v1`

个人账户入口、资源分类与文档链接。

返回：`application/json`；data 对象。

```sh
curl -fsS 'https://YOUR_HOST/api/public/v1'
```

### 我的账户

`GET /api/public/v1/me`

账户资料、概览、覆盖范围、数据地图、快照状态及链接。

返回：`application/json`；data 对象。

```sh
curl -fsS 'https://YOUR_HOST/api/public/v1/me'
```

### 仪表盘缓存

`GET /api/public/v1/me/dashboard`

完整公开仪表盘对象，包含指标、趋势、分区与表格，不包含 files。数据较多时优先使用细分接口。

返回：`application/json`；data 对象。

```sh
curl -fsS 'https://YOUR_HOST/api/public/v1/me/dashboard'
```

### 数据目录

`GET /api/public/v1/me/catalog`

各数据域的覆盖范围、核心指标、来源和状态。

返回：`application/json`；data 对象。

```sh
curl -fsS 'https://YOUR_HOST/api/public/v1/me/catalog'
```

### 概览

`GET /api/public/v1/me/overview`

最近记录、快照概况和本地恢复估算。

返回：`application/json`；data 对象。

```sh
curl -fsS 'https://YOUR_HOST/api/public/v1/me/overview'
```

### 覆盖范围

`GET /api/public/v1/me/coverage`

各数据集记录数及起止日期。

返回：`application/json`；data 对象。

```sh
curl -fsS 'https://YOUR_HOST/api/public/v1/me/coverage'
```

### 指标列表

`GET /api/public/v1/me/metrics`

指标最新值、7/30 天均值及趋势信息。

返回：`application/json`；data 对象。

```sh
curl -fsS 'https://YOUR_HOST/api/public/v1/me/metrics'
```

### 单项指标

`GET /api/public/v1/me/metrics/{metric_key}`

按 key 读取一张指标卡；不存在的指标返回 404。

返回：`application/json`；data 对象。

| 参数 | 位置 | 约束 | 说明 |
| --- | --- | --- | --- |
| `metric_key` | path | string · 必填 | 从 /metrics 获取指标 key。 |

```sh
curl -fsS 'https://YOUR_HOST/api/public/v1/me/metrics/steps'
```

### 相关性

`GET /api/public/v1/me/correlations`

缓存中的相关系数、强度和重叠点数，仅供描述性参考。

返回：`application/json`；data 对象。

```sh
curl -fsS 'https://YOUR_HOST/api/public/v1/me/correlations'
```

## 趋势与图表

### 趋势序列

`GET /api/public/v1/me/series/{granularity}`

从完整本地数据聚合序列，按指标选择列，按 limit 截取最后若干点。

返回：`application/json`；data.points[]：序列点；data.metrics[]：单位等元数据；meta.available_metrics[]：可选指标。

| 参数 | 位置 | 约束 | 说明 |
| --- | --- | --- | --- |
| `granularity` | path | string · 必填 · daily / weekly / monthly | 序列聚合粒度。 |
| `metrics` | query | string · 可选 | 逗号分隔的数值指标；未指定或全部不匹配时使用全部可用指标。 |
| `limit` | query | integer · 可选 · 1–1000 | 只取最后 N 个点；省略时不截断，不是日历天数。 |

```sh
curl -fsS 'https://YOUR_HOST/api/public/v1/me/series/daily?metrics=sleep_hours,steps,hrv&limit=30'
```

### SVG 趋势图

`GET /api/public/v1/me/charts/{chart_key}.svg`

返回可嵌入的 SVG；各指标独立归一化。缺少数据时仍返回带空状态文字的 SVG。

返回：`image/svg+xml`；SVG 文本；X-Fitflare-Chart-Meta 响应头包含图表元数据。

| 参数 | 位置 | 约束 | 说明 |
| --- | --- | --- | --- |
| `chart_key` | path | string · 必填 · series / overview-trend / weekly-trend / sleep-trend / activity-trend | 预置或自定义趋势图。 |
| `metrics` | query | string · 可选 | 逗号分隔的数值指标；未指定或全部不匹配时使用全部可用指标。 |
| `granularity` | query | string · 可选 · daily / weekly / monthly | 覆盖预置图粒度；省略时使用该预置图粒度。 |
| `limit` | query | integer · 可选 · 1–1000 | 只取最后 N 个点；省略时不截断，不是日历天数。 |
| `width` | query | integer · 可选 · 默认 960 · 360–1920 | SVG 宽度，单位 px。 |
| `height` | query | integer · 可选 · 默认 320 · 220–1080 | SVG 高度，单位 px。 |
| `theme` | query | string · 可选 · 默认 light · light / transparent | light 为浅色；transparent 为透明背景；其他值按浅色呈现。 |

```sh
curl -fsS 'https://YOUR_HOST/api/public/v1/me/charts/series.svg?metrics=sleep_hours,steps,hrv&granularity=daily&limit=30&width=960&height=320&theme=light'
```

## 数据集与表格

### 数据集目录

`GET /api/public/v1/me/datasets`

列出支持的完整结构化数据集和覆盖信息。

返回：`application/json`；data 对象。

```sh
curl -fsS 'https://YOUR_HOST/api/public/v1/me/datasets'
```

### 读取数据集

`GET /api/public/v1/me/datasets/{dataset}`

读取由 CSV 解析或聚合的完整历史，并从 offset 起分页。

返回：`application/json`；data.rows[]：当前页；data.columns[]：列名提示；meta：分页信息。

| 参数 | 位置 | 约束 | 说明 |
| --- | --- | --- | --- |
| `dataset` | path | string · 必填 · activity / sleep / hrv / rhr / daily / weekly / monthly | 完整本地数据集。 |
| `offset` | query | integer · 可选 · 默认 0 · 0–100000 | 从第 offset 条开始分页，按缓存记录顺序返回。 |
| `limit` | query | integer · 可选 · 默认 200 · 1–1000 | 从 offset 起最多返回的条数，默认 200。 |

```sh
curl -fsS 'https://YOUR_HOST/api/public/v1/me/datasets/activity?offset=0&limit=20'
```

### 摘要分区列表

`GET /api/public/v1/me/sections`

读取 activity、body、vitals、lifestyle、account 摘要。

返回：`application/json`；data 对象。

```sh
curl -fsS 'https://YOUR_HOST/api/public/v1/me/sections'
```

### 单个摘要分区

`GET /api/public/v1/me/sections/{section_key}`

返回指定分区的指标摘要。

返回：`application/json`；data.key（与 data.section 相同）、data.label、data.summary。

| 参数 | 位置 | 约束 | 说明 |
| --- | --- | --- | --- |
| `section_key` | path | string · 必填 · activity / body / vitals / lifestyle / account | 摘要分区。 |

```sh
curl -fsS 'https://YOUR_HOST/api/public/v1/me/sections/activity'
```

### 记录表目录

`GET /api/public/v1/me/tables`

返回仪表盘记录表的 key、条数和链接。

返回：`application/json`；data 对象。

```sh
curl -fsS 'https://YOUR_HOST/api/public/v1/me/tables'
```

### 读取记录表

`GET /api/public/v1/me/tables/{table_key}`

对仪表盘缓存中已有的记录分页；缓存可能只保留最近记录，与完整 datasets 不同。

返回：`application/json`；data.rows[]：当前页；meta.total、offset、limit、count：分页信息。

| 参数 | 位置 | 约束 | 说明 |
| --- | --- | --- | --- |
| `table_key` | path | string · 必填 · sleep / activity / activity_logs / recovery / body / vitals / foods / devices / badges / alarms / endpoints | 仪表盘缓存中的记录表。 |
| `offset` | query | integer · 可选 · 默认 0 · 0–100000 | 从第 offset 条开始分页，按缓存记录顺序返回。 |
| `limit` | query | integer · 可选 · 默认 100 · 1–1000 | 从 offset 起最多返回的条数，默认 100。 |

```sh
curl -fsS 'https://YOUR_HOST/api/public/v1/me/tables/sleep?offset=0&limit=20'
```

## 快照与接口状态

### 快照状态

`GET /api/public/v1/me/snapshot-status`

权限范围、缓存时间和接口抓取概况。

返回：`application/json`；data 对象。

```sh
curl -fsS 'https://YOUR_HOST/api/public/v1/me/snapshot-status'
```

### 完整快照

`GET /api/public/v1/me/snapshot`

返回选定元数据及各端点的原始 data。仍可能包含个人资料，不是匿名化结果。

返回：`application/json`；data 对象。

```sh
curl -fsS 'https://YOUR_HOST/api/public/v1/me/snapshot'
```

### 快照端点目录

`GET /api/public/v1/me/snapshot/endpoints`

端点 key、状态、scope、更新时间与链接。

返回：`application/json`；data 对象。

```sh
curl -fsS 'https://YOUR_HOST/api/public/v1/me/snapshot/endpoints'
```

### 单个快照端点

`GET /api/public/v1/me/snapshot/endpoints/{endpoint_key}`

指定端点的状态和上游缓存 data；先通过端点目录确认 key。

返回：`application/json`；data 对象。

| 参数 | 位置 | 约束 | 说明 |
| --- | --- | --- | --- |
| `endpoint_key` | path | string · 必填 | 从 /snapshot/endpoints 获取已缓存端点 key。 |

```sh
curl -fsS 'https://YOUR_HOST/api/public/v1/me/snapshot/endpoints/profile'
```

## 文档入口

### HTML 文档

`GET /api/public/v1/docs`

当前文档页面；无需数据访问权限。

返回：`text/html`；HTML 页面。

```sh
curl -fsS 'https://YOUR_HOST/api/public/v1/docs'
```

### Markdown 文档

`GET /api/public/v1/docs.md`

由同一接口目录生成的纯文本版本；无需数据访问权限。

返回：`text/markdown`；Markdown 文本。

```sh
curl -fsS 'https://YOUR_HOST/api/public/v1/docs.md'
```

### OpenAPI 3.1

`GET /api/public/v1/openapi.json`

完整版本化接口描述，包含参数、响应结构和当前部署的认证模式。

返回：`application/json`；OpenAPI 规范对象，不是业务响应包装。

```sh
curl -fsS 'https://YOUR_HOST/api/public/v1/openapi.json'
```
