> ## Documentation Index
> Fetch the complete documentation index at: https://docs.waffo.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# 更新收件人

> 修改收件人订阅的商户通知事件

更新收件人的事件订阅。更新是**部分更新**：只需提交本次要改动的开关，未提交的键保持原值。响应恒返回合并后的完整对象。

<Note>
  门店没有显式收件人时，列表里那条兜底条目（`isPrimary: true`，owner 账号邮箱）的 `id` 是形如 `OWNER_<storeId>` 的哨兵值。把它传到本端点会**就地物化**：账号邮箱变成一条真实收件人，你的 patch 叠加在门店级 `notify*` 之上，响应返回真实 UUID。兜底条目随之消失。
</Note>

```
POST /v1/actions/store-notification-recipient/update-recipient
```

**认证方式：** API Key（需 owner 或 admin 角色）

## 请求体

| 字段            | 类型     | 必填 | 说明                                                                               |
| ------------- | ------ | -- | -------------------------------------------------------------------------------- |
| `storeId`     | string | 是  | 门店 ID（Short ID 格式 `STO_xxx`）                                                     |
| `recipientId` | string | 是  | 原样回传 `add-recipient` 或 GraphQL 查询返回的值 —— 真实收件人是 UUID，兜底条目是 `OWNER_<storeId>` 哨兵值 |
| `preferences` | object | 是  | 本次要改动的开关。只接受事件目录内的 9 个键，其余键返回 400。                                               |

## 请求示例

<CodeGroup>
  ```bash cURL theme={"system"}
  curl -X POST https://api.waffo.com/v1/actions/store-notification-recipient/update-recipient \
    -H "Content-Type: application/json" \
    -H "X-Merchant-Id: $WAFFO_MERCHANT_ID" \
    -H "X-Signature: ..." \
    -d '{
      "storeId": "STO_2aUyqjCzEIiEcYMKj7TZtw",
      "recipientId": "11111111-2222-3333-4444-555555555555",
      "preferences": { "notifyNewOrders": false }
    }'
  ```

  ```javascript JavaScript theme={"system"}
  const response = await fetch(
    "https://api.waffo.com/v1/actions/store-notification-recipient/update-recipient",
    {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
        "X-Merchant-Id": process.env.WAFFO_MERCHANT_ID,
        "X-Signature": signature,
      },
      body: JSON.stringify({
        storeId: "STO_2aUyqjCzEIiEcYMKj7TZtw",
        recipientId: "11111111-2222-3333-4444-555555555555",
        preferences: { notifyNewOrders: false },
      }),
    },
  );

  const { data } = await response.json();
  ```
</CodeGroup>

## 成功响应 (200)

```json theme={"system"}
{
  "data": {
    "recipient": {
      "id": "11111111-2222-3333-4444-555555555555",
      "storeId": "STO_2aUyqjCzEIiEcYMKj7TZtw",
      "email": "ops@acme.com",
      "isPrimary": false,
      "preferences": {
        "notifyNewOrders": false,
        "notifyNewSubscriptions": true,
        "notifySubscriptionCanceled": true,
        "notifySubscriptionRenewed": true,
        "notifySubscriptionEnded": true,
        "notifySubscriptionPastDue": true,
        "notifySubscriptionUncanceled": true,
        "notifySubscriptionPlanChanged": true,
        "notifyChargeback": true
      },
      "createdAt": "2026-08-28T00:00:00.000Z"
    }
  }
}
```

<Note>
  邮箱地址本身不可修改。要把通知换到另一个地址，请先添加新收件人，再移除旧的。
</Note>

## 响应字段

| 字段            | 类型      | 说明                                 |
| ------------- | ------- | ---------------------------------- |
| `id`          | string  | 收件人 UUID                           |
| `storeId`     | string  | 所属门店 Short ID                      |
| `email`       | string  | 归一化后的收件地址（本端点不会改动）                 |
| `isPrimary`   | boolean | 此处恒为 `false` —— 物化兜底条目会把它变成一条真实收件人 |
| `preferences` | object  | 合并本次改动后的 9 个事件开关                   |
| `createdAt`   | string  | 创建时间（ISO 8601）                     |

## 错误

> **重试策略：** 4xx 一律不要重试 —— 修正请求后重新提交。5xx 用指数退避重试（起始 5 秒，最多 3 次）。

| 状态码 | `errors[0].message`                                               | 含义                                       | 建议处理                                  |
| --- | ----------------------------------------------------------------- | ---------------------------------------- | ------------------------------------- |
| 400 | `Missing required field: recipientId`                             | 未提供 `recipientId`                        | 修正请求体后重新提交                            |
| 400 | `Invalid recipient id format: expected UUID, got "..."`           | `recipientId` 既非 UUID 也非本店哨兵值            | 原样回传 add-recipient 或 GraphQL 返回的 `id` |
| 400 | `Unrecognized key: "notifyUnknownThing"`                          | 提交了 9 项事件目录之外的键                          | 移除该键后重新提交                             |
| 401 | `Missing merchantId in request context`                           | API Key 认证未解析出商户                         | 检查 API Key 请求头与签名                     |
| 403 | `Not authorized to manage notification recipients for this store` | 商户不是该门店的 `owner` 或 `admin`               | 确认商户在该门店的角色                           |
| 404 | `Notification recipient not found`                                | 该门店下没有这个 id 的收件人；或哨兵 id 对应的兜底条目已被真实收件人取代 | 重新拉取列表                                |
| 409 | `Notification recipients changed concurrently, please retry`      | 读与写之间有并发写入改动了列表                          | 重新拉取列表后重试                             |
| 500 | `Internal server error`                                           | 服务端未预期故障                                 | 用指数退避重试（起始 5 秒，最多 3 次）                |
