19 KiB
Client API 前端联调文档
文档版本:v1.0.0 最后更新:2026-03-31 状态:联调中
1. 文档说明
本文档面向前端联调,描述当前 client-api 在代码中真实可用的接口。
约定:
- 本文档优先级高于产品阶段的总草案;前端联调以本文档为准
- 本文档只覆盖
client-api - 每个接口会标记当前状态:
已实现,已联调已实现,未联调预留未就绪
2. 通用约定
2.1 Base Path
client-api:/client/v1
2.2 成功响应
{
"request_id": "req_xxx",
"data": {}
}
2.3 失败响应
{
"request_id": "req_xxx",
"error": {
"code": "invalid_request",
"message": "xxx",
"details": {}
}
}
2.4 鉴权说明
- 登录后接口使用:
Authorization: Bearer {access_token} launch成功后会返回session_token- 但当前版本下游
session相关接口尚未开放,因此前端暂时只需要保存session_token
2.5 枚举说明
client_type
appwechat
body_profile_status
pendingcompleted
3. 已实现接口
3.1 POST /client/v1/auth/sms/send
状态:已实现,已联调
接口介绍:
- 发送短信验证码
- 当前已接阿里云短信
请求参数:
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
scene |
string |
是 | 当前已使用 client_login |
country_code |
string |
是 | 国家码,如 86 |
mobile |
string |
是 | 手机号 |
client_type |
string |
是 | app / wechat |
device_id |
string |
是 | 设备唯一标识 |
请求示例:
{
"scene": "client_login",
"country_code": "86",
"mobile": "15168870729",
"client_type": "app",
"device_id": "dev_iphone_001"
}
返回参数:
| 字段 | 类型 | 说明 |
|---|---|---|
cooldown_sec |
int |
重发冷却时间 |
expires_in_sec |
int |
验证码有效期 |
3.2 POST /client/v1/auth/login/sms
状态:已实现,已联调
接口介绍:
- 短信登录
- 如果手机号首次登录,后端会自动创建:
userslogin_identities- 默认
user_body_profiles - 首条
user_body_profile_versions
请求参数:
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
login_request_id |
string |
是 | 登录幂等号 |
country_code |
string |
是 | 国家码 |
mobile |
string |
是 | 手机号 |
sms_code |
string |
是 | 短信验证码 |
client_type |
string |
是 | app / wechat |
device_id |
string |
是 | 设备唯一标识 |
返回参数:
| 字段 | 类型 | 说明 |
|---|---|---|
user_id |
string |
用户公开 ID |
access_token |
string |
登录态 token |
refresh_token |
string |
refresh token |
login_method |
string |
当前为 sms |
body_profile_status |
string |
pending / completed |
expires_in_sec |
int |
access_token 有效期 |
3.3 POST /client/v1/auth/login/wechat
状态:已实现,未联调
接口介绍:
- 微信登录入口已预留
- 当前仓库里 provider 仍以 mock 为主,尚未做真实联调
请求参数:
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
login_request_id |
string |
是 | 登录幂等号 |
wechat_login_code |
string |
是 | 微信登录 code |
client_type |
string |
是 | 建议传 wechat |
device_id |
string |
是 | 设备唯一标识 |
返回参数:
| 字段 | 类型 | 说明 |
|---|---|---|
user_id |
string |
用户公开 ID |
access_token |
string |
登录态 token |
refresh_token |
string |
refresh token |
login_method |
string |
当前为 wechat |
body_profile_status |
string |
pending / completed |
expires_in_sec |
int |
access_token 有效期 |
3.4 POST /client/v1/auth/refresh
状态:已实现,已联调
接口介绍:
- 使用 refresh token 刷新
access_token
请求参数:
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
refresh_token |
string |
是 | refresh token |
client_type |
string |
是 | app / wechat |
返回参数:
| 字段 | 类型 | 说明 |
|---|---|---|
access_token |
string |
新的登录态 token |
expires_in_sec |
int |
有效期 |
3.5 PUT /client/v1/me/body-profile
状态:已实现,未联调
接口介绍:
- 更新身体数据
- 成功后会更新当前档案,并追加历史版本
认证:
- 需要
access_token
请求参数:
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
gender |
string |
否 | male / female / other / unknown |
birth_date |
string |
否 | YYYY-MM-DD |
height_cm |
number |
否 | 身高,厘米 |
weight_kg |
number |
否 | 体重,千克 |
resting_heart_rate_bpm |
int |
否 | 静息心率 |
max_heart_rate_bpm |
int |
否 | 最大心率 |
返回参数:
| 字段 | 类型 | 说明 |
|---|---|---|
user_id |
string |
用户公开 ID |
body_profile_status |
string |
pending / completed |
completed_at |
string |
首次补全时间,未补全时可能为空 |
3.6 GET /client/v1/cards
状态:已实现,已联调
接口介绍:
- 首页卡片列表
查询参数:
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
region_code |
string |
否 | 地区编码,当前可空 |
返回参数:
data.items[]
| 字段 | 类型 | 说明 |
|---|---|---|
card_id |
string |
卡片公开 ID |
card_type |
string |
例如 competition_card |
display_name |
string |
卡片展示名称 |
competition_id |
string |
关联赛事 ID,非赛事卡可能为空 |
html_url |
string |
H5 地址,可空 |
cover_url |
string |
封面地址,可空 |
display_slot |
string |
展示槽位 |
display_priority |
int |
展示优先级 |
3.7 GET /client/v1/competitions/{competition_id}
状态:已实现,已联调
接口介绍:
- 赛事详情页
- 如果带
access_token,会返回当前用户的registration_status
认证:
- 可匿名访问
- 建议前端在登录后带上
access_token
Path 参数:
| 字段 | 类型 | 说明 |
|---|---|---|
competition_id |
string |
赛事公开 ID |
返回参数:
| 字段 | 类型 | 说明 |
|---|---|---|
competition_id |
string |
赛事公开 ID |
display_name |
string |
赛事名称 |
competition_status |
string |
当前状态 |
registration_enabled |
bool |
是否允许报名 |
registration_status |
string |
当前用户报名状态,匿名访问时可能为空 |
competition_start_at |
string |
赛事开始时间 |
competition_end_at |
string |
赛事结束时间 |
leaderboard_enabled |
bool |
是否展示排行榜 |
realtime_board_enabled |
bool |
是否启用实时榜 |
data.events[]
| 字段 | 类型 | 说明 |
|---|---|---|
event_id |
string |
Event 公开 ID |
display_name |
string |
Event 名称 |
is_default |
bool |
是否默认 Event |
current_release_id |
string |
当前发布版 ID |
manifest_url |
string |
manifest 下载地址 |
manifest_checksum_sha256 |
string |
manifest 校验值 |
relation_status |
string |
关联状态 |
3.8 GET /client/v1/competitions/{competition_id}/events/{event_id}
状态:已实现,已联调
接口介绍:
- 赛事上下文下的 Event 详情
- 前端应在这个页面预加载 manifest,并完成路线预览
认证:
- 可匿名访问
- 建议前端在登录后带上
access_token
Path 参数:
| 字段 | 类型 | 说明 |
|---|---|---|
competition_id |
string |
赛事公开 ID |
event_id |
string |
Event 公开 ID |
返回参数:
| 字段 | 类型 | 说明 |
|---|---|---|
competition_id |
string |
赛事公开 ID |
event_id |
string |
Event 公开 ID |
display_name |
string |
Event 名称 |
current_release_id |
string |
当前发布版 ID |
manifest_url |
string |
manifest 下载地址 |
manifest_checksum_sha256 |
string |
manifest 校验值 |
direct_entry_enabled |
bool |
是否支持地图直入 |
playfield_version_id |
string |
场地版本 ID |
playfield_kind |
string |
如 course |
data.competition_context
| 字段 | 类型 | 说明 |
|---|---|---|
competition_id |
string |
赛事公开 ID |
display_name |
string |
赛事名称 |
competition_status |
string |
赛事状态 |
registration_status |
string |
当前用户报名状态 |
leaderboard_enabled |
bool |
是否显示排行榜 |
realtime_board_enabled |
bool |
是否启用实时榜 |
data.map_summary
| 字段 | 类型 | 说明 |
|---|---|---|
map_id |
string |
地图公开 ID |
display_name |
string |
地图名称 |
cover_url |
string |
封面图,可空 |
scale_text |
string |
比例尺,可空 |
data.preview_summary
| 字段 | 类型 | 说明 |
|---|---|---|
control_count |
int |
控制点数量 |
route_count |
int |
路线数量 |
playfield_kind |
string |
场地类型 |
3.9 POST /client/v1/competitions/{competition_id}/registrations
状态:已实现,未联调
接口介绍:
- 赛事报名
认证:
- 需要
access_token
Path 参数:
| 字段 | 类型 | 说明 |
|---|---|---|
competition_id |
string |
赛事公开 ID |
请求参数:
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
group_id |
string |
否 | 队伍或分组 ID |
form_payload |
object |
否 | 附加报名表单 |
返回参数:
| 字段 | 类型 | 说明 |
|---|---|---|
registration_id |
string |
报名记录 ID |
status |
string |
当前报名状态 |
3.10 GET /client/v1/maps
状态:已实现,已联调
接口介绍:
- 地图列表页
查询参数:
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
region_code |
string |
否 | 地区编码 |
page |
int |
否 | 默认 1 |
page_size |
int |
否 | 默认 20,最大 50 |
返回参数:
data.items[]
| 字段 | 类型 | 说明 |
|---|---|---|
map_id |
string |
地图公开 ID |
display_name |
string |
地图名称 |
cover_url |
string |
封面图,可空 |
scale_text |
string |
比例尺,可空 |
distance_from_user_km |
number |
距离,可空 |
说明:
- 当前响应只返回
items,不回显page/page_size/total
3.11 GET /client/v1/maps/{map_id}
状态:已实现,已联调
接口介绍:
- 地图详情页
- 同时返回当前地图下允许直入的 Event 列表
Path 参数:
| 字段 | 类型 | 说明 |
|---|---|---|
map_id |
string |
地图公开 ID |
返回参数:
| 字段 | 类型 | 说明 |
|---|---|---|
map_id |
string |
地图公开 ID |
display_name |
string |
地图名称 |
data.map_summary
| 字段 | 类型 | 说明 |
|---|---|---|
cover_url |
string |
封面图,可空 |
scale_text |
string |
比例尺,可空 |
updated_date |
string |
更新时间,可空 |
data.events[]
| 字段 | 类型 | 说明 |
|---|---|---|
event_id |
string |
Event 公开 ID |
display_name |
string |
Event 名称 |
preview_image_url |
string |
预览图,可空 |
control_count |
int |
控制点数量 |
route_count |
int |
路线数量 |
direct_entry_enabled |
bool |
是否允许地图直入 |
current_release_id |
string |
当前发布版 ID |
manifest_url |
string |
manifest 下载地址 |
manifest_checksum_sha256 |
string |
manifest 校验值 |
playfield_kind |
string |
如 course |
3.12 GET /client/v1/events
状态:已实现,已联调
接口介绍:
- 地图直入链路下的 Event 列表
查询参数:
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
map_id |
string |
否 | 按地图筛选 |
page |
int |
否 | 默认 1 |
page_size |
int |
否 | 默认 20,最大 50 |
返回参数:
data.items[]
| 字段 | 类型 | 说明 |
|---|---|---|
event_id |
string |
Event 公开 ID |
display_name |
string |
Event 名称 |
map_id |
string |
地图公开 ID |
map_display_name |
string |
地图名称 |
preview_image_url |
string |
预览图,可空 |
control_count |
int |
控制点数量 |
route_count |
int |
路线数量 |
direct_entry_enabled |
bool |
是否允许地图直入 |
current_release_id |
string |
当前发布版 ID |
manifest_url |
string |
manifest 下载地址 |
manifest_checksum_sha256 |
string |
manifest 校验值 |
playfield_kind |
string |
如 course |
说明:
- 当前响应只返回
items,不回显page/page_size/total
3.13 GET /client/v1/events/{event_id}
状态:已实现,已联调
接口介绍:
- 地图直入上下文下的 Event 详情
- 与赛事入口页共用同一套 Event 详情视图
Path 参数:
| 字段 | 类型 | 说明 |
|---|---|---|
event_id |
string |
Event 公开 ID |
返回参数:
| 字段 | 类型 | 说明 |
|---|---|---|
event_id |
string |
Event 公开 ID |
display_name |
string |
Event 名称 |
direct_entry_enabled |
bool |
是否允许地图直入 |
current_release_id |
string |
当前发布版 ID |
manifest_url |
string |
manifest 下载地址 |
manifest_checksum_sha256 |
string |
manifest 校验值 |
playfield_version_id |
string |
场地版本 ID |
playfield_kind |
string |
如 course |
data.map_summary
| 字段 | 类型 | 说明 |
|---|---|---|
map_id |
string |
地图公开 ID |
display_name |
string |
地图名称 |
cover_url |
string |
封面图,可空 |
scale_text |
string |
比例尺,可空 |
data.event_summary
| 字段 | 类型 | 说明 |
|---|---|---|
control_count |
int |
控制点数量 |
route_count |
int |
路线数量 |
playfield_kind |
string |
场地类型 |
3.14 POST /client/v1/competitions/{competition_id}/events/{event_id}/launch
状态:已实现,已联调
接口介绍:
- 赛事入口
launch - 会校验赛事时间窗、报名状态、
release_id - 成功后创建 session,并返回
session_token
认证:
- 需要
access_token
Path 参数:
| 字段 | 类型 | 说明 |
|---|---|---|
competition_id |
string |
赛事公开 ID |
event_id |
string |
Event 公开 ID |
请求参数:
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
launch_request_id |
string |
是 | 启动幂等号 |
device_id |
string |
是 | 设备唯一标识 |
client_type |
string |
是 | 必须与 access_token 内声明一致 |
release_id |
string |
是 | 前端当前持有的发布版 ID |
route_code |
string |
否 | 当前选中的路线编码 |
返回参数:
| 字段 | 类型 | 说明 |
|---|---|---|
session_id |
string |
会话 ID |
session_token |
string |
会话 token |
session_token_expires_at |
string |
会话 token 过期时间 |
participant_id |
string |
参赛身份 ID |
competition_id |
string |
赛事公开 ID |
event_id |
string |
Event 公开 ID |
event_release_id |
string |
实际冻结的发布版 ID |
playfield_version_id |
string |
场地版本 ID |
route_code |
string |
当前冻结的路线编码 |
realtime_endpoint |
string |
realtime-center 地址 |
realtime_token |
string |
当前版本通常为空 |
当前注意:
- 若前端传入的
release_id已过期,会返回EVENT_RELEASE_STALE - 当前后端会冻结并回传
route_code,但还没有对 manifest 内路线做严格校验
3.15 POST /client/v1/events/{event_id}/launch
状态:已实现,已联调
接口介绍:
- 地图直入
launch - 不校验赛事报名资格
- 成功后创建 session,并返回
session_token
认证:
- 需要
access_token
Path 参数:
| 字段 | 类型 | 说明 |
|---|---|---|
event_id |
string |
Event 公开 ID |
请求参数:
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
launch_request_id |
string |
是 | 启动幂等号 |
device_id |
string |
是 | 设备唯一标识 |
client_type |
string |
是 | 必须与 access_token 内声明一致 |
release_id |
string |
是 | 前端当前持有的发布版 ID |
route_code |
string |
否 | 当前选中的路线编码 |
返回参数:
| 字段 | 类型 | 说明 |
|---|---|---|
session_id |
string |
会话 ID |
session_token |
string |
会话 token |
session_token_expires_at |
string |
会话 token 过期时间 |
participant_id |
string |
参赛身份 ID |
event_id |
string |
Event 公开 ID |
event_release_id |
string |
实际冻结的发布版 ID |
playfield_version_id |
string |
场地版本 ID |
route_code |
string |
当前冻结的路线编码 |
realtime_endpoint |
string |
realtime-center 地址 |
realtime_token |
string |
当前版本通常为空 |
当前注意:
- 若前端传入的
release_id已过期,会返回EVENT_RELEASE_STALE - 当前后端会冻结并回传
route_code,但还没有对 manifest 内路线做严格校验
4. 预留未就绪接口
以下接口当前在路由中已占位,但实际会直接返回 not implemented:
| 接口 | 当前错误码 |
|---|---|
POST /client/v1/session-uploads |
session_upload_not_ready |
POST /client/v1/punches |
session_punch_not_ready |
POST /client/v1/sessions/{session_id}/finish |
session_finish_not_ready |
GET /client/v1/sessions/{session_id}/result |
session_result_not_ready |
GET /client/v1/sessions/{session_id}/replay-summary |
session_replay_summary_not_ready |
GET /client/v1/sessions/{session_id}/gps-track |
session_gps_track_not_ready |
GET /client/v1/sessions/{session_id}/heart-rate |
session_heart_rate_not_ready |
GET /client/v1/me/sessions |
session_history_not_ready |
说明:
- 所以当前不是“只有 GPS / 心率上报没测”
- 而是整条
session下游链路都还没开放 - 当前已实测闭环停在
launch成功返回session_token
5. 当前测试数据
以下数据可直接用于本地联调:
| 类型 | ID |
|---|---|
card_id |
crd_classic_demo_001 |
competition_id |
cmp_classic_demo_001 |
map_id |
lxcb-001 |
event_id |
sample-classic-001 |
release_id |
sample-classic-001-rel-1 |
route_code |
classic-001 |
说明:
- 已存在测试赛事卡片、地图、Event、manifest 绑定关系
- 已存在一个已批准报名的测试用户,可直接验证赛事入口
launch