Files
atlas-seller-kit/docs/api/stores-and-platforms.md

8.0 KiB
Raw Permalink Blame History

平台上下文与店铺管理 API

1. 平台目录与页头上下文

GET /api/platforms

返回当前可选择、已启用的平台及客户端所需的非敏感能力:

{
  "data": [{
    "id": "uuid",
    "code": "OZON",
    "name": "Ozon",
    "supported_currencies": ["CNY", "RUB"],
    "default_currency_code": "CNY",
    "default_market_code": "RU",
    "default_locale": "ru-RU"
  }]
}

GET /api/platform-context

要求 X-Atlas-Platform-Id,返回平台摘要、该工作空间在此平台的默认店铺摘要和店铺数。没有默认店铺不是错误:default_store 为 null,编辑/发布类接口会另外要求可用店铺。

2. 店铺资源形状

{
  "id": "uuid",
  "platform_id": "uuid",
  "name": "Ozon 俄罗斯店",
  "platform_client_id": "123456",
  "currency_code": "RUB",
  "is_default": true,
  "note": "主店",
  "status": "active",
  "credential_status": "valid",
  "credential_checked_at": "2026-09-02T08:00:00Z",
  "last_error": null,
  "api_key_expires_at": null,
  "product_limit": null,
  "product_limit_checked_at": null,
  "warehouse_count": 3,
  "warehouses_synced_at": "2026-09-02T08:01:00Z",
  "cookie_status": null,
  "watermark_template": { "id": "uuid", "name": "右下角品牌" },
  "created_at": "2026-09-02T08:00:00Z",
  "updated_at": "2026-09-02T08:00:00Z",
  "revision": 1
}

api_key_expires_at 和 product_limit 无平台事实来源时为 null,前端显示 —;不能估算。首期 cookie_status 固定为 null,不暗示 Cookie 可用于正式发布。响应绝不包含 api_key、密文、指纹或仓库原始平台 payload。

3. 查询店铺

GET /api/stores?platform_id={uuid}&cursor={opaque}&limit=20

platform_id 必填,按 created_at DESC, id DESC 返回当前工作空间未删除店铺。该管理列表可使用查询参数,不能同时传平台 header。

GET /api/stores/{store_id}

返回店铺资源。资源不属于当前工作空间或已删除时返回 404。

4. 添加店铺授权

POST /api/stores

Headers:Idempotency-Key 必填。

{
  "platform_id": "uuid",
  "name": "Ozon 俄罗斯店",
  "client_id": "123456",
  "api_key": "secret-only-in-request",
  "currency_code": "RUB",
  "is_default": true,
  "note": "主店"
}

校验 currency_code 是否为目标平台可用币种。服务端立即把 API Key 信封加密保存、创建 status=verifying 的店铺,并投递低风险凭据验证操作;不得将 Key 放入任务 payload、日志或响应。仓库同步是独立的后续操作,不随创建自动触发。

返回 202 Accepted:

{
  "data": {
    "store": { "id": "uuid", "status": "verifying", "credential_status": "unknown" },
    "operation": { "id": "uuid", "kind": "store_credential_verification", "status": "queued" }
  }
}

首家未删除店铺强制为默认。对已有店铺提交 is_default=true 时,服务端在同一事务取消旧默认店铺;校验失败不把店铺置为 active,失败原因以可展示的脱敏 last_error 摘要(code、message、at)返回给后续读取接口。

4.1 Ozon 凭据验证与前端展示

Worker 只调用一个无写副作用的 Ozon Seller API 探针:

POST /v1/description-category/tree
Client-Id: <store platform_client_id>
Api-Key: <decrypted secret, worker memory only>
Content-Type: application/json

{ "language": "ZH_HANS" }

该调用只用于验证 Ozon 是否接受当前 Client ID 与 API Key,不创建、修改或同步任何 Ozon 数据。它不携带 API Key 至队列、日志、operation 或 HTTP 响应。

