用户数据互通 API
用户数据互通(Channel User)是开放平台面向合作方 B 端系统的服务对服务接口(S2S)。 合作方通过此组接口将自身用户、家庭组、家庭成员数据写入晓葆平台,实现健康档案、 权益卡、AI 解读等能力与合作方用户体系的双向打通。
概述
接口路径前缀:/open/v1/channel/users
| 方法 | 路径 | 说明 |
|---|---|---|
| POST | /open/v1/channel/users | 一步注册绑定(用户 + 家庭组 + 成员) |
| GET | /open/v1/channel/users/{openUserId} | 全量用户快照 |
| PATCH | /open/v1/channel/users/{openUserId} | 更新用户基础信息 |
| POST | /open/v1/channel/users/{openUserId}/family-groups | 新增或更新家庭组 |
| DELETE | /open/v1/channel/users/{openUserId}/family-groups/{groupId} | 解散家庭组 |
| POST | /open/v1/channel/users/{openUserId}/family-members | 新增或更新家庭成员 |
| DELETE | /open/v1/channel/users/{openUserId}/family-members/{memberId} | 删除家庭成员 |
鉴权说明
所有接口均为 B 端 S2S 调用,需在 HTTP Header 中携带以下三个字段:
| Header | 类型 | 必填 | 说明 |
|---|---|---|---|
X-App-Id | string | 是 | 控制台「凭证管理」中的 App ID |
X-Timestamp | integer | 是 | Unix 秒级时间戳,有效窗口 ±5 分钟 |
X-Signature | string | 是 | md5(api_key + timestamp + api_secret + request_body) |
一步注册绑定
将合作方 App 用户、家庭组(多组)、家庭成员一次性绑定到开放平台。
- 幂等键:
(app_id, channel_user_id),重复调用返回已有映射,不产生重复用户。 family_groups和family_members均为可选,仅传user时为纯建档。family_members[].app_group_id必须存在于本次family_groups列表中。
请求体(application/json):
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
channel_user_id | string | 是 | 合作方系统内的用户唯一标识(最长 100 字符) |
user | object | 是 | 用户基础信息,见下表 |
family_groups | array | 否 | 家庭组列表,见下表 |
family_members | array | 否 | 家庭成员列表,见下表 |
user 对象:
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
name | string | 是 | 姓名,最长 32 字符 |
phone | string | 否 | 手机号(大陆 11 位) |
gender | string | 否 | male / female / unknown |
birth_date | string | 否 | 出生日期,格式 Y-m-d,须早于今日 |
nickname | string | 否 | 昵称,最长 32 字符 |
avatar | string | 否 | 头像 URL,最长 500 字符 |
email | string | 否 | 邮箱地址 |
family_groups 单项:
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
app_group_id | integer | 是 | 合作方侧家庭组 ID(幂等键) |
name | string | 是 | 家庭组名称,最长 64 字符 |
family_members 单项:
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
app_user_id | string | 是 | 合作方侧成员唯一标识(幂等键,最长 32 字符) |
app_group_id | integer | 是 | 归属家庭组(对应本次 family_groups 中的 app_group_id) |
name | string | 是 | 姓名,最长 32 字符 |
relationship | string | 是 | 与主账号关系,见关系枚举表 |
gender | string | 否 | male / female / unknown |
birth_date | string | 否 | Y-m-d |
phone | string | 否 | 手机号,最长 16 字符 |
id_type | string | 否 | 证件类型,最长 20 字符 |
id_number | string | 否 | 证件号,最长 32 字符 |
height | integer | 否 | 身高(cm),范围 30–300 |
weight | integer | 否 | 体重(kg×100),范围 100–50000(如 6000 = 60.00 kg) |
blood_type | string | 否 | A / B / AB / O / unknown |
is_default | boolean | 否 | 是否设为默认咨询人 |
请求示例:
POST /open/v1/channel/users
X-App-Id: 100023
X-Timestamp: 1743494400
X-Signature: d41d8cd98f00b204e9800998ecf8427e
{
"channel_user_id": "partner_u_8801",
"user": {
"name": "张三",
"phone": "13800138000",
"gender": "male",
"birth_date": "1985-06-15"
},
"family_groups": [
{ "app_group_id": 501, "name": "张三家庭" }
],
"family_members": [
{
"app_user_id": "partner_m_1001",
"app_group_id": 501,
"name": "张三",
"relationship": "SELF",
"gender": "male",
"birth_date": "1985-06-15",
"is_default": true
}
]
}成功响应(首次注册 201 Created,幂等命中 200 OK):
{
"success": true,
"code": 0,
"message": "绑定成功",
"data": {
"open_user_id": 10086, // 开放平台用户ID,请持久化存储
"channel_user_id": "partner_u_8801",
"created": true, // false 表示幂等命中已有记录
"family_groups": [
{ "family_group_id": 2001, "app_group_id": 501 }
],
"family_members": [
{ "member_id": 3001, "app_user_id": "partner_m_1001" }
]
},
"timestamp": "2026-04-01T10:00:00+08:00"
}open_user_id、family_group_id、member_id 持久化存储到合作方系统,后续所有接口均以这些 ID 作为路径参数。全量用户快照
返回指定用户的基础信息、全部有效家庭组及家庭成员的完整快照。 App 侧收到用户互通类 Webhook 后,调用此接口对齐本地数据。
路径参数:
| 参数 | 类型 | 说明 |
|---|---|---|
openUserId | integer | 开放平台用户 ID(注册绑定时返回的 open_user_id) |
查询参数(可选):
| 参数 | 类型 | 说明 |
|---|---|---|
updated_after | string | ISO8601 时间,仅过滤返回 family_members 的增量集合,user 和 family_groups 始终全量返回 |
channel_user_id | string | 尚未落库 open_user_id 时的兜底查询,两个参数任传其一即可 |
成功响应(200 OK):
{
"success": true,
"code": 0,
"message": "获取成功",
"data": {
"user": {
"open_user_id": 10086,
"name": "张三",
"nickname": null,
"gender": "male",
"avatar": null,
"phone": "138****8000", // 脱敏:前3后4
"email": null,
"birth_date": "1985-06-15",
"status": "ACTIVE",
"registered_at": "2026-04-01 10:00:00"
},
"family_groups": [
{
"family_group_id": 2001,
"app_group_id": 501,
"name": "张三家庭",
"member_count": 1
}
],
"family_members": [
{
"member_id": 3001,
"app_user_id": "partner_m_1001",
"app_group_id": 501,
"family_group_id": 2001,
"name": "张三",
"relationship": "SELF",
"gender": "male",
"birth_date": "1985-06-15",
"phone": null,
"id_type": null,
"height": null,
"weight": null,
"blood_type": null,
"is_default": true,
"updated_at": "2026-04-01 10:00:00"
}
]
},
"timestamp": "2026-04-01T10:00:00+08:00"
}更新用户基础信息
PATCH 语义:只传需要变更的字段,未传字段保持不变。 成功后触发 Webhook:user.profile.updated。
请求体(所有字段均为可选):
| 字段 | 类型 | 说明 |
|---|---|---|
name | string | 姓名,最长 32 字符 |
nickname | string | 昵称,最长 32 字符,传 null 可清空 |
gender | string | male / female / unknown |
avatar | string | 头像 URL,最长 500 字符 |
phone | string | 手机号(大陆 11 位) |
email | string | 邮箱地址 |
birth_date | string | 出生日期,格式 Y-m-d |
成功响应(200 OK):
{ "success": true, "code": 0, "message": "更新成功", "timestamp": "..." }新增或更新家庭组
以 app_group_id 为幂等键 upsert。相同 app_group_id 重复提交只更新 name,不产生重复记录。 成功后触发 Webhook:user.family_group.created(含更新语义)。
请求体:
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
app_group_id | integer | 是 | 合作方侧家庭组 ID(幂等键) |
name | string | 是 | 家庭组名称,最长 64 字符 |
成功响应(新建 201,更新 200):
{
"success": true,
"code": 0,
"message": "家庭组创建成功",
"data": {
"family_group_id": 2001,
"app_group_id": 501,
"name": "张三家庭",
"created": true // false 表示已存在并更新
},
"timestamp": "..."
}解散家庭组
软标记家庭组为已解散(status=0),并级联软删除组内所有家庭成员。 成功后触发 Webhook:user.family_group.deleted。
路径参数:
| 参数 | 类型 | 说明 |
|---|---|---|
openUserId | integer | 开放平台用户 ID |
groupId | integer | 开放平台家庭组 ID(注册绑定时返回的 family_group_id) |
成功响应(200 OK):
{ "success": true, "code": 0, "message": "家庭组已解散", "timestamp": "..." }新增或更新家庭成员
以 app_user_id 为幂等键 upsert。通过 app_group_id 指定归属家庭组(开放平台自动解析为 family_group_id)。 成功后触发 Webhook:user.family_member.created 或 user.family_member.updated。
请求体:
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
app_user_id | string | 是 | 合作方侧成员唯一标识(幂等键,最长 32 字符) |
app_group_id | integer | 是 | 归属家庭组(合作方侧 app_group_id,须已存在且未解散) |
name | string | 是 | 姓名,最长 32 字符 |
relationship | string | 是 | 关系枚举,见下方说明 |
gender | string | 否 | male / female / unknown |
birth_date | string | 否 | Y-m-d |
phone | string | 否 | 手机号,最长 16 字符 |
height | integer | 否 | 身高(cm),范围 30–300 |
weight | integer | 否 | 体重(kg×100),范围 100–50000 |
blood_type | string | 否 | A / B / AB / O / unknown |
is_default | boolean | 否 | 是否设为默认咨询人 |
relationship 枚举(常用值):
| 值 | 含义 | 值 | 含义 |
|---|---|---|---|
SELF | 本人 | SPOUSE | 配偶 |
FATHER | 父亲 | MOTHER | 母亲 |
SON | 儿子 | DAUGHTER | 女儿 |
GRANDFATHER | 祖父 | GRANDMOTHER | 祖母 |
BROTHER | 兄弟 | SISTER | 姐妹 |
OTHER | 其他 |
成功响应(新建 201,更新 200):
{
"success": true,
"code": 0,
"message": "家庭成员添加成功",
"data": {
"member_id": 3001, // 开放平台成员ID,请持久化存储
"app_user_id": "partner_m_1001",
"created": true
},
"timestamp": "..."
}删除家庭成员
软删除家庭成员(写入 deleted_at),不物理删除数据。 成功后触发 Webhook:user.family_member.deleted。
路径参数:
| 参数 | 类型 | 说明 |
|---|---|---|
openUserId | integer | 开放平台用户 ID |
memberId | integer | 开放平台成员 ID(注册或 upsert 时返回的 member_id) |
成功响应(200 OK):
{ "success": true, "code": 0, "message": "家庭成员已删除", "timestamp": "..." }Webhook 事件
所有写入操作成功后,平台会向应用配置的 Webhook URL 推送事件通知(异步):
| 触发接口 | 事件名 | 说明 |
|---|---|---|
| 更新用户信息(PATCH) | user.profile.updated | 用户基础信息变更,建议拉取快照对齐 |
| 新增/更新家庭组 | user.family_group.created | 包含新建与更新两种场景 |
| 解散家庭组 | user.family_group.deleted | 组内成员已级联软删 |
| 新增家庭成员 | user.family_member.created | |
| 更新家庭成员 | user.family_member.updated | |
| 删除家庭成员 | user.family_member.deleted |
错误码
| code | HTTP 状态 | 说明 | 处理建议 |
|---|---|---|---|
USER_NOT_FOUND | 404 | open_user_id 不存在或不属于当前应用 | 确认 open_user_id 是否正确 |
FAMILY_GROUP_NOT_FOUND | 404 | 家庭组不存在、已解散或无权操作 | 确认 groupId / app_group_id 是否正确 |
FAMILY_MEMBER_NOT_FOUND | 404 | 家庭成员不存在或已删除 | 确认 memberId 是否正确 |
INVALID_APP_GROUP_ID | 422 | 一步注册时 family_members 引用了不在本次 family_groups 中的 app_group_id | 检查 family_members[].app_group_id 是否都在 family_groups 列表内 |
VALIDATION_ERROR | 422 | 请求体字段格式不合法 | 查看 errors 字段中的具体字段名和错误描述 |
HTTP_401 | 401 | 签名校验失败或 App-Id 不存在 | 检查签名算法和时间戳有效性 |
HTTP_429 | 429 | 请求频率超过限制 | 降低请求速率,实现指数退避重试 |