Worker 结果 店铺最终状态 前端文案与行为
operation 为 queued / running status=verifying、credential_status=unknown 仅显示“验证中”;不要同时展示“未验证”。可轮询 operation,并在终态后刷新店铺列表。
Ozon 返回 2xx active / valid 显示“正常”。
Ozon 返回 401 credential_invalid / invalid 显示“凭据无效”,提示用户核对 Client ID 与 API Key。
Ozon 返回 403 credential_invalid / invalid 显示“访问被拒绝”,提示 Client ID 与 API Key 必须属于同一账户,且密钥需要读取权限。
Ozon 返回其他确定性 4xx sync_error / 保留当前凭据状态 显示 last_error.message;该状态不代表 API Key 无效。
网络超时、429 或 5xx 保持验证中,Worker 重试;重试耗尽后为 sync_error 显示“暂时无法验证,请稍后重试”。

页面最终以 GET /api/stores 返回的店铺状态为准;GET /api/operations/{operation_id} 只用于得知异步过程是否结束及读取脱敏错误。点击“重新验证凭据”会重新发起上述一次类目树请求。

5. 编辑、默认店铺、验证与删除

PATCH /api/stores/{store_id}

Headers:If-Match 与 Idempotency-Key 必填。

{
  "name": "Ozon 俄罗斯主店",
  "currency_code": "RUB",
  "note": "更新备注",
  "api_key": "optional-replacement-secret"
}

不可修改 platform_id 和 client_id,避免把一个授权连接变成另一个平台/账户。未传 api_key 代表保留旧密钥;传入时替换、撤销旧密钥并再次触发凭据验证。普通编辑返回 200;包含新 Key 时返回 202 和验证 operation。

POST /api/stores/{store_id}/set-default

Headers:Idempotency-Key 必填。路径店铺在其平台下成为默认店铺,返回更新后的店铺摘要。无 body。

POST /api/stores/{store_id}/credential-verifications

Headers:Idempotency-Key 必填。手动重试凭据校验,返回 202 与 operation。店铺停用或删除时返回 422。

POST /api/stores/{store_id}/category-tree-syncs

Headers:Idempotency-Key 必填。同步请求 Ozon POST /v1/description-category/tree 并写入目标门店缓存;只有完整响应成功落库后才返回 200 与类目数量。必须是凭据已验证的 Ozon 门店,否则返回 422 STORE_CREDENTIAL_UNAVAILABLE。Ozon 请求或落库失败返回脱敏错误,旧缓存保持不变。此手动操作不经 Worker 或队列,API Key 仅在服务端请求期间短暂存在。

此端点是现有门店级能力,不是未来系统管理员同步入口。迁移至平台级参考目录时,须另行修订/废弃该同步语义;管理员操作应按平台排入统一后台任务,不复用本同步 HTTP 路径直接请求 Ozon。

POST /api/stores/{store_id}/warehouse-syncs

Headers:Idempotency-Key 必填。触发 Ozon POST /v1/warehouse/list 同步,返回 202 与 operation。凭据无效时不调用平台,返回 422 STORE_CREDENTIAL_UNAVAILABLE。

DELETE /api/stores/{store_id}

Headers:Idempotency-Key 必填。仅软删除 Atlas 内的店铺连接,不影响 Ozon 后台。删除当前默认店铺时:若同平台仍有其他未删除店铺,返回 422 DEFAULT_STORE_REPLACEMENT_REQUIRED,客户端必须先选择新的默认店铺;若没有其他店铺,可以删除,平台默认店铺变为 null。

6. 仓库与推荐水印

GET /api/stores/{store_id}/warehouses

返回最近一次同步成功的仓库摘要,按名称排序:

{ "data": [{ "id": "uuid", "platform_warehouse_id": "123", "name": "Москва", "fulfillment": "rfbs", "is_rfbs": true, "status": "active", "synced_at": "2026-09-02T08:01:00Z" }] }

从未成功同步时返回空数组及 meta.warehouses_synced_at = null,不把空数组解释为平台没有仓库。

PUT /api/stores/{store_id}/watermark-binding

Headers:Idempotency-Key 必填。

{ "template_id": "uuid" }

传 { "template_id": null } 表示“暂不绑定”。模板必须是当前工作空间的活动模板。服务端在事务内结束旧绑定、创建新绑定(或保持未绑定),返回店铺中的 watermark_template 摘要。此绑定只代表图片编辑弹窗的未来推荐值;首期不会自动改写已有图片或在发布时添加水印。