Raise App API
版本 1.2.0。下载 OpenAPI 文件(YAML)
概述
给已安装的应用用的接口(主版本 v1):客户中心、站点访客、经营记账、审计链、当前人员的权限与部门、成员、安装了本应用的企业、其他应用的服务、本应用的开放事件、记录链接。调用根地址是 https://api.{域名}/app/v1(https://app.{域名}/app/v1 同样可用)。
本文件里的路径已经去掉了这个前缀:GET /access 就是 GET https://api.{域名}/app/v1/access。它与 /open/v1(open-v1.openapi.yaml)是平台的两个接口面:/open/v1 给组织授权的集成读写组织数据,/app/v1 给已安装的应用调用平台能力;同一个生成器 tools/sdkgen 生成两套 SDK 客户端。
令牌与范围
- 令牌 应用自己的租户令牌(
POST /open/v1/oauth/token,grant_type=client_credentials,见 open-v1 文档),或使用这个应用页面的人的页面会话。客户令牌不能调用这里(403forbidden)。 - 范围 每个操作需要一个
app.…范围(操作的x-raise-scope,描述里也写着)。范围必须是应用在清单(manifest)uses里声明过的:令牌里带着它们,页面会话也按清单给。没声明的范围是 403scope_required。 - 租户 永远是令牌的租户。响应头
X-K3-Tenant写出令牌实际指向的组织。 - 有些操作只收应用自己的令牌(没有人在背后),页面会话是 403
forbidden,操作描述里会写明。
约定
与 /open/v1 相同的约定:
- 错误 状态 ≥ 400 的正文都是
{"error":{"code","message","requestId","docUrl","details"}}。code稳定,用它分支;message给人看。details没内容时是{}。requestId与响应头X-Request-Id相同,报问题时带上。 - 幂等 每个
POST收Idempotency-Key(1–255 字符)。范围是应用 + 组织。保存 24 小时。同键同方法同路径同正文 → 重放第一次的回答,并带Idempotent-Replayed: true。同键不同正文 → 409idempotency_conflict。第一次还在处理 → 409idempotency_in_progress。状态 ≥ 500 的回答不保存。SDK 会在 POST 上自动生成 uuid v4。业务上的去重另有自己的键(记账的sourceApp + sourceRef + kind、接触的key、事件的key、服务调用的idempotencyKey),它们在正文里,与这个头无关。 - 限流 认证过的调用都带
X-RateLimit-Limit、X-RateLimit-Remaining、X-RateLimit-Reset。429 另带Retry-After(秒)。Raise-Environment: test|live说明这把令牌属于哪边。 - 时间 RFC 3339 UTC。金额 整数最小货币单位。JSON 字段 camelCase(
GET /access的正文例外,见该操作)。 - 正文里的未知字段会被拒绝(422)。
实时文档的同步连接(不在这个文件的路径里)
realtime 接口管文档的建立、服务端改动和读取;人在页面里的协同编辑走 WebSocket,由平台在应用自己的域名上提供(经应用网关,不在 api.{域名}):GET /app/v1/realtime/sync?codec=&kind=(一条连接服务这个编码、这个种类的所有文档)和 GET /app/v1/realtime/docs/{id}/sync(同一条连接,编码与种类从文档读)。网关先检查应用令牌、安装、Origin 和连接数,再交给平台;页面一侧用 @21stware/raise-design 的实时文档组件或应用 SDK(packages/app-sdk/go/realtime)连接,不要自己拼协议。每份文档的权限是调用者在它所属资源上的级别(resources 接口)。
清单 realtime.docs[] 的每个种类还可以写三项。admit:本应用的一个权限点(permissions[].id),开同步连接的人必须持有,否则 403;不写则网关放进来的人都可以。topics:本应用声明的资源类型(resources[].type);同步连接可以订阅 <类型>:<id>,平台在调用者对这个资源至少有查看级别时放行;<类型>:* 是这个类型的列表(有一个被新建、改名、归档或分享给人),持有 admit 权限点的人可以订阅(没写 admit 的种类没有列表主题);其余主题一律拒绝;应用用 POST /realtime/topics/{topic}/publish 告诉订阅者有变化。store:这个种类的文档放在哪个命名空间,默认本应用 id;写别的应用 id 就是与它共用文档,平台只在对方已安装的清单里也声明了同一种类、同一 store、同一编码(双方都同意),且两个应用属于同一开发者组织时接受(提交版本时检查一次,每次使用时再检查)。共用命名空间不扩大权限:每个应用的人仍只按它自己声明的资源类型判断。English: each kind may also set admit (a permission point a person must hold to open a sync connection), topics (declared resource types whose <type>:<id> topics a client may subscribe to at view level or above, and <type>:*, the list of that type, for whoever holds the admit point) and store (the namespace, default the app id; another app's id shares that app's documents only when both declare the same kind, store and codec and both apps belong to one developer organisation).
用 Go 模块 github.com/21stware/raise-go(client.App.…)或 npm 包 @tokiter/raise-sdk(raise.app.…),不要自己拼重试。SDK 的基地址是 /open/v1 根,应用接口的根由它换成同级的 /app/v1。
地址
/app/v1
认证方式
| 名称 | 类型 | 说明 |
|---|---|---|
bearer | http bearer | 应用自己的租户令牌(POST /open/v1/oauth/token 换到),或使用这个应用页面的人的页面会话。Authorization: Bearer <token> |
customers
客户中心:按手机号等身份找到或建立客户、读遮蔽后的资料、记录一次接触
POST /customers/resolve
按身份(手机号等)找到或建立客户,返回主客户的 id
需要范围 app.customers:resolve。English: finds the customer that owns one of the identities, or creates one, and answers the primary customer's id and whether this call created it.
identities 是这个人的身份(kind、value,可带 scope、verified)。name、owner、ownerUnit 在新建客户时使用。channel 与 sourceRef 是这位客户第一次从哪里来(来源应用是调用的应用,不能自己填)。public 标记匿名访客发起的调用。anonymous 要求新建一位没有任何身份的客户,此时 identities 必须为空,也不做任何匹配,所以一定新建。
查询 dryRun=1:只回答“会得到什么”,什么也不写(不建客户);新建的客户 id 不会被任何别的调用认识。
数据范围:页面会话里的人找到的客户如果不在他「查看客户」(customer.read)的数据范围内,回答只有 id 与 created,没有 name;应用自己的调用(企业令牌)不受影响。
正文里的字段不合规是 422。
- 认证:
bearer - 范围:
app.customers:resolve - operationId:
resolveCustomer
参数
| 名称 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
dryRun | query | string | 传 1 时只预演,不写入 可选值: 1 | |
Idempotency-Key | header | string | 每个 POST 都收。SDK 未传入时会生成 uuid v4。24 小时内同键同正文重放第一次的回答 最短 1,最长 255 |
请求正文(必填)(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
identities | CustomerIdentity[] | 是 | 这个人的身份。anonymous 为 true 时必须为空 |
identities[].kind | string | 是 | 身份的种类 |
identities[].scope | string | 身份所在的范围。可省略 | |
identities[].value | string | 是 | 身份的值 |
identities[].verified | boolean | 这个身份已被证明 | |
name | string | 新建客户时使用的姓名 | |
channel | string | 第一次来源的渠道 | |
sourceRef | string | 第一次来源:指向那次活动的 k3:// 引用 | |
owner | string | 新建客户时的负责人 | |
ownerUnit | string | 新建客户时的归属部门 | |
public | boolean | 标记这是匿名访客发起的调用 | |
anonymous | boolean | 要求新建一位没有任何身份的客户;此时 identities 必须为空,不做匹配,一定新建 |
响应
| 状态 | 说明 |
|---|---|
| 200 | 主客户。created 说明这次调用是否新建了它 |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 413 | payload_too_large:正文太大。见 PayloadTooLarge |
| 422 | 字段或参数不被接受(正文读不出来、有未知字段、缺必填、取值越界)。见 Unprocessable |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
200 响应正文(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
id | string | 是 | 主客户的 id |
created | boolean | 是 | 这次调用是否新建了它 |
name | string | 客户中心保存的姓名:新建时或原来没有姓名时是这次给的,否则是原有的 |
GET /customers/{id}
读一位客户的遮蔽资料
需要范围 app.customers:read。English: the customer's profile with phone and e-mail masked.
id 是主客户的 id。若这个 id 的客户已被合并,返回的 id 是合并后的主客户(与你问的不同),mergedFrom 列出并入它的客户。客户中心没有这个 id 是 404 not_found。
数据范围:应用自己的调用(企业令牌)可读本企业任何客户;页面会话里的人只能读他在客户应用里「查看客户」(customer.read)数据范围内的客户,范围外的与不存在一样返回 404。
- 认证:
bearer - 范围:
app.customers:read - operationId:
getCustomerProfile
参数
| 名称 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
id | path | string | 是 | 客户 id |
响应
| 状态 | 说明 |
|---|---|
| 200 | 客户资料 |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 404 | not_found:对应的记录不存在(客户中心没有这个客户,访客、服务或所指的东西不存在)。见 NotFound |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
200 响应正文(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
id | string | 是 | 主客户的 id;被合并过时与所问的 id 不同 |
name | string | 是 | |
stage | string | 是 | 生效的阶段:lead、customer 或 dormant(长期没有接触的客户是 dormant) |
owner | string | 负责人(员工 subject) | |
ownerUnit | string | ||
sourceApp | string | 第一次带来这位客户的应用 | |
sourceChannel | string | ||
phone | string | 打码后的第一个电话 | |
tags | string[] | 标签 id | |
lastTouchAt | string(date-time) | 是 | |
createdAt | string(date-time) | 是 | |
wecomBasis | string | 企业微信外部联系人与客户的关联依据,取最弱的一个:none、phone 或 unionid;没有外部联系人时为空 | |
wecomPending | boolean | 即 wecomBasis 为 none(待关联) | |
sourceRef | string | ||
dealtAt | string(date-time) | ||
identities | CustomerIdentityView[] | 是 | |
identities[].kind | string | 是 | |
identities[].scope | string | ||
identities[].masked | string | 是 | 打码后的值 |
identities[].value | string | 明文。只在请求了明文时出现 | |
identities[].verified | boolean | 是 | |
identities[].firstSeen | string(date-time) | 是 | |
identities[].source | string | ||
links | string[] | 是 | |
mergedFrom | string[] | 并入它的客户 | |
touchCount | integer | 是 | 这位客户及并入它的客户的接触总数 |
POST /customers/touch
给客户的时间线记一次接触(同一个 key 只记一次)
需要范围 app.customers:resolve。English: appends one entry to the customer's timeline, once per key.
kind 写成 {应用}.{动作}(例如 coupons.redeem),ref 是指向所发生之事的 k3:// 引用,key 是幂等键(租户内唯一,用来源事件派生,例如 coupons:claim:cl_17),at 省略为现在。同一个 key 再来,written 为 false。
- 认证:
bearer - 范围:
app.customers:resolve - operationId:
touchCustomer
参数
| 名称 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
Idempotency-Key | header | string | 每个 POST 都收。SDK 未传入时会生成 uuid v4。24 小时内同键同正文重放第一次的回答 最短 1,最长 255 |
请求正文(必填)(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
customer | string | 是 | 客户 id |
key | string | 是 | 幂等键,租户内唯一,用来源事件派生 |
kind | string | 是 | {应用}.{动作},例如 coupons.redeem |
ref | string | 指向所发生之事的 k3:// 引用 | |
attrs | object | ||
at | string(date-time) | 省略为现在 |
响应
| 状态 | 说明 |
|---|---|
| 200 | written 为 true 表示这次写入了;false 表示这个 key 以前就有 |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 404 | not_found:对应的记录不存在(客户中心没有这个客户,访客、服务或所指的东西不存在)。见 NotFound |
| 413 | payload_too_large:正文太大。见 PayloadTooLarge |
| 422 | 字段或参数不被接受(正文读不出来、有未知字段、缺必填、取值越界)。见 Unprocessable |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
200 响应正文(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
written | boolean | 是 | false 表示这个 key 以前就有 |
GET /customers
列出调用者(这个人)有权看的客户
需要范围 app.customers:list。English: a page of the customers inside the calling person's customer.read grant on the customer app.
数据范围是这个人在客户应用上的 customer.read 授权,不是应用自己的权限:应用用自己的令牌调用,或这个人没有 customer.read,都是 403。stage 是 lead、customer 或 dormant;limit 为 1 到 200;hint 只留下处在待处理合并建议一端的客户;wecomPending 只留下企业微信外部联系人尚未关联的客户。字段不合规是 422。
- 认证:
bearer - 范围:
app.customers:list - operationId:
listCustomerPage
参数
| 名称 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
q | query | string | 按姓名或身份搜索 | |
stage | query | string | 阶段 可选值: lead、customer、dormant | |
tag | query | string | 标签 id | |
owner | query | string | 负责人(员工 subject) | |
source | query | string | 来源应用 | |
hint | query | boolean | 只留下有合并建议的客户 | |
wecomPending | query | boolean | 只留下企业微信待关联的客户 | |
limit | query | integer | 一页多少条 最小 1,最大 200 | |
offset | query | integer | 跳过多少条 最小 0 |
响应
| 状态 | 说明 |
|---|---|
| 200 | 一页客户和同范围同筛选下的总数 |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 422 | 字段或参数不被接受(正文读不出来、有未知字段、缺必填、取值越界)。见 Unprocessable |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
200 响应正文(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
items | CustomerSummary[] | 是 | |
items[].id | string | 是 | 主客户的 id |
items[].name | string | 是 | |
items[].stage | string | 是 | 生效的阶段:lead、customer 或 dormant |
items[].owner | string | 负责人(员工 subject) | |
items[].ownerUnit | string | ||
items[].sourceApp | string | 第一次带来这位客户的应用 | |
items[].sourceChannel | string | ||
items[].phone | string | 打码后的第一个电话 | |
items[].tags | string[] | 标签 id | |
items[].lastTouchAt | string(date-time) | 是 | |
items[].createdAt | string(date-time) | 是 | |
items[].wecomBasis | string | 企业微信外部联系人与客户的关联依据,取最弱的一个:none、phone 或 unionid;没有外部联系人时省略 | |
items[].wecomPending | boolean | 即 wecomBasis 为 none(待关联) | |
total | integer | 是 | 同一范围、同一筛选下的客户总数 |
GET /customers/find
按手机号找到一位客户
需要范围 app.customers:read。English: finds the customer that owns the phone and answers the masked profile.
kind 目前只有 phone,value 是号码。没有这位客户是 404 not_found;kind 不对或 value 为空是 422。
- 认证:
bearer - 范围:
app.customers:read - operationId:
findCustomer
参数
| 名称 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
kind | query | string | 是 | 身份的种类 可选值: phone |
value | query | string | 是 | 身份的值 |
响应
| 状态 | 说明 |
|---|---|
| 200 | 客户资料 |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 404 | not_found:对应的记录不存在(客户中心没有这个客户,访客、服务或所指的东西不存在)。见 NotFound |
| 422 | 字段或参数不被接受(正文读不出来、有未知字段、缺必填、取值越界)。见 Unprocessable |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
200 响应正文(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
id | string | 是 | 主客户的 id;被合并过时与所问的 id 不同 |
name | string | 是 | |
stage | string | 是 | 生效的阶段:lead、customer 或 dormant(长期没有接触的客户是 dormant) |
owner | string | 负责人(员工 subject) | |
ownerUnit | string | ||
sourceApp | string | 第一次带来这位客户的应用 | |
sourceChannel | string | ||
phone | string | 打码后的第一个电话 | |
tags | string[] | 标签 id | |
lastTouchAt | string(date-time) | 是 | |
createdAt | string(date-time) | 是 | |
wecomBasis | string | 企业微信外部联系人与客户的关联依据,取最弱的一个:none、phone 或 unionid;没有外部联系人时为空 | |
wecomPending | boolean | 即 wecomBasis 为 none(待关联) | |
sourceRef | string | ||
dealtAt | string(date-time) | ||
identities | CustomerIdentityView[] | 是 | |
identities[].kind | string | 是 | |
identities[].scope | string | ||
identities[].masked | string | 是 | 打码后的值 |
identities[].value | string | 明文。只在请求了明文时出现 | |
identities[].verified | boolean | 是 | |
identities[].firstSeen | string(date-time) | 是 | |
identities[].source | string | ||
links | string[] | 是 | |
mergedFrom | string[] | 并入它的客户 | |
touchCount | integer | 是 | 这位客户及并入它的客户的接触总数 |
GET /customers/{id}/timeline
读一位客户的时间线(新的在前)
需要范围 app.customers:read。English: the customer's timeline entries, newest first, paged by the id of the last one seen.
limit 为 1 到 200;before 是上一页最后一条的 id,只取比它早的。没有这个客户是 404 not_found。
- 认证:
bearer - 范围:
app.customers:read - operationId:
listCustomerTimeline
参数
| 名称 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
id | path | string | 是 | 客户 id(主客户;被合并过的 id 会指到合并后的客户) |
limit | query | integer | 最多几条 最小 1,最大 200 | |
before | query | integer(int64) | 只取 id 比它小的接触 最小 0 |
响应
| 状态 | 说明 |
|---|---|
| 200 | 接触,新的在前 |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 404 | not_found:对应的记录不存在(客户中心没有这个客户,访客、服务或所指的东西不存在)。见 NotFound |
| 422 | 字段或参数不被接受(正文读不出来、有未知字段、缺必填、取值越界)。见 Unprocessable |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
200 响应正文(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
items | CustomerTouchView[] | 是 | |
items[].id | integer(int64) | 是 | 接触的 id,翻页用 |
items[].customer | string | 是 | 写给哪位客户(可能是已并入的) |
items[].kind | string | 是 | {应用}.{动作} |
items[].app | string | ||
items[].ref | string | 指向所发生之事的 k3:// 引用 | |
items[].attrs | object | 是 | |
items[].at | string(date-time) | 是 |
POST /customers/{id}/rename
改客户的姓名
需要范围 app.customers:write。English: renames the customer. 没有这个客户是 404 not_found。
- 认证:
bearer - 范围:
app.customers:write - operationId:
renameCustomer
参数
| 名称 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
id | path | string | 是 | 客户 id(主客户;被合并过的 id 会指到合并后的客户) |
Idempotency-Key | header | string | 每个 POST 都收。SDK 未传入时会生成 uuid v4。24 小时内同键同正文重放第一次的回答 最短 1,最长 255 |
请求正文(必填)(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
name | string | 是 |
响应
| 状态 | 说明 |
|---|---|
| 204 | 已办。没有正文 |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 404 | not_found:对应的记录不存在(客户中心没有这个客户,访客、服务或所指的东西不存在)。见 NotFound |
| 413 | payload_too_large:正文太大。见 PayloadTooLarge |
| 422 | 字段或参数不被接受(正文读不出来、有未知字段、缺必填、取值越界)。见 Unprocessable |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
POST /customers/{id}/links
把本应用的一条记录挂到客户上
需要范围 app.customers:write。English: links one of the calling app's own records to the customer.
ref 必须是本应用自己的记录(k3://<调用的应用>/…),别的应用的引用是 422。
- 认证:
bearer - 范围:
app.customers:write - operationId:
linkCustomer
参数
| 名称 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
id | path | string | 是 | 客户 id(主客户;被合并过的 id 会指到合并后的客户) |
Idempotency-Key | header | string | 每个 POST 都收。SDK 未传入时会生成 uuid v4。24 小时内同键同正文重放第一次的回答 最短 1,最长 255 |
请求正文(必填)(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
ref | string | 是 | 本应用自己的记录:k3://<调用的应用>/… |
响应
| 状态 | 说明 |
|---|---|
| 204 | 已办。没有正文 |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 404 | not_found:对应的记录不存在(客户中心没有这个客户,访客、服务或所指的东西不存在)。见 NotFound |
| 413 | payload_too_large:正文太大。见 PayloadTooLarge |
| 422 | 字段或参数不被接受(正文读不出来、有未知字段、缺必填、取值越界)。见 Unprocessable |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
POST /customers/{id}/owner
改客户的负责人和归属部门
需要范围 app.customers:write。English: sets the customer's owner and owning unit.
owner 是员工 subject,ownerUnit 是部门 id;两个都可以是空串,表示清空。
- 认证:
bearer - 范围:
app.customers:write - operationId:
setCustomerOwner
参数
| 名称 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
id | path | string | 是 | 客户 id(主客户;被合并过的 id 会指到合并后的客户) |
Idempotency-Key | header | string | 每个 POST 都收。SDK 未传入时会生成 uuid v4。24 小时内同键同正文重放第一次的回答 最短 1,最长 255 |
请求正文(必填)(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
owner | string | 是 | 员工 subject;空串清空 |
ownerUnit | string | 是 | 部门 id;空串清空 |
响应
| 状态 | 说明 |
|---|---|
| 204 | 已办。没有正文 |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 404 | not_found:对应的记录不存在(客户中心没有这个客户,访客、服务或所指的东西不存在)。见 NotFound |
| 413 | payload_too_large:正文太大。见 PayloadTooLarge |
| 422 | 字段或参数不被接受(正文读不出来、有未知字段、缺必填、取值越界)。见 Unprocessable |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
POST /customers/{id}/dealt
记这位客户成交了
需要范围 app.customers:write。English: marks the customer as having dealt, at the given time or now.
at 省略为现在。
- 认证:
bearer - 范围:
app.customers:write - operationId:
markCustomerDealt
参数
| 名称 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
id | path | string | 是 | 客户 id(主客户;被合并过的 id 会指到合并后的客户) |
Idempotency-Key | header | string | 每个 POST 都收。SDK 未传入时会生成 uuid v4。24 小时内同键同正文重放第一次的回答 最短 1,最长 255 |
请求正文(必填)(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
at | string(date-time) | 省略为现在 |
响应
| 状态 | 说明 |
|---|---|
| 204 | 已办。没有正文 |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 404 | not_found:对应的记录不存在(客户中心没有这个客户,访客、服务或所指的东西不存在)。见 NotFound |
| 413 | payload_too_large:正文太大。见 PayloadTooLarge |
| 422 | 字段或参数不被接受(正文读不出来、有未知字段、缺必填、取值越界)。见 Unprocessable |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
POST /customers/{id}/merge
把另一位客户并入这一位
需要范围 app.customers:write。English: merges the other customer into this one and answers the primary customer's id.
other 必填。两个 id 都可以是已被合并过的,返回的 primary 是合并后的主客户。
- 认证:
bearer - 范围:
app.customers:write - operationId:
mergeCustomers
参数
| 名称 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
id | path | string | 是 | 客户 id(主客户;被合并过的 id 会指到合并后的客户) |
Idempotency-Key | header | string | 每个 POST 都收。SDK 未传入时会生成 uuid v4。24 小时内同键同正文重放第一次的回答 最短 1,最长 255 |
请求正文(必填)(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
other | string | 是 | 并入这一位的客户 id |
响应
| 状态 | 说明 |
|---|---|
| 200 | 合并后的主客户 |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 404 | not_found:对应的记录不存在(客户中心没有这个客户,访客、服务或所指的东西不存在)。见 NotFound |
| 413 | payload_too_large:正文太大。见 PayloadTooLarge |
| 422 | 字段或参数不被接受(正文读不出来、有未知字段、缺必填、取值越界)。见 Unprocessable |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
200 响应正文(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
primary | string | 是 | 合并后的主客户 id |
POST /customers/{id}/erase
抹除一位客户的个人数据(不可撤销)
需要范围 app.customers:write。English: erases the customer's personal data; final.
正文是 {}。抹除之后不能恢复。
- 认证:
bearer - 范围:
app.customers:write - operationId:
eraseCustomer
参数
| 名称 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
id | path | string | 是 | 客户 id(主客户;被合并过的 id 会指到合并后的客户) |
Idempotency-Key | header | string | 每个 POST 都收。SDK 未传入时会生成 uuid v4。24 小时内同键同正文重放第一次的回答 最短 1,最长 255 |
请求正文(必填)(application/json)
类型 CustomerEraseRequest。空对象 {}
响应
| 状态 | 说明 |
|---|---|
| 204 | 已办。没有正文 |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 404 | not_found:对应的记录不存在(客户中心没有这个客户,访客、服务或所指的东西不存在)。见 NotFound |
| 413 | payload_too_large:正文太大。见 PayloadTooLarge |
| 422 | 字段或参数不被接受(正文读不出来、有未知字段、缺必填、取值越界)。见 Unprocessable |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
GET /customers/tags
列出企业的客户标签库(opv2 J2 ④)
需要范围 app.customers:read。English: the tenant's tag dictionary; writable says which tags an app may put on and take off.
不含每个标签有多少客户。
- 认证:
bearer - 范围:
app.customers:read - operationId:
listCustomerTags
响应
| 状态 | 说明 |
|---|---|
| 200 | 标签库 |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
200 响应正文(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
items | AppCustomerTag[] | 是 | |
items[].id | string | 是 | 标签 id |
items[].name | string | 是 | 名称 |
items[].color | string | 是 | 颜色 |
items[].source | string | 是 | 来源:manual、wecom 或 rule |
items[].writable | boolean | 是 | 应用能不能打上、去掉(手动标签) |
PUT /customers/{id}/tags/{tag}
给本企业的一位客户打上标签(opv2 J2 ④)
需要范围 app.customers:tag。English: puts a manual tag on a customer of the tenant.
只能是标签库里的手动标签:别的来源(企业微信)的标签只读,返回 422 validation_failed。客户或标签不存在是 404 not_found;客户被合并时作用在主客户上。重复调用结果相同。每次改动在企业的审计链里记一条(customer.tag / customer.untag,操作者是页面会话的人或应用自己);一个应用在一个企业里每 10 分钟最多改 3000 次,超过返回 429。只限本企业的客户:应用自己的调用(企业令牌)可改本企业任何客户;页面会话里的人只能改他在客户应用里「编辑客户」(customer.write)的数据范围内的客户,范围外的客户与不存在一样返回 404。
- 认证:
bearer - 范围:
app.customers:tag - operationId:
addCustomerTag
参数
| 名称 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
Idempotency-Key | header | string | 每个 POST 都收。SDK 未传入时会生成 uuid v4。24 小时内同键同正文重放第一次的回答 最短 1,最长 255 | |
id | path | string | 是 | 客户 id |
tag | path | string | 是 | 标签 id(GET /customers/tags) |
响应
| 状态 | 说明 |
|---|---|
| 200 | 已改 |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 404 | not_found:对应的记录不存在(客户中心没有这个客户,访客、服务或所指的东西不存在)。见 NotFound |
| 422 | 字段或参数不被接受(正文读不出来、有未知字段、缺必填、取值越界)。见 Unprocessable |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
200 响应正文(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
customer | string | 是 | 客户 id |
tag | string | 是 | 标签 id |
on | boolean | 是 | true 打上,false 去掉 |
DELETE /customers/{id}/tags/{tag}
去掉本企业一位客户的标签(opv2 J2 ④)
需要范围 app.customers:tag。English: takes a manual tag off a customer of the tenant.
只能是标签库里的手动标签:别的来源(企业微信)的标签只读,返回 422 validation_failed。客户或标签不存在是 404 not_found;客户被合并时作用在主客户上。重复调用结果相同。每次改动在企业的审计链里记一条(customer.tag / customer.untag,操作者是页面会话的人或应用自己);一个应用在一个企业里每 10 分钟最多改 3000 次,超过返回 429。只限本企业的客户:应用自己的调用(企业令牌)可改本企业任何客户;页面会话里的人只能改他在客户应用里「编辑客户」(customer.write)的数据范围内的客户,范围外的客户与不存在一样返回 404。
- 认证:
bearer - 范围:
app.customers:tag - operationId:
removeCustomerTag
参数
| 名称 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
Idempotency-Key | header | string | 每个 POST 都收。SDK 未传入时会生成 uuid v4。24 小时内同键同正文重放第一次的回答 最短 1,最长 255 | |
id | path | string | 是 | 客户 id |
tag | path | string | 是 | 标签 id(GET /customers/tags) |
响应
| 状态 | 说明 |
|---|---|
| 200 | 已改 |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 404 | not_found:对应的记录不存在(客户中心没有这个客户,访客、服务或所指的东西不存在)。见 NotFound |
| 422 | 字段或参数不被接受(正文读不出来、有未知字段、缺必填、取值越界)。见 Unprocessable |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
200 响应正文(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
customer | string | 是 | 客户 id |
tag | string | 是 | 标签 id |
on | boolean | 是 | true 打上,false 去掉 |
visitors
站点访客与客户的对应
GET /site-visitors/{site}/{visitor}
一位站点访客对应的客户,以及访客是否证明了自己是谁
需要范围 app.visitors:read。English: the customer a site visitor is tied to, and whether the visitor proved the tie.
没有对应的客户时 customer 为空字符串,verified 为 false。verified 为 true 表示访客自己证明过身份(微信、短信验证码);表单或 Identify 写入的对应是 false。要授予访问权限请看 verified,只做归因看 customer 即可。
- 认证:
bearer - 范围:
app.visitors:read - operationId:
getSiteVisitor
参数
| 名称 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
site | path | string | 是 | 站点 id |
visitor | path | string | 是 | 访客 id |
响应
| 状态 | 说明 |
|---|---|
| 200 | 对应的客户 |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 404 | not_found:对应的记录不存在(客户中心没有这个客户,访客、服务或所指的东西不存在)。见 NotFound |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
200 响应正文(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
customer | string | 是 | 对应的客户 id;没有对应时为空字符串 |
verified | boolean | 是 | 访客自己证明过身份(微信、短信验证码);表单或 Identify 写入的对应是 false |
PUT /site-visitors/{site}/{visitor}
把一位站点访客认定为某位客户
需要范围 app.visitors:write。English: ties a site visitor to a customer.
正文 {customer}。返回写入后访客对应的客户 id。
- 认证:
bearer - 范围:
app.visitors:write - operationId:
identifySiteVisitor
参数
| 名称 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
site | path | string | 是 | 站点 id |
visitor | path | string | 是 | 访客 id |
请求正文(必填)(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
customer | string | 是 | 客户 id |
响应
| 状态 | 说明 |
|---|---|
| 200 | 访客现在对应的客户 |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 404 | not_found:对应的记录不存在(客户中心没有这个客户,访客、服务或所指的东西不存在)。见 NotFound |
| 413 | payload_too_large:正文太大。见 PayloadTooLarge |
| 422 | 字段或参数不被接受(正文读不出来、有未知字段、缺必填、取值越界)。见 Unprocessable |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
200 响应正文(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
customer | string | 是 | 访客现在对应的客户 id |
GET /site-visitors
按顺序号列出已被认定的站点访客(给订阅端续读)
需要范围 app.visitors:read。English: the identified visitors after a sequence number; a reader keeps the last seq it handled.
after 是已处理的最后一个 seq(默认 0,不能为负)。limit 必填,1 到 500。其他值是 422。没有结果时 items 是 []。
- 认证:
bearer - 范围:
app.visitors:read - operationId:
listIdentifiedSiteVisitors
参数
| 名称 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
after | query | integer | 从这个顺序号之后开始读 默认 0最小 0 | |
limit | query | integer | 条数,必填,1 到 500 最小 1,最大 500 |
响应
| 状态 | 说明 |
|---|---|
| 200 | 一批已认定的访客 |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 422 | 字段或参数不被接受(正文读不出来、有未知字段、缺必填、取值越界)。见 Unprocessable |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
200 响应正文(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
items | IdentifiedVisitor[] | 是 | |
items[].site | string | 是 | |
items[].visitor | string | 是 | |
items[].customer | string | 是 | |
items[].seq | integer | 是 | 顺序号,续读时作为 after |
items[].at | string(date-time) | 是 | |
items[].verified | boolean | 是 | 访客自己证明过身份;false 是表单或 Identify 写的对应 |
access
当前人员在本应用里能做什么,以及所在部门
GET /access
当前人员对本应用某个权限点能做什么
需要范围 app.access:read。English: what the caller (the person of the page session) may do with one permission of this app.
point 必填,必须以 app.{本应用 id}. 开头,否则 403 forbidden。type 是对象类型 id(读对象类型时用来取字段可见性)。
正文的字段名不是 camelCase:它是权限求值器的结果原样输出(Managed、Allowed、All、Self、Units、Subject、Personal、Fields)。基础模式(组织没有启用权限模型)下,平台角色说了算,Allowed 与范围不适用。平台没有接通权限求值时,回答是只有 {"managed": false}(小写)。
- 认证:
bearer - 范围:
app.access:read - operationId:
checkAccess
参数
| 名称 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
point | query | string | 是 | 权限点,以 app.{本应用 id}. 开头 |
type | query | string | 对象类型 id,可省略 |
响应
| 状态 | 说明 |
|---|---|
| 200 | 求值结果 |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
200 响应正文(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
Managed | boolean | 组织启用了权限模型。false 是基础模式:平台角色说了算,下面的字段不适用 | |
Allowed | boolean | 这个权限点是否允许 | |
All | boolean | 每一条记录 | |
Self | boolean | 自己创建的记录 | |
Units | string[],可为 null | 在这些部门创建的记录(子树已展开) | |
Subject | string | 被求值的人 | |
Personal | boolean | 个人授权给了(一部分)权限 | |
Fields | map[string, string],可为 null | 读对象类型时,调用者看到被打码或完全看不到的字段 |
POST /access/points
当前人员对本应用多个权限点能做什么(一次问完)
需要范围 app.access:read。English: what the caller may do with several permissions of this app, in one call.
points 是 1 到 100 个 {point, type},规则同 GET /access:每个 point 都必须以 app.{本应用 id}. 开头,有一个不是就整次 403 forbidden(什么都不问);个数为 0 或超过 100 是 422。results[i] 就是 GET /access 对 points[i] 的回答(同一个求值器、同样不是 camelCase 的字段名;平台没有接通权限求值时每一项都是 {"managed": false})。平台不记住答案:收回的权限在下一次调用就没有了。English: 1 to 100 {point, type}, each under the app.{app id}. prefix (one that is not refuses the whole call with 403 before anything is asked; none or over 100 is 422); results[i] is exactly GET /access's answer for points[i], nothing cached.
- 认证:
bearer - 范围:
app.access:read - operationId:
checkAccessPoints
参数
| 名称 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
Idempotency-Key | header | string | 每个 POST 都收。SDK 未传入时会生成 uuid v4。24 小时内同键同正文重放第一次的回答 最短 1,最长 255 |
请求正文(必填)(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
points | AccessPoint[] | 是 | 最多 100 项 |
points[].point | string | 是 | 权限点,以 app.{本应用 id}. 开头 |
points[].type | string | 对象类型 id,可省略 |
响应
| 状态 | 说明 |
|---|---|
| 200 | 每个权限点的求值结果,与请求同序 |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 413 | payload_too_large:正文太大。见 PayloadTooLarge |
| 422 | 字段或参数不被接受(正文读不出来、有未知字段、缺必填、取值越界)。见 Unprocessable |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
200 响应正文(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
results | Access[] | 是 | 与 points 同序,每项同 GET /access 的回答 |
results[].Managed | boolean | 组织启用了权限模型。false 是基础模式:平台角色说了算,下面的字段不适用 | |
results[].Allowed | boolean | 这个权限点是否允许 | |
results[].All | boolean | 每一条记录 | |
results[].Self | boolean | 自己创建的记录 | |
results[].Units | string[],可为 null | 在这些部门创建的记录(子树已展开) | |
results[].Subject | string | 被求值的人 | |
results[].Personal | boolean | 个人授权给了(一部分)权限 | |
results[].Fields | map[string, string],可为 null | 读对象类型时,调用者看到被打码或完全看不到的字段 |
GET /unit
当前人员所在的部门
需要范围 app.access:read。English: the department of the caller. 平台没有接通权限求值时是 501 capability_off。
- 认证:
bearer - 范围:
app.access:read - operationId:
getUnit
响应
| 状态 | 说明 |
|---|---|
| 200 | 部门 id(没有部门时为空字符串) |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
200 响应正文(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
unit | string | 是 | 部门 id;没有部门时为空字符串 |
directory
企业的成员列表
GET /members
企业的成员列表
需要范围 app.directory:read。English: the members of the tenant. 没有成员时 items 是 []。
- 认证:
bearer - 范围:
app.directory:read - operationId:
listDirectoryMembers
响应
| 状态 | 说明 |
|---|---|
| 200 | 成员 |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
200 响应正文(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
items | Member[] | 是 | |
items[].userId | string | 是 | |
items[].email | string | 是 | |
items[].name | string | 是 | |
items[].state | string | 是 | active、inactive 或 invited |
items[].roles | string[] | 是 | |
items[].machine | boolean | ||
items[].avatarUrl | string | 头像的绝对地址;没有头像时省略 |
ledger
向经营记账(本应用来源的记账行)
POST /ledger/posts
向经营记账记一笔(本应用来源)
需要范围 app.ledger:post。English: enqueues one posting in the platform's outbox and starts its delivery to the books; answers the outbox key.
sourceApp 必须是调用的应用,否则 403 forbidden;例外是本应用自己的网关收款按渠道记(与所有渠道记账一样):sourceApp 为 channel:wechat 或 channel:alipay,sourceRef 为 k3://payments/order/{id},那笔支付单是本应用在这个渠道建的、已付款,金额不超过它。English: sourceApp must be the calling app, or channel:{wechat|alipay} with sourceRef k3://payments/order/{id} of a paid payment order the app made on that channel, the amount within it. sourceApp + sourceRef + kind 是记账的去重键:同一组合只记一次。direction 是 in 或 out,amountCents 大于 0(分),currency 省略为组织的币种(不做换算,别的币种会被拒绝),occurredOn 省略为组织时区的今天。
reverses 写某个更早的同来源同引用的记账的 kind,本笔是它的冲销(金额必须相同、方向相反,不能同时是账单)。settles 写某笔开出账单的更早记账的 kind,本笔是对这张账单的付款。这两个字段互斥,也都不能与 bill 同用,违反是 422。
- 认证:
bearer - 范围:
app.ledger:post - operationId:
postLedger
参数
| 名称 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
Idempotency-Key | header | string | 每个 POST 都收。SDK 未传入时会生成 uuid v4。24 小时内同键同正文重放第一次的回答 最短 1,最长 255 |
请求正文(必填)(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
sourceApp | string | 是 | 必须是调用的应用;本应用已付款的网关支付单按渠道记时为 channel:wechat / channel:alipay |
sourceRef | string | 是 | 来源记录的 k3:// 引用,例如 k3://membership/package/pk_1 |
kind | string | 是 | purchase、refund、approval… |
direction | string | 是 | 可选值:in、out |
amountCents | integer | 是 | 大于 0,单位分 |
currency | string | 省略为组织的币种;别的币种会被拒绝,不做换算 | |
occurredOn | string | YYYY-MM-DD;省略为组织时区的今天 | |
account | string | 账簿的账户 id,调用方知道时才给 | |
method | string | 用调用方的话说的付款方式(cash wechat alipay card transfer other),账簿据此映射账户 | |
category | string | 分类名(在该方向下找到或建立) | |
party | LedgerParty | ||
party.name | string | 是 | |
party.ref | string | ||
party.kind | string | customer、supplier 或 both(默认:收入记 customer,支出记 supplier) | |
memo | string | ||
bill | LedgerBill | 要一张账单(收入是应收,支出是应付),而不是一笔流水 | |
bill.title | string | ||
bill.dueOn | string | YYYY-MM-DD;省略为没有到期日 | |
reverses | string | 更早的同来源同引用的记账的 kind,本笔是它的冲销。金额须相同,方向相反 | |
settles | string | 开出账单的更早记账的 kind,本笔是对这张账单的付款,至多付到账单还欠的数目 | |
createdBy | string | 记录的所有人(用于数据范围);省略为调用者 | |
ownerUnit | string | 记录的归属部门;省略为调用者的部门 |
响应
| 状态 | 说明 |
|---|---|
| 200 | 已进入发件箱。key 是发件箱键 |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 413 | payload_too_large:正文太大。见 PayloadTooLarge |
| 422 | 字段或参数不被接受(正文读不出来、有未知字段、缺必填、取值越界)。见 Unprocessable |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
200 响应正文(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
key | string | 是 | 发件箱键 |
audit
向企业的审计链写入本应用的操作
POST /audit
向企业的审计链写入本应用的一条操作
需要范围 app.audit:write。English: appends one entry to the tenant's audit chain as the caller.
action 必须以 {本应用 id}. 开头,否则 403 forbidden。成功回答 204,没有正文。
- 认证:
bearer - 范围:
app.audit:write - operationId:
appendAudit
参数
| 名称 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
Idempotency-Key | header | string | 每个 POST 都收。SDK 未传入时会生成 uuid v4。24 小时内同键同正文重放第一次的回答 最短 1,最长 255 |
请求正文(必填)(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
action | string | 是 | 必须以 {本应用 id}. 开头 |
resource | string | 是 | |
diff | any | 任意 JSON,记入审计链 |
响应
| 状态 | 说明 |
|---|---|
| 204 | 已写入。没有正文 |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 413 | payload_too_large:正文太大。见 PayloadTooLarge |
| 422 | 字段或参数不被接受(正文读不出来、有未知字段、缺必填、取值越界)。见 Unprocessable |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
installations
安装了本应用的企业(只收应用自己的令牌)
GET /installations
安装了本应用且已开启的企业
需要范围 app.installations:read。只收应用自己的令牌;页面会话是 403 forbidden。测试凭证的令牌列出装了本应用的测试企业(不论属于哪个开发者组织);正式凭证的令牌只列真实组织。English: the tenants that have the app installed and switched on (the app's own calls only); a test credential's token lists the test enterprises that have the app installed, of any developer organisation, a live one real organisations only.
- 认证:
bearer - 范围:
app.installations:read - operationId:
listInstallations
响应
| 状态 | 说明 |
|---|---|
| 200 | 企业 id |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
200 响应正文(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
tenants | string[] | 是 | 安装了本应用且已开启的企业 id |
services
调用其他应用声明的服务(只收应用自己的令牌)
POST /services/{owner}/{name}/calls
调用另一个应用声明的服务(排队,至少投递一次)
需要范围 app.services:call。只收应用自己的令牌;页面会话是 403 forbidden。English: starts one run of a service another app declares (the call trigger); the platform queues it and delivers it at least once.
owner 是声明服务的应用,name 是服务名。正文 input 是交给服务的 JSON,idempotencyKey 去重:同一个键就是同一次运行。第一次返回 202 且 created 为 true;这个键以前用过则 200,返回当时那次运行。
- 认证:
bearer - 范围:
app.services:call - operationId:
callService
参数
| 名称 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
owner | path | string | 是 | 声明服务的应用 id |
name | path | string | 是 | 服务名 |
Idempotency-Key | header | string | 每个 POST 都收。SDK 未传入时会生成 uuid v4。24 小时内同键同正文重放第一次的回答 最短 1,最长 255 |
请求正文(必填)(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
input | any | 交给服务的 JSON | |
idempotencyKey | string | 去重:同一个键就是同一次运行 |
响应
| 状态 | 说明 |
|---|---|
| 200 | 这个 idempotencyKey 以前用过:这是当时那次运行 |
| 202 | 新建了一次运行 |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 404 | not_found:对应的记录不存在(客户中心没有这个客户,访客、服务或所指的东西不存在)。见 NotFound |
| 413 | payload_too_large:正文太大。见 PayloadTooLarge |
| 422 | 字段或参数不被接受(正文读不出来、有未知字段、缺必填、取值越界)。见 Unprocessable |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
200 响应正文(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
id | string | 是 | 运行的 id |
status | string | 是 | 运行的状态 |
created | boolean | 是 | 这次调用新建了它 |
202 响应正文(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
id | string | 是 | 运行的 id |
status | string | 是 | 运行的状态 |
created | boolean | 是 | 这次调用新建了它 |
events
发出本应用在清单里声明的开放事件
POST /events/emit
发出本应用声明的一个开放事件
需要范围 app.events:emit。English: writes one open event of the app into the platform's outbox and starts its delivery.
type 必须是本应用在清单 events.emits 里声明的事件类型,并以 {本应用 id}. 开头,否则 403 forbidden。key 必填(最多 200 字符):同一个键就是同一个事件。customer 是事件涉及的客户,data 是事件内容。返回 202。
应用之间的事件(opv2 J2 ②):同一个事务里,事件也写进平台的发件箱,送给本租户里装了并开着、在清单 services[] 里声明了触发器 event:{type} 的应用(见 webhook event:{app}.{what}),至少一次,幂等键是 appevt:{本应用 id}:{key}(超过 128 字符时用摘要)。type 同时是平台登记的开放事件、且有 customer 时,才另外送给集成的 webhook。data 最多 16 KiB(JSON),超过返回 422;事件只用 id 指代人和记录,不放手机号、姓名。清单里声明了的类型只由声明它的应用发布:同名的审计动作不再作为事件送给服务。
- 认证:
bearer - 范围:
app.events:emit - operationId:
emitEvent
参数
| 名称 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
Idempotency-Key | header | string | 每个 POST 都收。SDK 未传入时会生成 uuid v4。24 小时内同键同正文重放第一次的回答 最短 1,最长 255 |
请求正文(必填)(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
type | string | 是 | 本应用在清单 events.emits 里声明的事件类型,以 {本应用 id}. 开头 |
key | string | 是 | 必填,最多 200 字符。同一个键就是同一个事件 |
customer | string | 事件涉及的客户 id | |
data | object | 事件内容,最多 16 KiB(JSON);只用 id 指代人和记录 |
响应
| 状态 | 说明 |
|---|---|
| 202 | 已进入发件箱。written 为 false 表示没有写入新事件 |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 413 | payload_too_large:正文太大。见 PayloadTooLarge |
| 422 | 字段或参数不被接受(正文读不出来、有未知字段、缺必填、取值越界)。见 Unprocessable |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
202 响应正文(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
key | string | 是 | 发件箱键 |
written | boolean | 是 | false 表示没有写入新事件 |
links
其他应用的记录链接:搜索与解析
GET /links
按当前人员的权限搜索另一个应用的记录链接
需要范围 app.links:read。English: searches the records of another app as the caller sees them.
app 是要搜的应用;省略时搜这个组织已安装并开启的全部应用(每个应用最多 limit 条,installed 为 true)。q 是文字查询(省略为最近的)。limit 默认 20,1 到 50,超出是 422。指定的应用在这个组织没有安装或没有开启时,installed 为 false 且 items 是 [],选择器可以据此区分“没装”和“没找到”。English: app omitted searches every installed app.
- 认证:
bearer - 范围:
app.links:read - operationId:
searchLinks
参数
| 名称 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
app | query | string | 要搜索其记录的应用 id;省略为全部已安装的应用 | |
q | query | string | 文字查询,省略为最近的 | |
limit | query | integer | 条数,默认 20,最大 50 默认 20最小 1,最大 50 |
响应
| 状态 | 说明 |
|---|---|
| 200 | 链接 |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 422 | 字段或参数不被接受(正文读不出来、有未知字段、缺必填、取值越界)。见 Unprocessable |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
200 响应正文(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
items | Link[] | 是 | |
items[].ref | string | 是 | k3://应用/类型/id |
items[].title | string | 是 | |
items[].kind | string | 是 | 类型的中文名,例如 会员、审批单、文件 |
items[].app | string | 是 | 记录所属的应用 id |
items[].route | string | 在所属应用里打开它的路由 | |
items[].excerpt | string | 文档正文开头约 200 字的纯文本(不含标题)。只有记录是文档的应用才给 | |
items[].doc | boolean | 记录是文档(页面、Word、Excel、PowerPoint 文件) | |
items[].icon | string | 人给记录选的图标(emoji、px:<id>、med:<id>) | |
installed | boolean | 是 | 该应用在这个组织是否已安装并开启 |
GET /links/resolve
解析一个 k3:// 引用:它指向什么,当前人员能不能看到
需要范围 app.links:read。English: what a reference points at and whether the caller may see it.
ref 必填,必须是 k3:// 引用,否则 422。不存在或看不到时 found 为 false,没有 link。
- 认证:
bearer - 范围:
app.links:read - operationId:
resolveLink
参数
| 名称 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
ref | query | string | 是 | k3://应用/类型/id |
响应
| 状态 | 说明 |
|---|---|
| 200 | 解析结果 |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 422 | 字段或参数不被接受(正文读不出来、有未知字段、缺必填、取值越界)。见 Unprocessable |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
200 响应正文(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
found | boolean | 是 | |
link | Link | 另一个应用的一条记录 | |
link.ref | string | 是 | k3://应用/类型/id |
link.title | string | 是 | |
link.kind | string | 是 | 类型的中文名,例如 会员、审批单、文件 |
link.app | string | 是 | 记录所属的应用 id |
link.route | string | 在所属应用里打开它的路由 | |
link.excerpt | string | 文档正文开头约 200 字的纯文本(不含标题)。只有记录是文档的应用才给 | |
link.doc | boolean | 记录是文档(页面、Word、Excel、PowerPoint 文件) | |
link.icon | string | 人给记录选的图标(emoji、px:<id>、med:<id>) |
GET /backlinks
列出提到本应用某条记录的其他应用的记录
需要范围 app.links:read。English: the records of other apps that mention one of the calling app's own records, as the page session's person sees them.
ref 必填,必须是调用应用自己的记录(k3://<应用>/…):不是 k3:// 引用是 422,是别的应用的记录是 403(应用只能问谁提到了自己的记录)。各应用的提供者按当前人员的权限过滤,所以要用页面会话(有人)调用;应用自己的调用没有人,items 是 []。调用应用自己的记录不在其中(应用自己列)。limit 默认 50,1 到 100,超出是 422。English: items exclude the calling app's own records; the app's own token (no person) gets [].
- 认证:
bearer - 范围:
app.links:read - operationId:
listBacklinks
参数
| 名称 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
ref | query | string | 是 | 调用应用自己的记录,k3://应用/类型/id |
limit | query | integer | 条数,默认 50,最大 100 默认 50最小 1,最大 100 |
响应
| 状态 | 说明 |
|---|---|
| 200 | 提到它的记录 |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 422 | 字段或参数不被接受(正文读不出来、有未知字段、缺必填、取值越界)。见 Unprocessable |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
200 响应正文(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
items | Backlink[] | 是 | |
items[].ref | string | 是 | 提到它的记录,k3://应用/类型/id |
items[].app | string | 是 | 记录所属的应用 id |
items[].kind | string | 是 | 类型的中文名,例如 文档、审批单 |
items[].title | string | 是 | |
items[].path | string | 在所属应用里打开它的路径 | |
items[].context | string | 提到处前后的一句话 | |
items[].updatedAt | string(date-time) | 是 |
entitlements
权益服务:模板、发放、预留与核销、退款、转让,以及其他应用声明的 granter
GET /entitlements/templates
列出权益模板
需要范围 app.entitlements:read。English: the tenant's entitlement templates, optionally of one app or only the active ones.
ownerApp 筛归属的应用;activeOnly 为 true 时只留启用的。没有时 data 是 []。
- 认证:
bearer - 范围:
app.entitlements:read - operationId:
listEntitlementTemplates
参数
| 名称 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
ownerApp | query | string | 只要这个应用的模板 | |
activeOnly | query | boolean | 只要启用的 |
响应
| 状态 | 说明 |
|---|---|
| 200 | 模板 |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 422 | 字段或参数不被接受(正文读不出来、有未知字段、缺必填、取值越界)。见 Unprocessable |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
200 响应正文(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
data | EntitlementTemplate[] | 是 | |
data[].id | string | 是 | 模板 id |
data[].ownerApp | string | 是 | 归属的应用 |
data[].kind | string | 是 | 种类 |
data[].name | string | 是 | 名称 |
data[].params | EntitlementParams | 是 | 种类相关的参数(字段名是 snake_case);哪个种类读哪些字段由服务在保存模板时检查 |
data[].params.total_times | integer | 次数(count、count_period) | |
data[].params.valid_days | integer | 有效天数(period、count_period 必填) | |
data[].params.valid_from | string | "grant"(默认)或 "first_use" | |
data[].params.daily_cap | integer | 每日上限(期卡) | |
data[].params.weekly_cap | integer | 每周上限(期卡) | |
data[].params.starts_on | string | 固定有效期开始,YYYY-MM-DD(券;覆盖 valid_days) | |
data[].params.ends_on | string | 固定有效期结束,含当天 | |
data[].params.form | string | 券的形式:cash、percent、service、code | |
data[].params.amount_off_cents | integer | 满减金额(cash) | |
data[].params.percent | integer | 折扣:减多少个百分点,1 到 99(percent) | |
data[].params.threshold_cents | integer | 订单要达到的金额(cash、percent) | |
data[].params.max_off_cents | integer | 最多减多少,0 为不封顶(percent) | |
data[].params.restore_on_refund | boolean | 订单退款时把券还回去(由调用方读到后作废核销单) | |
data[].params.description | string | 奖品说明 | |
data[].params.fulfilment | string | 奖品如何交付(对平台不透明) | |
data[].scope | string[] | 是 | 范围标签 |
data[].transferable | boolean | 是 | 可转让 |
data[].freezable | boolean | 是 | 可冻结 |
data[].maxFreezeDays | integer | 是 | 最多冻结天数 |
data[].active | boolean | 是 | 启用 |
data[].createdAt | string(date-time) | 是 | 建立时间 |
data[].updatedAt | string(date-time) | 是 | 修改时间 |
POST /entitlements/templates
建立一个权益模板(归属永远是调用的应用)
需要范围 app.entitlements:write。English: creates a template owned by the calling app.
ownerApp 可省略;写了别的应用是 403 forbidden。种类(kind)建立后不能改。带请求头 K3-Dry-Run: 1 只预演,什么也不写。
- 认证:
bearer - 范围:
app.entitlements:write - operationId:
createEntitlementTemplate
参数
| 名称 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
K3-Dry-Run | header | string | 传 1 时只预演:回答和真做一样,什么也不留下 可选值: 1 | |
Idempotency-Key | header | string | 每个 POST 都收。SDK 未传入时会生成 uuid v4。24 小时内同键同正文重放第一次的回答 最短 1,最长 255 |
请求正文(必填)(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
ownerApp | string | 可省略;写了就必须是调用的应用 | |
kind | string | 是 | 种类:count、period、count_period、voucher、prize。建立后不能改 |
name | string | 是 | 名称 |
params | EntitlementParams | 种类相关的参数(字段名是 snake_case);哪个种类读哪些字段由服务在保存模板时检查 | |
params.total_times | integer | 次数(count、count_period) | |
params.valid_days | integer | 有效天数(period、count_period 必填) | |
params.valid_from | string | "grant"(默认)或 "first_use" | |
params.daily_cap | integer | 每日上限(期卡) | |
params.weekly_cap | integer | 每周上限(期卡) | |
params.starts_on | string | 固定有效期开始,YYYY-MM-DD(券;覆盖 valid_days) | |
params.ends_on | string | 固定有效期结束,含当天 | |
params.form | string | 券的形式:cash、percent、service、code | |
params.amount_off_cents | integer | 满减金额(cash) | |
params.percent | integer | 折扣:减多少个百分点,1 到 99(percent) | |
params.threshold_cents | integer | 订单要达到的金额(cash、percent) | |
params.max_off_cents | integer | 最多减多少,0 为不封顶(percent) | |
params.restore_on_refund | boolean | 订单退款时把券还回去(由调用方读到后作废核销单) | |
params.description | string | 奖品说明 | |
params.fulfilment | string | 奖品如何交付(对平台不透明) | |
scope | string[] | 范围标签(不透明) | |
transferable | boolean | 可转让 | |
freezable | boolean | 可冻结 | |
maxFreezeDays | integer | 最多冻结天数 | |
active | boolean | 省略:建立时为启用,修改时不变 |
响应
| 状态 | 说明 |
|---|---|
| 201 | 已建立 |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 413 | payload_too_large:正文太大。见 PayloadTooLarge |
| 422 | 服务拒绝,或字段不被接受。见 Refused |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
201 响应正文(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
id | string | 是 | 模板 id |
ownerApp | string | 是 | 归属的应用 |
kind | string | 是 | 种类 |
name | string | 是 | 名称 |
params | EntitlementParams | 是 | 种类相关的参数(字段名是 snake_case);哪个种类读哪些字段由服务在保存模板时检查 |
params.total_times | integer | 次数(count、count_period) | |
params.valid_days | integer | 有效天数(period、count_period 必填) | |
params.valid_from | string | "grant"(默认)或 "first_use" | |
params.daily_cap | integer | 每日上限(期卡) | |
params.weekly_cap | integer | 每周上限(期卡) | |
params.starts_on | string | 固定有效期开始,YYYY-MM-DD(券;覆盖 valid_days) | |
params.ends_on | string | 固定有效期结束,含当天 | |
params.form | string | 券的形式:cash、percent、service、code | |
params.amount_off_cents | integer | 满减金额(cash) | |
params.percent | integer | 折扣:减多少个百分点,1 到 99(percent) | |
params.threshold_cents | integer | 订单要达到的金额(cash、percent) | |
params.max_off_cents | integer | 最多减多少,0 为不封顶(percent) | |
params.restore_on_refund | boolean | 订单退款时把券还回去(由调用方读到后作废核销单) | |
params.description | string | 奖品说明 | |
params.fulfilment | string | 奖品如何交付(对平台不透明) | |
scope | string[] | 是 | 范围标签 |
transferable | boolean | 是 | 可转让 |
freezable | boolean | 是 | 可冻结 |
maxFreezeDays | integer | 是 | 最多冻结天数 |
active | boolean | 是 | 启用 |
createdAt | string(date-time) | 是 | 建立时间 |
updatedAt | string(date-time) | 是 | 修改时间 |
GET /entitlements/templates/{id}
读一个权益模板
需要范围 app.entitlements:read。English: one template of the tenant.
- 认证:
bearer - 范围:
app.entitlements:read - operationId:
getEntitlementTemplate
参数
| 名称 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
id | path | string | 是 | id |
响应
| 状态 | 说明 |
|---|---|
| 200 | 模板 |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 404 | not_found:对应的记录不存在(客户中心没有这个客户,访客、服务或所指的东西不存在)。见 NotFound |
| 422 | 服务拒绝,或字段不被接受。见 Refused |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
200 响应正文(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
id | string | 是 | 模板 id |
ownerApp | string | 是 | 归属的应用 |
kind | string | 是 | 种类 |
name | string | 是 | 名称 |
params | EntitlementParams | 是 | 种类相关的参数(字段名是 snake_case);哪个种类读哪些字段由服务在保存模板时检查 |
params.total_times | integer | 次数(count、count_period) | |
params.valid_days | integer | 有效天数(period、count_period 必填) | |
params.valid_from | string | "grant"(默认)或 "first_use" | |
params.daily_cap | integer | 每日上限(期卡) | |
params.weekly_cap | integer | 每周上限(期卡) | |
params.starts_on | string | 固定有效期开始,YYYY-MM-DD(券;覆盖 valid_days) | |
params.ends_on | string | 固定有效期结束,含当天 | |
params.form | string | 券的形式:cash、percent、service、code | |
params.amount_off_cents | integer | 满减金额(cash) | |
params.percent | integer | 折扣:减多少个百分点,1 到 99(percent) | |
params.threshold_cents | integer | 订单要达到的金额(cash、percent) | |
params.max_off_cents | integer | 最多减多少,0 为不封顶(percent) | |
params.restore_on_refund | boolean | 订单退款时把券还回去(由调用方读到后作废核销单) | |
params.description | string | 奖品说明 | |
params.fulfilment | string | 奖品如何交付(对平台不透明) | |
scope | string[] | 是 | 范围标签 |
transferable | boolean | 是 | 可转让 |
freezable | boolean | 是 | 可冻结 |
maxFreezeDays | integer | 是 | 最多冻结天数 |
active | boolean | 是 | 启用 |
createdAt | string(date-time) | 是 | 建立时间 |
updatedAt | string(date-time) | 是 | 修改时间 |
PUT /entitlements/templates/{id}
修改本应用的权益模板
需要范围 app.entitlements:write。English: changes a template of the calling app.
已发出的权益不受影响(权益是发放时的副本)。别的应用的模板是 403 forbidden。种类建立后不能改。带 K3-Dry-Run: 1 只预演。
- 认证:
bearer - 范围:
app.entitlements:write - operationId:
updateEntitlementTemplate
参数
| 名称 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
id | path | string | 是 | id |
K3-Dry-Run | header | string | 传 1 时只预演:回答和真做一样,什么也不留下 可选值: 1 |
请求正文(必填)(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
ownerApp | string | 可省略;写了就必须是调用的应用 | |
kind | string | 是 | 种类:count、period、count_period、voucher、prize。建立后不能改 |
name | string | 是 | 名称 |
params | EntitlementParams | 种类相关的参数(字段名是 snake_case);哪个种类读哪些字段由服务在保存模板时检查 | |
params.total_times | integer | 次数(count、count_period) | |
params.valid_days | integer | 有效天数(period、count_period 必填) | |
params.valid_from | string | "grant"(默认)或 "first_use" | |
params.daily_cap | integer | 每日上限(期卡) | |
params.weekly_cap | integer | 每周上限(期卡) | |
params.starts_on | string | 固定有效期开始,YYYY-MM-DD(券;覆盖 valid_days) | |
params.ends_on | string | 固定有效期结束,含当天 | |
params.form | string | 券的形式:cash、percent、service、code | |
params.amount_off_cents | integer | 满减金额(cash) | |
params.percent | integer | 折扣:减多少个百分点,1 到 99(percent) | |
params.threshold_cents | integer | 订单要达到的金额(cash、percent) | |
params.max_off_cents | integer | 最多减多少,0 为不封顶(percent) | |
params.restore_on_refund | boolean | 订单退款时把券还回去(由调用方读到后作废核销单) | |
params.description | string | 奖品说明 | |
params.fulfilment | string | 奖品如何交付(对平台不透明) | |
scope | string[] | 范围标签(不透明) | |
transferable | boolean | 可转让 | |
freezable | boolean | 可冻结 | |
maxFreezeDays | integer | 最多冻结天数 | |
active | boolean | 省略:建立时为启用,修改时不变 |
响应
| 状态 | 说明 |
|---|---|
| 200 | 修改后的模板 |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 404 | not_found:对应的记录不存在(客户中心没有这个客户,访客、服务或所指的东西不存在)。见 NotFound |
| 413 | payload_too_large:正文太大。见 PayloadTooLarge |
| 422 | 服务拒绝,或字段不被接受。见 Refused |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
200 响应正文(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
id | string | 是 | 模板 id |
ownerApp | string | 是 | 归属的应用 |
kind | string | 是 | 种类 |
name | string | 是 | 名称 |
params | EntitlementParams | 是 | 种类相关的参数(字段名是 snake_case);哪个种类读哪些字段由服务在保存模板时检查 |
params.total_times | integer | 次数(count、count_period) | |
params.valid_days | integer | 有效天数(period、count_period 必填) | |
params.valid_from | string | "grant"(默认)或 "first_use" | |
params.daily_cap | integer | 每日上限(期卡) | |
params.weekly_cap | integer | 每周上限(期卡) | |
params.starts_on | string | 固定有效期开始,YYYY-MM-DD(券;覆盖 valid_days) | |
params.ends_on | string | 固定有效期结束,含当天 | |
params.form | string | 券的形式:cash、percent、service、code | |
params.amount_off_cents | integer | 满减金额(cash) | |
params.percent | integer | 折扣:减多少个百分点,1 到 99(percent) | |
params.threshold_cents | integer | 订单要达到的金额(cash、percent) | |
params.max_off_cents | integer | 最多减多少,0 为不封顶(percent) | |
params.restore_on_refund | boolean | 订单退款时把券还回去(由调用方读到后作废核销单) | |
params.description | string | 奖品说明 | |
params.fulfilment | string | 奖品如何交付(对平台不透明) | |
scope | string[] | 是 | 范围标签 |
transferable | boolean | 是 | 可转让 |
freezable | boolean | 是 | 可冻结 |
maxFreezeDays | integer | 是 | 最多冻结天数 |
active | boolean | 是 | 启用 |
createdAt | string(date-time) | 是 | 建立时间 |
updatedAt | string(date-time) | 是 | 修改时间 |
GET /entitlements/grants
列出一位客户的权益(新的在前)
需要范围 app.entitlements:read。English: a holder's grants, newest first.
holder 必填。status 可选:active、not_started、frozen、expired、used_up、used、refunded、voided、transferred(按今天计算)。正文是 {data: [...]},不分页。
- 认证:
bearer - 范围:
app.entitlements:read - operationId:
listEntitlementGrants
参数
| 名称 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
holder | query | string | 是 | 客户 id(cu_…) |
status | query | string | 只要这个状态的权益 |
响应
| 状态 | 说明 |
|---|---|
| 200 | 权益 |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 422 | 服务拒绝,或字段不被接受。见 Refused |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
200 响应正文(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
data | EntitlementGrant[] | 是 | |
data[].id | string | 是 | 权益 id |
data[].template | string | 是 | 来源模板 id |
data[].ownerApp | string | 是 | 模板归属的应用 |
data[].kind | string | 是 | 种类 |
data[].name | string | 是 | 名称 |
data[].params | EntitlementParams | 是 | 种类相关的参数(字段名是 snake_case);哪个种类读哪些字段由服务在保存模板时检查 |
data[].params.total_times | integer | 次数(count、count_period) | |
data[].params.valid_days | integer | 有效天数(period、count_period 必填) | |
data[].params.valid_from | string | "grant"(默认)或 "first_use" | |
data[].params.daily_cap | integer | 每日上限(期卡) | |
data[].params.weekly_cap | integer | 每周上限(期卡) | |
data[].params.starts_on | string | 固定有效期开始,YYYY-MM-DD(券;覆盖 valid_days) | |
data[].params.ends_on | string | 固定有效期结束,含当天 | |
data[].params.form | string | 券的形式:cash、percent、service、code | |
data[].params.amount_off_cents | integer | 满减金额(cash) | |
data[].params.percent | integer | 折扣:减多少个百分点,1 到 99(percent) | |
data[].params.threshold_cents | integer | 订单要达到的金额(cash、percent) | |
data[].params.max_off_cents | integer | 最多减多少,0 为不封顶(percent) | |
data[].params.restore_on_refund | boolean | 订单退款时把券还回去(由调用方读到后作废核销单) | |
data[].params.description | string | 奖品说明 | |
data[].params.fulfilment | string | 奖品如何交付(对平台不透明) | |
data[].scope | string[] | 是 | 范围标签 |
data[].transferable | boolean | 是 | 可转让 |
data[].freezable | boolean | 是 | 可冻结 |
data[].maxFreezeDays | integer | 是 | 最多冻结天数 |
data[].holder | string | 是 | 持有的客户 id |
data[].total | integer | 是 | 总次数 |
data[].remaining | integer | 是 | 剩余次数 |
data[].startsOn | string | 是 | 开始日期 |
data[].endsOn | string | 是 | 结束日期 |
data[].state | string | 是 | 对它做过什么 |
data[].status | string | 是 | 对人说的状态:active、not_started、frozen、expired、used_up、used、refunded、voided、transferred(按今天算) |
data[].frozenFrom | string | 冻结开始 | |
data[].frozenUntil | string | 冻结到 | |
data[].frozenDaysUsed | integer | 是 | 已冻结天数 |
data[].source | string | 是 | 来源 |
data[].paidCents | integer | 是 | 付款 |
data[].refundedCents | integer | 是 | 已退 |
data[].origin | string | k3:// 引用 | |
data[].attribution | object | 归因 | |
data[].code | string | 券码 | |
data[].transferredFrom | string | 转让自哪一项 | |
data[].held | EntitlementHold | 一个未支付订单对权益的占用 | |
data[].held.id | string | 是 | 占用 id |
data[].held.grant | string | 是 | 权益 id |
data[].held.ref | string | 是 | 占用它的订单 |
data[].held.expiresAt | string(date-time) | 是 | 占用到何时 |
data[].createdBy | string | 是 | 发放者 |
data[].createdAt | string(date-time) | 是 | 发放时间 |
data[].ledger | EntitlementLedgerEntry[] | 只在读单项权益时有 | |
data[].ledger[].id | integer | 是 | 流水 id |
data[].ledger[].kind | string | 是 | 变动的种类 |
data[].ledger[].delta | integer | 是 | 次数的增减 |
data[].ledger[].balance | integer | 是 | 变动后的余额 |
data[].ledger[].actorName | string | 是 | 谁做的 |
data[].ledger[].reason | string | 是 | 原因 |
data[].ledger[].ref | string | 关联的订单或预约 | |
data[].ledger[].redemptionId | string | 关联的核销单 | |
data[].ledger[].at | string(date-time) | 是 | 时间 |
POST /entitlements/grants
按本应用的模板向客户发放权益(同一个 key 只发一次)
需要范围 app.entitlements:write。English: issues count grants of one of the app's own templates to a customer, once per key.
key 在正文里;正文没写时用请求头 Idempotency-Key。同键重来返回 200 且 replay 为 true,不再发放;新发放返回 201。模板不是本应用的是 403 forbidden。count 为 1 到 1000,默认 1;code 只用于 count 为 1 的券或奖品。
- 认证:
bearer - 范围:
app.entitlements:write - operationId:
grantEntitlement
参数
| 名称 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
K3-Dry-Run | header | string | 传 1 时只预演:回答和真做一样,什么也不留下 可选值: 1 | |
Idempotency-Key | header | string | 每个 POST 都收。SDK 未传入时会生成 uuid v4。24 小时内同键同正文重放第一次的回答 最短 1,最长 255 |
请求正文(必填)(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
key | string | 幂等键(“来源应用:来源引用:种类”);省略时用请求头 Idempotency-Key | |
template | string | 是 | 模板 id(必须是本应用的) |
holder | string | 是 | 持有的客户 id(cu_…) |
source | string | 来源:purchase、gift、claim、draw、import、transfer。默认 purchase(付款为 0 且没写时为 gift) | |
origin | string | k3:// 引用:谁发的、为什么 | |
paidCents | integer | 持有人为每一项付的金额 | |
attribution | object | 来源归因 | |
count | integer | 发几项,1 到 1000,默认 1 最小 1,最大 1000 | |
code | string | 给这一项用的券码,而不是生成的;只在 count 为 1 的券或奖品,租户内唯一 |
响应
| 状态 | 说明 |
|---|---|
| 200 | 同一个 key 已发放过:这是当时的权益(replay 为 true) |
| 201 | 已发放 |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 404 | not_found:对应的记录不存在(客户中心没有这个客户,访客、服务或所指的东西不存在)。见 NotFound |
| 413 | payload_too_large:正文太大。见 PayloadTooLarge |
| 422 | 服务拒绝,或字段不被接受。见 Refused |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
200 响应正文(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
grants | EntitlementGrant[] | 是 | |
grants[].id | string | 是 | 权益 id |
grants[].template | string | 是 | 来源模板 id |
grants[].ownerApp | string | 是 | 模板归属的应用 |
grants[].kind | string | 是 | 种类 |
grants[].name | string | 是 | 名称 |
grants[].params | EntitlementParams | 是 | 种类相关的参数(字段名是 snake_case);哪个种类读哪些字段由服务在保存模板时检查 |
grants[].params.total_times | integer | 次数(count、count_period) | |
grants[].params.valid_days | integer | 有效天数(period、count_period 必填) | |
grants[].params.valid_from | string | "grant"(默认)或 "first_use" | |
grants[].params.daily_cap | integer | 每日上限(期卡) | |
grants[].params.weekly_cap | integer | 每周上限(期卡) | |
grants[].params.starts_on | string | 固定有效期开始,YYYY-MM-DD(券;覆盖 valid_days) | |
grants[].params.ends_on | string | 固定有效期结束,含当天 | |
grants[].params.form | string | 券的形式:cash、percent、service、code | |
grants[].params.amount_off_cents | integer | 满减金额(cash) | |
grants[].params.percent | integer | 折扣:减多少个百分点,1 到 99(percent) | |
grants[].params.threshold_cents | integer | 订单要达到的金额(cash、percent) | |
grants[].params.max_off_cents | integer | 最多减多少,0 为不封顶(percent) | |
grants[].params.restore_on_refund | boolean | 订单退款时把券还回去(由调用方读到后作废核销单) | |
grants[].params.description | string | 奖品说明 | |
grants[].params.fulfilment | string | 奖品如何交付(对平台不透明) | |
grants[].scope | string[] | 是 | 范围标签 |
grants[].transferable | boolean | 是 | 可转让 |
grants[].freezable | boolean | 是 | 可冻结 |
grants[].maxFreezeDays | integer | 是 | 最多冻结天数 |
grants[].holder | string | 是 | 持有的客户 id |
grants[].total | integer | 是 | 总次数 |
grants[].remaining | integer | 是 | 剩余次数 |
grants[].startsOn | string | 是 | 开始日期 |
grants[].endsOn | string | 是 | 结束日期 |
grants[].state | string | 是 | 对它做过什么 |
grants[].status | string | 是 | 对人说的状态:active、not_started、frozen、expired、used_up、used、refunded、voided、transferred(按今天算) |
grants[].frozenFrom | string | 冻结开始 | |
grants[].frozenUntil | string | 冻结到 | |
grants[].frozenDaysUsed | integer | 是 | 已冻结天数 |
grants[].source | string | 是 | 来源 |
grants[].paidCents | integer | 是 | 付款 |
grants[].refundedCents | integer | 是 | 已退 |
grants[].origin | string | k3:// 引用 | |
grants[].attribution | object | 归因 | |
grants[].code | string | 券码 | |
grants[].transferredFrom | string | 转让自哪一项 | |
grants[].held | EntitlementHold | 一个未支付订单对权益的占用 | |
grants[].held.id | string | 是 | 占用 id |
grants[].held.grant | string | 是 | 权益 id |
grants[].held.ref | string | 是 | 占用它的订单 |
grants[].held.expiresAt | string(date-time) | 是 | 占用到何时 |
grants[].createdBy | string | 是 | 发放者 |
grants[].createdAt | string(date-time) | 是 | 发放时间 |
grants[].ledger | EntitlementLedgerEntry[] | 只在读单项权益时有 | |
grants[].ledger[].id | integer | 是 | 流水 id |
grants[].ledger[].kind | string | 是 | 变动的种类 |
grants[].ledger[].delta | integer | 是 | 次数的增减 |
grants[].ledger[].balance | integer | 是 | 变动后的余额 |
grants[].ledger[].actorName | string | 是 | 谁做的 |
grants[].ledger[].reason | string | 是 | 原因 |
grants[].ledger[].ref | string | 关联的订单或预约 | |
grants[].ledger[].redemptionId | string | 关联的核销单 | |
grants[].ledger[].at | string(date-time) | 是 | 时间 |
replay | boolean | 是 | 同一个 key 已发放过,这是当时的权益 |
201 响应正文(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
grants | EntitlementGrant[] | 是 | |
grants[].id | string | 是 | 权益 id |
grants[].template | string | 是 | 来源模板 id |
grants[].ownerApp | string | 是 | 模板归属的应用 |
grants[].kind | string | 是 | 种类 |
grants[].name | string | 是 | 名称 |
grants[].params | EntitlementParams | 是 | 种类相关的参数(字段名是 snake_case);哪个种类读哪些字段由服务在保存模板时检查 |
grants[].params.total_times | integer | 次数(count、count_period) | |
grants[].params.valid_days | integer | 有效天数(period、count_period 必填) | |
grants[].params.valid_from | string | "grant"(默认)或 "first_use" | |
grants[].params.daily_cap | integer | 每日上限(期卡) | |
grants[].params.weekly_cap | integer | 每周上限(期卡) | |
grants[].params.starts_on | string | 固定有效期开始,YYYY-MM-DD(券;覆盖 valid_days) | |
grants[].params.ends_on | string | 固定有效期结束,含当天 | |
grants[].params.form | string | 券的形式:cash、percent、service、code | |
grants[].params.amount_off_cents | integer | 满减金额(cash) | |
grants[].params.percent | integer | 折扣:减多少个百分点,1 到 99(percent) | |
grants[].params.threshold_cents | integer | 订单要达到的金额(cash、percent) | |
grants[].params.max_off_cents | integer | 最多减多少,0 为不封顶(percent) | |
grants[].params.restore_on_refund | boolean | 订单退款时把券还回去(由调用方读到后作废核销单) | |
grants[].params.description | string | 奖品说明 | |
grants[].params.fulfilment | string | 奖品如何交付(对平台不透明) | |
grants[].scope | string[] | 是 | 范围标签 |
grants[].transferable | boolean | 是 | 可转让 |
grants[].freezable | boolean | 是 | 可冻结 |
grants[].maxFreezeDays | integer | 是 | 最多冻结天数 |
grants[].holder | string | 是 | 持有的客户 id |
grants[].total | integer | 是 | 总次数 |
grants[].remaining | integer | 是 | 剩余次数 |
grants[].startsOn | string | 是 | 开始日期 |
grants[].endsOn | string | 是 | 结束日期 |
grants[].state | string | 是 | 对它做过什么 |
grants[].status | string | 是 | 对人说的状态:active、not_started、frozen、expired、used_up、used、refunded、voided、transferred(按今天算) |
grants[].frozenFrom | string | 冻结开始 | |
grants[].frozenUntil | string | 冻结到 | |
grants[].frozenDaysUsed | integer | 是 | 已冻结天数 |
grants[].source | string | 是 | 来源 |
grants[].paidCents | integer | 是 | 付款 |
grants[].refundedCents | integer | 是 | 已退 |
grants[].origin | string | k3:// 引用 | |
grants[].attribution | object | 归因 | |
grants[].code | string | 券码 | |
grants[].transferredFrom | string | 转让自哪一项 | |
grants[].held | EntitlementHold | 一个未支付订单对权益的占用 | |
grants[].held.id | string | 是 | 占用 id |
grants[].held.grant | string | 是 | 权益 id |
grants[].held.ref | string | 是 | 占用它的订单 |
grants[].held.expiresAt | string(date-time) | 是 | 占用到何时 |
grants[].createdBy | string | 是 | 发放者 |
grants[].createdAt | string(date-time) | 是 | 发放时间 |
grants[].ledger | EntitlementLedgerEntry[] | 只在读单项权益时有 | |
grants[].ledger[].id | integer | 是 | 流水 id |
grants[].ledger[].kind | string | 是 | 变动的种类 |
grants[].ledger[].delta | integer | 是 | 次数的增减 |
grants[].ledger[].balance | integer | 是 | 变动后的余额 |
grants[].ledger[].actorName | string | 是 | 谁做的 |
grants[].ledger[].reason | string | 是 | 原因 |
grants[].ledger[].ref | string | 关联的订单或预约 | |
grants[].ledger[].redemptionId | string | 关联的核销单 | |
grants[].ledger[].at | string(date-time) | 是 | 时间 |
replay | boolean | 是 | 同一个 key 已发放过,这是当时的权益 |
GET /entitlements/grants/{id}
读一项权益和它的流水
需要范围 app.entitlements:read。English: one grant with its ledger.
- 认证:
bearer - 范围:
app.entitlements:read - operationId:
getEntitlementGrant
参数
| 名称 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
id | path | string | 是 | id |
响应
| 状态 | 说明 |
|---|---|
| 200 | 权益,带 ledger |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 404 | not_found:对应的记录不存在(客户中心没有这个客户,访客、服务或所指的东西不存在)。见 NotFound |
| 422 | 服务拒绝,或字段不被接受。见 Refused |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
200 响应正文(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
id | string | 是 | 权益 id |
template | string | 是 | 来源模板 id |
ownerApp | string | 是 | 模板归属的应用 |
kind | string | 是 | 种类 |
name | string | 是 | 名称 |
params | EntitlementParams | 是 | 种类相关的参数(字段名是 snake_case);哪个种类读哪些字段由服务在保存模板时检查 |
params.total_times | integer | 次数(count、count_period) | |
params.valid_days | integer | 有效天数(period、count_period 必填) | |
params.valid_from | string | "grant"(默认)或 "first_use" | |
params.daily_cap | integer | 每日上限(期卡) | |
params.weekly_cap | integer | 每周上限(期卡) | |
params.starts_on | string | 固定有效期开始,YYYY-MM-DD(券;覆盖 valid_days) | |
params.ends_on | string | 固定有效期结束,含当天 | |
params.form | string | 券的形式:cash、percent、service、code | |
params.amount_off_cents | integer | 满减金额(cash) | |
params.percent | integer | 折扣:减多少个百分点,1 到 99(percent) | |
params.threshold_cents | integer | 订单要达到的金额(cash、percent) | |
params.max_off_cents | integer | 最多减多少,0 为不封顶(percent) | |
params.restore_on_refund | boolean | 订单退款时把券还回去(由调用方读到后作废核销单) | |
params.description | string | 奖品说明 | |
params.fulfilment | string | 奖品如何交付(对平台不透明) | |
scope | string[] | 是 | 范围标签 |
transferable | boolean | 是 | 可转让 |
freezable | boolean | 是 | 可冻结 |
maxFreezeDays | integer | 是 | 最多冻结天数 |
holder | string | 是 | 持有的客户 id |
total | integer | 是 | 总次数 |
remaining | integer | 是 | 剩余次数 |
startsOn | string | 是 | 开始日期 |
endsOn | string | 是 | 结束日期 |
state | string | 是 | 对它做过什么 |
status | string | 是 | 对人说的状态:active、not_started、frozen、expired、used_up、used、refunded、voided、transferred(按今天算) |
frozenFrom | string | 冻结开始 | |
frozenUntil | string | 冻结到 | |
frozenDaysUsed | integer | 是 | 已冻结天数 |
source | string | 是 | 来源 |
paidCents | integer | 是 | 付款 |
refundedCents | integer | 是 | 已退 |
origin | string | k3:// 引用 | |
attribution | object | 归因 | |
code | string | 券码 | |
transferredFrom | string | 转让自哪一项 | |
held | EntitlementHold | 一个未支付订单对权益的占用 | |
held.id | string | 是 | 占用 id |
held.grant | string | 是 | 权益 id |
held.ref | string | 是 | 占用它的订单 |
held.expiresAt | string(date-time) | 是 | 占用到何时 |
createdBy | string | 是 | 发放者 |
createdAt | string(date-time) | 是 | 发放时间 |
ledger | EntitlementLedgerEntry[] | 只在读单项权益时有 | |
ledger[].id | integer | 是 | 流水 id |
ledger[].kind | string | 是 | 变动的种类 |
ledger[].delta | integer | 是 | 次数的增减 |
ledger[].balance | integer | 是 | 变动后的余额 |
ledger[].actorName | string | 是 | 谁做的 |
ledger[].reason | string | 是 | 原因 |
ledger[].ref | string | 关联的订单或预约 | |
ledger[].redemptionId | string | 关联的核销单 | |
ledger[].at | string(date-time) | 是 | 时间 |
POST /entitlements/grants/{id}/refund
退本应用发出的一项权益
需要范围 app.entitlements:write。English: ends a grant of the app's own template and answers the amount to give back.
mode 省略或 times:按剩余次数的份额;amount:按 amountCents,不超过还没退的付款。reason 必填。路径里的 id 优先于正文里的 grant。别的应用的权益是 403 forbidden。服务不动钱,钱由调用方退。
- 认证:
bearer - 范围:
app.entitlements:write - operationId:
refundEntitlement
参数
| 名称 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
id | path | string | 是 | id |
K3-Dry-Run | header | string | 传 1 时只预演:回答和真做一样,什么也不留下 可选值: 1 | |
Idempotency-Key | header | string | 每个 POST 都收。SDK 未传入时会生成 uuid v4。24 小时内同键同正文重放第一次的回答 最短 1,最长 255 |
请求正文(必填)(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
mode | string | 省略或 times:按剩余次数的份额;amount:按 amountCents 可选值: times、amount | |
amountCents | integer | mode 为 amount 时的退款金额 | |
reason | string | 是 | 原因(必填) |
grant | string | 被路径里的 id 取代,可省略 |
响应
| 状态 | 说明 |
|---|---|
| 200 | 退款结果 |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 404 | not_found:对应的记录不存在(客户中心没有这个客户,访客、服务或所指的东西不存在)。见 NotFound |
| 409 | 见 Conflict |
| 413 | payload_too_large:正文太大。见 PayloadTooLarge |
| 422 | 服务拒绝,或字段不被接受。见 Refused |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
200 响应正文(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
amountCents | integer | 是 | 退回的金额(服务不动钱,由调用方退) |
grant | EntitlementGrant | 是 | 一项权益 |
grant.id | string | 是 | 权益 id |
grant.template | string | 是 | 来源模板 id |
grant.ownerApp | string | 是 | 模板归属的应用 |
grant.kind | string | 是 | 种类 |
grant.name | string | 是 | 名称 |
grant.params | EntitlementParams | 是 | 种类相关的参数(字段名是 snake_case);哪个种类读哪些字段由服务在保存模板时检查 |
grant.params.total_times | integer | 次数(count、count_period) | |
grant.params.valid_days | integer | 有效天数(period、count_period 必填) | |
grant.params.valid_from | string | "grant"(默认)或 "first_use" | |
grant.params.daily_cap | integer | 每日上限(期卡) | |
grant.params.weekly_cap | integer | 每周上限(期卡) | |
grant.params.starts_on | string | 固定有效期开始,YYYY-MM-DD(券;覆盖 valid_days) | |
grant.params.ends_on | string | 固定有效期结束,含当天 | |
grant.params.form | string | 券的形式:cash、percent、service、code | |
grant.params.amount_off_cents | integer | 满减金额(cash) | |
grant.params.percent | integer | 折扣:减多少个百分点,1 到 99(percent) | |
grant.params.threshold_cents | integer | 订单要达到的金额(cash、percent) | |
grant.params.max_off_cents | integer | 最多减多少,0 为不封顶(percent) | |
grant.params.restore_on_refund | boolean | 订单退款时把券还回去(由调用方读到后作废核销单) | |
grant.params.description | string | 奖品说明 | |
grant.params.fulfilment | string | 奖品如何交付(对平台不透明) | |
grant.scope | string[] | 是 | 范围标签 |
grant.transferable | boolean | 是 | 可转让 |
grant.freezable | boolean | 是 | 可冻结 |
grant.maxFreezeDays | integer | 是 | 最多冻结天数 |
grant.holder | string | 是 | 持有的客户 id |
grant.total | integer | 是 | 总次数 |
grant.remaining | integer | 是 | 剩余次数 |
grant.startsOn | string | 是 | 开始日期 |
grant.endsOn | string | 是 | 结束日期 |
grant.state | string | 是 | 对它做过什么 |
grant.status | string | 是 | 对人说的状态:active、not_started、frozen、expired、used_up、used、refunded、voided、transferred(按今天算) |
grant.frozenFrom | string | 冻结开始 | |
grant.frozenUntil | string | 冻结到 | |
grant.frozenDaysUsed | integer | 是 | 已冻结天数 |
grant.source | string | 是 | 来源 |
grant.paidCents | integer | 是 | 付款 |
grant.refundedCents | integer | 是 | 已退 |
grant.origin | string | k3:// 引用 | |
grant.attribution | object | 归因 | |
grant.code | string | 券码 | |
grant.transferredFrom | string | 转让自哪一项 | |
grant.held | EntitlementHold | 一个未支付订单对权益的占用 | |
grant.held.id | string | 是 | 占用 id |
grant.held.grant | string | 是 | 权益 id |
grant.held.ref | string | 是 | 占用它的订单 |
grant.held.expiresAt | string(date-time) | 是 | 占用到何时 |
grant.createdBy | string | 是 | 发放者 |
grant.createdAt | string(date-time) | 是 | 发放时间 |
grant.ledger | EntitlementLedgerEntry[] | 只在读单项权益时有 | |
grant.ledger[].id | integer | 是 | 流水 id |
grant.ledger[].kind | string | 是 | 变动的种类 |
grant.ledger[].delta | integer | 是 | 次数的增减 |
grant.ledger[].balance | integer | 是 | 变动后的余额 |
grant.ledger[].actorName | string | 是 | 谁做的 |
grant.ledger[].reason | string | 是 | 原因 |
grant.ledger[].ref | string | 关联的订单或预约 | |
grant.ledger[].redemptionId | string | 关联的核销单 | |
grant.ledger[].at | string(date-time) | 是 | 时间 |
POST /entitlements/stores/relink
把本应用权益里的旧门店 id 换成组织里的门店
需要范围 app.entitlements:write。English: rewrites a legacy store id to the organisation's store in the templates and grants the calling app owns, and in the redemptions of those grants.
scope 里的 store:<from> 换成 store:<to>,这些权益的核销记录的地点 from 换成 to。只动调用应用自己发出的模板与权益(所有者由平台按调用方定,正文不能指定)。重复调用不再改变任何东西。活动关联旧门店记录时用它(ADR-0057)。
- 认证:
bearer - 范围:
app.entitlements:write - operationId:
relinkEntitlementStore
参数
| 名称 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
K3-Dry-Run | header | string | 传 1 时只预演:回答和真做一样,什么也不留下 可选值: 1 | |
Idempotency-Key | header | string | 每个 POST 都收。SDK 未传入时会生成 uuid v4。24 小时内同键同正文重放第一次的回答 最短 1,最长 255 |
请求正文(必填)(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
from | string | 是 | 旧门店 id(应用自己的旧记录) 最长 100 |
to | string | 是 | 组织里的门店(部门 id) 最长 100 |
响应
| 状态 | 说明 |
|---|---|
| 204 | 已改写。没有正文 |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 413 | payload_too_large:正文太大。见 PayloadTooLarge |
| 422 | 服务拒绝,或字段不被接受。见 Refused |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
POST /entitlements/grants/{id}/transfer
把本应用发出的一项权益转给另一位客户
需要范围 app.entitlements:write。English: gives what is left of a grant to another holder.
原权益结束,生成一项条款相同的新权益并返回。不能转让时是 422,说明原因。别的应用的权益是 403 forbidden。
- 认证:
bearer - 范围:
app.entitlements:write - operationId:
transferEntitlement
参数
| 名称 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
id | path | string | 是 | id |
K3-Dry-Run | header | string | 传 1 时只预演:回答和真做一样,什么也不留下 可选值: 1 | |
Idempotency-Key | header | string | 每个 POST 都收。SDK 未传入时会生成 uuid v4。24 小时内同键同正文重放第一次的回答 最短 1,最长 255 |
请求正文(必填)(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
to | string | 是 | 接收的客户 id |
reason | string | 原因 | |
grant | string | 被路径里的 id 取代,可省略 |
响应
| 状态 | 说明 |
|---|---|
| 200 | 新的权益 |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 404 | not_found:对应的记录不存在(客户中心没有这个客户,访客、服务或所指的东西不存在)。见 NotFound |
| 409 | 见 Conflict |
| 413 | payload_too_large:正文太大。见 PayloadTooLarge |
| 422 | 服务拒绝,或字段不被接受。见 Refused |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
200 响应正文(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
id | string | 是 | 权益 id |
template | string | 是 | 来源模板 id |
ownerApp | string | 是 | 模板归属的应用 |
kind | string | 是 | 种类 |
name | string | 是 | 名称 |
params | EntitlementParams | 是 | 种类相关的参数(字段名是 snake_case);哪个种类读哪些字段由服务在保存模板时检查 |
params.total_times | integer | 次数(count、count_period) | |
params.valid_days | integer | 有效天数(period、count_period 必填) | |
params.valid_from | string | "grant"(默认)或 "first_use" | |
params.daily_cap | integer | 每日上限(期卡) | |
params.weekly_cap | integer | 每周上限(期卡) | |
params.starts_on | string | 固定有效期开始,YYYY-MM-DD(券;覆盖 valid_days) | |
params.ends_on | string | 固定有效期结束,含当天 | |
params.form | string | 券的形式:cash、percent、service、code | |
params.amount_off_cents | integer | 满减金额(cash) | |
params.percent | integer | 折扣:减多少个百分点,1 到 99(percent) | |
params.threshold_cents | integer | 订单要达到的金额(cash、percent) | |
params.max_off_cents | integer | 最多减多少,0 为不封顶(percent) | |
params.restore_on_refund | boolean | 订单退款时把券还回去(由调用方读到后作废核销单) | |
params.description | string | 奖品说明 | |
params.fulfilment | string | 奖品如何交付(对平台不透明) | |
scope | string[] | 是 | 范围标签 |
transferable | boolean | 是 | 可转让 |
freezable | boolean | 是 | 可冻结 |
maxFreezeDays | integer | 是 | 最多冻结天数 |
holder | string | 是 | 持有的客户 id |
total | integer | 是 | 总次数 |
remaining | integer | 是 | 剩余次数 |
startsOn | string | 是 | 开始日期 |
endsOn | string | 是 | 结束日期 |
state | string | 是 | 对它做过什么 |
status | string | 是 | 对人说的状态:active、not_started、frozen、expired、used_up、used、refunded、voided、transferred(按今天算) |
frozenFrom | string | 冻结开始 | |
frozenUntil | string | 冻结到 | |
frozenDaysUsed | integer | 是 | 已冻结天数 |
source | string | 是 | 来源 |
paidCents | integer | 是 | 付款 |
refundedCents | integer | 是 | 已退 |
origin | string | k3:// 引用 | |
attribution | object | 归因 | |
code | string | 券码 | |
transferredFrom | string | 转让自哪一项 | |
held | EntitlementHold | 一个未支付订单对权益的占用 | |
held.id | string | 是 | 占用 id |
held.grant | string | 是 | 权益 id |
held.ref | string | 是 | 占用它的订单 |
held.expiresAt | string(date-time) | 是 | 占用到何时 |
createdBy | string | 是 | 发放者 |
createdAt | string(date-time) | 是 | 发放时间 |
ledger | EntitlementLedgerEntry[] | 只在读单项权益时有 | |
ledger[].id | integer | 是 | 流水 id |
ledger[].kind | string | 是 | 变动的种类 |
ledger[].delta | integer | 是 | 次数的增减 |
ledger[].balance | integer | 是 | 变动后的余额 |
ledger[].actorName | string | 是 | 谁做的 |
ledger[].reason | string | 是 | 原因 |
ledger[].ref | string | 关联的订单或预约 | |
ledger[].redemptionId | string | 关联的核销单 | |
ledger[].at | string(date-time) | 是 | 时间 |
POST /entitlements/redemptions
核销一次权益(原子,按 key 幂等)
需要范围 app.entitlements:write。English: uses a grant once or more, atomically.
pick 指定权益;不指定时服务在 holder 的权益里按“先到期的、无期限的最后、剩得少的、先发的”选。key 在正文里,没写时用请求头 Idempotency-Key;同键重来 replay 为 true,不再扣。任何权益都可以核销,不限本应用的模板。不能核销时是 422,error.message 是给人看的原因,error.details.items 逐项说明其他权益为什么不行。
- 认证:
bearer - 范围:
app.entitlements:write - operationId:
redeemEntitlement
参数
| 名称 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
K3-Dry-Run | header | string | 传 1 时只预演:回答和真做一样,什么也不留下 可选值: 1 | |
Idempotency-Key | header | string | 每个 POST 都收。SDK 未传入时会生成 uuid v4。24 小时内同键同正文重放第一次的回答 最短 1,最长 255 |
请求正文(必填)(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
key | string | 幂等键;省略时用请求头 Idempotency-Key | |
holder | string | 从谁的权益里选;pick 指定了权益时可省略 | |
pick | string | 指定权益 id;省略则由服务选 | |
scope | string[] | 这次使用的范围标签:权益的范围为空、这里为空或这里每个标签都在权益的范围里,权益才适用 | |
times | integer | 次数,默认 1(券和奖品总是 1 次) | |
by | string | 核销的人或系统,默认调用者 | |
where | string | 线下核销的门店 | |
ref | string | 它所付的订单或预约 | |
orderCents | integer | 满减券和折扣券所用于的订单金额(这两种必填) |
响应
| 状态 | 说明 |
|---|---|
| 200 | 核销单和核销后的权益 |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 404 | not_found:对应的记录不存在(客户中心没有这个客户,访客、服务或所指的东西不存在)。见 NotFound |
| 409 | 见 Conflict |
| 413 | payload_too_large:正文太大。见 PayloadTooLarge |
| 422 | 服务拒绝,或字段不被接受。见 Refused |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
200 响应正文(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
redemption | EntitlementRedemption | 是 | 一次使用(核销单) |
redemption.id | string | 是 | 核销单 id |
redemption.no | string | 是 | 核销单号 |
redemption.grant | string | 是 | 权益 id |
redemption.holder | string | 是 | 客户 id |
redemption.times | integer | 是 | 次数 |
redemption.discountCents | integer | 是 | 券减掉的金额 |
redemption.state | string | 是 | ok 或 void |
redemption.voidReason | string | 作废原因 | |
redemption.voidedAt | string(date-time) | 作废时间 | |
redemption.by | string | 是 | 核销者 |
redemption.byName | string | 是 | 核销者姓名 |
redemption.where | string | 门店 | |
redemption.ref | string | 订单或预约 | |
redemption.createdAt | string(date-time) | 是 | 核销时间 |
grant | EntitlementGrant | 是 | 一项权益 |
grant.id | string | 是 | 权益 id |
grant.template | string | 是 | 来源模板 id |
grant.ownerApp | string | 是 | 模板归属的应用 |
grant.kind | string | 是 | 种类 |
grant.name | string | 是 | 名称 |
grant.params | EntitlementParams | 是 | 种类相关的参数(字段名是 snake_case);哪个种类读哪些字段由服务在保存模板时检查 |
grant.params.total_times | integer | 次数(count、count_period) | |
grant.params.valid_days | integer | 有效天数(period、count_period 必填) | |
grant.params.valid_from | string | "grant"(默认)或 "first_use" | |
grant.params.daily_cap | integer | 每日上限(期卡) | |
grant.params.weekly_cap | integer | 每周上限(期卡) | |
grant.params.starts_on | string | 固定有效期开始,YYYY-MM-DD(券;覆盖 valid_days) | |
grant.params.ends_on | string | 固定有效期结束,含当天 | |
grant.params.form | string | 券的形式:cash、percent、service、code | |
grant.params.amount_off_cents | integer | 满减金额(cash) | |
grant.params.percent | integer | 折扣:减多少个百分点,1 到 99(percent) | |
grant.params.threshold_cents | integer | 订单要达到的金额(cash、percent) | |
grant.params.max_off_cents | integer | 最多减多少,0 为不封顶(percent) | |
grant.params.restore_on_refund | boolean | 订单退款时把券还回去(由调用方读到后作废核销单) | |
grant.params.description | string | 奖品说明 | |
grant.params.fulfilment | string | 奖品如何交付(对平台不透明) | |
grant.scope | string[] | 是 | 范围标签 |
grant.transferable | boolean | 是 | 可转让 |
grant.freezable | boolean | 是 | 可冻结 |
grant.maxFreezeDays | integer | 是 | 最多冻结天数 |
grant.holder | string | 是 | 持有的客户 id |
grant.total | integer | 是 | 总次数 |
grant.remaining | integer | 是 | 剩余次数 |
grant.startsOn | string | 是 | 开始日期 |
grant.endsOn | string | 是 | 结束日期 |
grant.state | string | 是 | 对它做过什么 |
grant.status | string | 是 | 对人说的状态:active、not_started、frozen、expired、used_up、used、refunded、voided、transferred(按今天算) |
grant.frozenFrom | string | 冻结开始 | |
grant.frozenUntil | string | 冻结到 | |
grant.frozenDaysUsed | integer | 是 | 已冻结天数 |
grant.source | string | 是 | 来源 |
grant.paidCents | integer | 是 | 付款 |
grant.refundedCents | integer | 是 | 已退 |
grant.origin | string | k3:// 引用 | |
grant.attribution | object | 归因 | |
grant.code | string | 券码 | |
grant.transferredFrom | string | 转让自哪一项 | |
grant.held | EntitlementHold | 一个未支付订单对权益的占用 | |
grant.held.id | string | 是 | 占用 id |
grant.held.grant | string | 是 | 权益 id |
grant.held.ref | string | 是 | 占用它的订单 |
grant.held.expiresAt | string(date-time) | 是 | 占用到何时 |
grant.createdBy | string | 是 | 发放者 |
grant.createdAt | string(date-time) | 是 | 发放时间 |
grant.ledger | EntitlementLedgerEntry[] | 只在读单项权益时有 | |
grant.ledger[].id | integer | 是 | 流水 id |
grant.ledger[].kind | string | 是 | 变动的种类 |
grant.ledger[].delta | integer | 是 | 次数的增减 |
grant.ledger[].balance | integer | 是 | 变动后的余额 |
grant.ledger[].actorName | string | 是 | 谁做的 |
grant.ledger[].reason | string | 是 | 原因 |
grant.ledger[].ref | string | 关联的订单或预约 | |
grant.ledger[].redemptionId | string | 关联的核销单 | |
grant.ledger[].at | string(date-time) | 是 | 时间 |
replay | boolean | 是 | 同一个 key 已做过,没有再扣 |
POST /entitlements/redemptions/{id}/void
作废一张核销单,次数退回
需要范围 app.entitlements:write。English: undoes a redemption of a grant of the app's own template; the times come back through the ledger.
核销单所用的权益不是本应用的是 403 forbidden。正文必须是 JSON 对象,reason 可省略。
- 认证:
bearer - 范围:
app.entitlements:write - operationId:
voidEntitlementRedemption
参数
| 名称 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
id | path | string | 是 | id |
K3-Dry-Run | header | string | 传 1 时只预演:回答和真做一样,什么也不留下 可选值: 1 | |
Idempotency-Key | header | string | 每个 POST 都收。SDK 未传入时会生成 uuid v4。24 小时内同键同正文重放第一次的回答 最短 1,最长 255 |
请求正文(必填)(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
reason | string | 原因 |
响应
| 状态 | 说明 |
|---|---|
| 200 | 作废后的核销单 |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 404 | not_found:对应的记录不存在(客户中心没有这个客户,访客、服务或所指的东西不存在)。见 NotFound |
| 409 | 见 Conflict |
| 413 | payload_too_large:正文太大。见 PayloadTooLarge |
| 422 | 服务拒绝,或字段不被接受。见 Refused |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
200 响应正文(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
redemption | EntitlementRedemption | 是 | 一次使用(核销单) |
redemption.id | string | 是 | 核销单 id |
redemption.no | string | 是 | 核销单号 |
redemption.grant | string | 是 | 权益 id |
redemption.holder | string | 是 | 客户 id |
redemption.times | integer | 是 | 次数 |
redemption.discountCents | integer | 是 | 券减掉的金额 |
redemption.state | string | 是 | ok 或 void |
redemption.voidReason | string | 作废原因 | |
redemption.voidedAt | string(date-time) | 作废时间 | |
redemption.by | string | 是 | 核销者 |
redemption.byName | string | 是 | 核销者姓名 |
redemption.where | string | 门店 | |
redemption.ref | string | 订单或预约 | |
redemption.createdAt | string(date-time) | 是 | 核销时间 |
grant | EntitlementGrant | 是 | 一项权益 |
grant.id | string | 是 | 权益 id |
grant.template | string | 是 | 来源模板 id |
grant.ownerApp | string | 是 | 模板归属的应用 |
grant.kind | string | 是 | 种类 |
grant.name | string | 是 | 名称 |
grant.params | EntitlementParams | 是 | 种类相关的参数(字段名是 snake_case);哪个种类读哪些字段由服务在保存模板时检查 |
grant.params.total_times | integer | 次数(count、count_period) | |
grant.params.valid_days | integer | 有效天数(period、count_period 必填) | |
grant.params.valid_from | string | "grant"(默认)或 "first_use" | |
grant.params.daily_cap | integer | 每日上限(期卡) | |
grant.params.weekly_cap | integer | 每周上限(期卡) | |
grant.params.starts_on | string | 固定有效期开始,YYYY-MM-DD(券;覆盖 valid_days) | |
grant.params.ends_on | string | 固定有效期结束,含当天 | |
grant.params.form | string | 券的形式:cash、percent、service、code | |
grant.params.amount_off_cents | integer | 满减金额(cash) | |
grant.params.percent | integer | 折扣:减多少个百分点,1 到 99(percent) | |
grant.params.threshold_cents | integer | 订单要达到的金额(cash、percent) | |
grant.params.max_off_cents | integer | 最多减多少,0 为不封顶(percent) | |
grant.params.restore_on_refund | boolean | 订单退款时把券还回去(由调用方读到后作废核销单) | |
grant.params.description | string | 奖品说明 | |
grant.params.fulfilment | string | 奖品如何交付(对平台不透明) | |
grant.scope | string[] | 是 | 范围标签 |
grant.transferable | boolean | 是 | 可转让 |
grant.freezable | boolean | 是 | 可冻结 |
grant.maxFreezeDays | integer | 是 | 最多冻结天数 |
grant.holder | string | 是 | 持有的客户 id |
grant.total | integer | 是 | 总次数 |
grant.remaining | integer | 是 | 剩余次数 |
grant.startsOn | string | 是 | 开始日期 |
grant.endsOn | string | 是 | 结束日期 |
grant.state | string | 是 | 对它做过什么 |
grant.status | string | 是 | 对人说的状态:active、not_started、frozen、expired、used_up、used、refunded、voided、transferred(按今天算) |
grant.frozenFrom | string | 冻结开始 | |
grant.frozenUntil | string | 冻结到 | |
grant.frozenDaysUsed | integer | 是 | 已冻结天数 |
grant.source | string | 是 | 来源 |
grant.paidCents | integer | 是 | 付款 |
grant.refundedCents | integer | 是 | 已退 |
grant.origin | string | k3:// 引用 | |
grant.attribution | object | 归因 | |
grant.code | string | 券码 | |
grant.transferredFrom | string | 转让自哪一项 | |
grant.held | EntitlementHold | 一个未支付订单对权益的占用 | |
grant.held.id | string | 是 | 占用 id |
grant.held.grant | string | 是 | 权益 id |
grant.held.ref | string | 是 | 占用它的订单 |
grant.held.expiresAt | string(date-time) | 是 | 占用到何时 |
grant.createdBy | string | 是 | 发放者 |
grant.createdAt | string(date-time) | 是 | 发放时间 |
grant.ledger | EntitlementLedgerEntry[] | 只在读单项权益时有 | |
grant.ledger[].id | integer | 是 | 流水 id |
grant.ledger[].kind | string | 是 | 变动的种类 |
grant.ledger[].delta | integer | 是 | 次数的增减 |
grant.ledger[].balance | integer | 是 | 变动后的余额 |
grant.ledger[].actorName | string | 是 | 谁做的 |
grant.ledger[].reason | string | 是 | 原因 |
grant.ledger[].ref | string | 关联的订单或预约 | |
grant.ledger[].redemptionId | string | 关联的核销单 | |
grant.ledger[].at | string(date-time) | 是 | 时间 |
replay | boolean | 是 | 同一个 key 已做过,没有再扣 |
POST /entitlements/reservations
预留一次使用(到时未确认自动释放)
需要范围 app.entitlements:write。English: keeps one use aside until it is confirmed, cancelled or expired.
正文是核销的字段加 ttlSeconds(5 到 86400,默认 900)。权益的选法同核销。预留期间别人不能用这份。同一个 key 返回同一个预留:200 且 replay 为 true;新预留 201。
- 认证:
bearer - 范围:
app.entitlements:write - operationId:
reserveEntitlement
参数
| 名称 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
K3-Dry-Run | header | string | 传 1 时只预演:回答和真做一样,什么也不留下 可选值: 1 | |
Idempotency-Key | header | string | 每个 POST 都收。SDK 未传入时会生成 uuid v4。24 小时内同键同正文重放第一次的回答 最短 1,最长 255 |
请求正文(必填)(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
key | string | 预留的幂等键;省略时用请求头 Idempotency-Key | |
holder | string | 从谁的权益里选 | |
pick | string | 指定权益 id | |
scope | string[] | 这次使用的范围标签 | |
times | integer | 次数,默认 1 | |
by | string | 默认调用者 | |
where | string | 门店 | |
ref | string | 所付的订单或预约 | |
orderCents | integer | 满减券和折扣券所用于的订单金额 | |
ttlSeconds | integer | 保留多少秒,5 到 86400,默认 900 最小 5,最大 86400 |
响应
| 状态 | 说明 |
|---|---|
| 200 | 同一个 key 已预留过:这是当时的预留(replay 为 true) |
| 201 | 已预留 |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 404 | not_found:对应的记录不存在(客户中心没有这个客户,访客、服务或所指的东西不存在)。见 NotFound |
| 409 | 见 Conflict |
| 413 | payload_too_large:正文太大。见 PayloadTooLarge |
| 422 | 服务拒绝,或字段不被接受。见 Refused |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
200 响应正文(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
id | string | 是 | 预留 id |
grant | string | 是 | 被留住的权益 id |
holder | string | 是 | 客户 id |
times | integer | 是 | 次数 |
scope | string[] | 是 | 范围标签 |
orderCents | integer | 是 | 订单金额 |
discountCents | integer | 是 | 券减掉的金额 |
key | string | 是 | 预留的键 |
ref | string | 订单或预约 | |
where | string | 门店 | |
by | string | 是 | 谁预留的 |
byName | string | 是 | 姓名 |
app | string | 预留的应用 | |
state | string | 是 | live、confirmed、cancelled、expired |
expiresAt | string(date-time) | 是 | 到期时间 |
redemption | string | 已确认时的核销单 id | |
reason | string | 已取消时的原因 | |
createdAt | string(date-time) | 是 | 预留时间 |
replay | boolean | 是 | 同一个 key 已预留过,这是当时的预留 |
201 响应正文(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
id | string | 是 | 预留 id |
grant | string | 是 | 被留住的权益 id |
holder | string | 是 | 客户 id |
times | integer | 是 | 次数 |
scope | string[] | 是 | 范围标签 |
orderCents | integer | 是 | 订单金额 |
discountCents | integer | 是 | 券减掉的金额 |
key | string | 是 | 预留的键 |
ref | string | 订单或预约 | |
where | string | 门店 | |
by | string | 是 | 谁预留的 |
byName | string | 是 | 姓名 |
app | string | 预留的应用 | |
state | string | 是 | live、confirmed、cancelled、expired |
expiresAt | string(date-time) | 是 | 到期时间 |
redemption | string | 已确认时的核销单 id | |
reason | string | 已取消时的原因 | |
createdAt | string(date-time) | 是 | 预留时间 |
replay | boolean | 是 | 同一个 key 已预留过,这是当时的预留 |
GET /entitlements/reservations/{id}
读一个预留
需要范围 app.entitlements:read。English: one reservation. A live one past its expiry reads as expired.
- 认证:
bearer - 范围:
app.entitlements:read - operationId:
getEntitlementReservation
参数
| 名称 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
id | path | string | 是 | id |
响应
| 状态 | 说明 |
|---|---|
| 200 | 预留 |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 404 | not_found:对应的记录不存在(客户中心没有这个客户,访客、服务或所指的东西不存在)。见 NotFound |
| 422 | 服务拒绝,或字段不被接受。见 Refused |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
200 响应正文(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
id | string | 是 | 预留 id |
grant | string | 是 | 被留住的权益 id |
holder | string | 是 | 客户 id |
times | integer | 是 | 次数 |
scope | string[] | 是 | 范围标签 |
orderCents | integer | 是 | 订单金额 |
discountCents | integer | 是 | 券减掉的金额 |
key | string | 是 | 预留的键 |
ref | string | 订单或预约 | |
where | string | 门店 | |
by | string | 是 | 谁预留的 |
byName | string | 是 | 姓名 |
app | string | 预留的应用 | |
state | string | 是 | live、confirmed、cancelled、expired |
expiresAt | string(date-time) | 是 | 到期时间 |
redemption | string | 已确认时的核销单 id | |
reason | string | 已取消时的原因 | |
createdAt | string(date-time) | 是 | 预留时间 |
replay | boolean | 是 | 同一个 key 已预留过,这是当时的预留 |
POST /entitlements/reservations/{id}/confirm
确认预留:做出核销(恰好一次)
需要范围 app.entitlements:write。English: makes the reservation's redemption, exactly once.
再次确认返回同一张核销单且 replay 为 true。预留已过期或已取消是 409 conflict。不需要正文。
- 认证:
bearer - 范围:
app.entitlements:write - operationId:
confirmEntitlementReservation
参数
| 名称 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
id | path | string | 是 | id |
K3-Dry-Run | header | string | 传 1 时只预演:回答和真做一样,什么也不留下 可选值: 1 | |
Idempotency-Key | header | string | 每个 POST 都收。SDK 未传入时会生成 uuid v4。24 小时内同键同正文重放第一次的回答 最短 1,最长 255 |
响应
| 状态 | 说明 |
|---|---|
| 200 | 核销单和核销后的权益 |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 404 | not_found:对应的记录不存在(客户中心没有这个客户,访客、服务或所指的东西不存在)。见 NotFound |
| 409 | 见 Conflict |
| 422 | 服务拒绝,或字段不被接受。见 Refused |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
200 响应正文(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
redemption | EntitlementRedemption | 是 | 一次使用(核销单) |
redemption.id | string | 是 | 核销单 id |
redemption.no | string | 是 | 核销单号 |
redemption.grant | string | 是 | 权益 id |
redemption.holder | string | 是 | 客户 id |
redemption.times | integer | 是 | 次数 |
redemption.discountCents | integer | 是 | 券减掉的金额 |
redemption.state | string | 是 | ok 或 void |
redemption.voidReason | string | 作废原因 | |
redemption.voidedAt | string(date-time) | 作废时间 | |
redemption.by | string | 是 | 核销者 |
redemption.byName | string | 是 | 核销者姓名 |
redemption.where | string | 门店 | |
redemption.ref | string | 订单或预约 | |
redemption.createdAt | string(date-time) | 是 | 核销时间 |
grant | EntitlementGrant | 是 | 一项权益 |
grant.id | string | 是 | 权益 id |
grant.template | string | 是 | 来源模板 id |
grant.ownerApp | string | 是 | 模板归属的应用 |
grant.kind | string | 是 | 种类 |
grant.name | string | 是 | 名称 |
grant.params | EntitlementParams | 是 | 种类相关的参数(字段名是 snake_case);哪个种类读哪些字段由服务在保存模板时检查 |
grant.params.total_times | integer | 次数(count、count_period) | |
grant.params.valid_days | integer | 有效天数(period、count_period 必填) | |
grant.params.valid_from | string | "grant"(默认)或 "first_use" | |
grant.params.daily_cap | integer | 每日上限(期卡) | |
grant.params.weekly_cap | integer | 每周上限(期卡) | |
grant.params.starts_on | string | 固定有效期开始,YYYY-MM-DD(券;覆盖 valid_days) | |
grant.params.ends_on | string | 固定有效期结束,含当天 | |
grant.params.form | string | 券的形式:cash、percent、service、code | |
grant.params.amount_off_cents | integer | 满减金额(cash) | |
grant.params.percent | integer | 折扣:减多少个百分点,1 到 99(percent) | |
grant.params.threshold_cents | integer | 订单要达到的金额(cash、percent) | |
grant.params.max_off_cents | integer | 最多减多少,0 为不封顶(percent) | |
grant.params.restore_on_refund | boolean | 订单退款时把券还回去(由调用方读到后作废核销单) | |
grant.params.description | string | 奖品说明 | |
grant.params.fulfilment | string | 奖品如何交付(对平台不透明) | |
grant.scope | string[] | 是 | 范围标签 |
grant.transferable | boolean | 是 | 可转让 |
grant.freezable | boolean | 是 | 可冻结 |
grant.maxFreezeDays | integer | 是 | 最多冻结天数 |
grant.holder | string | 是 | 持有的客户 id |
grant.total | integer | 是 | 总次数 |
grant.remaining | integer | 是 | 剩余次数 |
grant.startsOn | string | 是 | 开始日期 |
grant.endsOn | string | 是 | 结束日期 |
grant.state | string | 是 | 对它做过什么 |
grant.status | string | 是 | 对人说的状态:active、not_started、frozen、expired、used_up、used、refunded、voided、transferred(按今天算) |
grant.frozenFrom | string | 冻结开始 | |
grant.frozenUntil | string | 冻结到 | |
grant.frozenDaysUsed | integer | 是 | 已冻结天数 |
grant.source | string | 是 | 来源 |
grant.paidCents | integer | 是 | 付款 |
grant.refundedCents | integer | 是 | 已退 |
grant.origin | string | k3:// 引用 | |
grant.attribution | object | 归因 | |
grant.code | string | 券码 | |
grant.transferredFrom | string | 转让自哪一项 | |
grant.held | EntitlementHold | 一个未支付订单对权益的占用 | |
grant.held.id | string | 是 | 占用 id |
grant.held.grant | string | 是 | 权益 id |
grant.held.ref | string | 是 | 占用它的订单 |
grant.held.expiresAt | string(date-time) | 是 | 占用到何时 |
grant.createdBy | string | 是 | 发放者 |
grant.createdAt | string(date-time) | 是 | 发放时间 |
grant.ledger | EntitlementLedgerEntry[] | 只在读单项权益时有 | |
grant.ledger[].id | integer | 是 | 流水 id |
grant.ledger[].kind | string | 是 | 变动的种类 |
grant.ledger[].delta | integer | 是 | 次数的增减 |
grant.ledger[].balance | integer | 是 | 变动后的余额 |
grant.ledger[].actorName | string | 是 | 谁做的 |
grant.ledger[].reason | string | 是 | 原因 |
grant.ledger[].ref | string | 关联的订单或预约 | |
grant.ledger[].redemptionId | string | 关联的核销单 | |
grant.ledger[].at | string(date-time) | 是 | 时间 |
replay | boolean | 是 | 同一个 key 已做过,没有再扣 |
POST /entitlements/reservations/{id}/cancel
取消预留,释放被留住的次数
需要范围 app.entitlements:write。English: gives a live reservation up; one that ended already is answered as it is.
已结束的预留原样返回且 replay 为 true。正文必须是 JSON 对象,reason 可省略。
- 认证:
bearer - 范围:
app.entitlements:write - operationId:
cancelEntitlementReservation
参数
| 名称 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
id | path | string | 是 | id |
K3-Dry-Run | header | string | 传 1 时只预演:回答和真做一样,什么也不留下 可选值: 1 | |
Idempotency-Key | header | string | 每个 POST 都收。SDK 未传入时会生成 uuid v4。24 小时内同键同正文重放第一次的回答 最短 1,最长 255 |
请求正文(必填)(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
reason | string | 原因 |
响应
| 状态 | 说明 |
|---|---|
| 200 | 取消后的预留 |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 404 | not_found:对应的记录不存在(客户中心没有这个客户,访客、服务或所指的东西不存在)。见 NotFound |
| 409 | 见 Conflict |
| 413 | payload_too_large:正文太大。见 PayloadTooLarge |
| 422 | 服务拒绝,或字段不被接受。见 Refused |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
200 响应正文(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
id | string | 是 | 预留 id |
grant | string | 是 | 被留住的权益 id |
holder | string | 是 | 客户 id |
times | integer | 是 | 次数 |
scope | string[] | 是 | 范围标签 |
orderCents | integer | 是 | 订单金额 |
discountCents | integer | 是 | 券减掉的金额 |
key | string | 是 | 预留的键 |
ref | string | 订单或预约 | |
where | string | 门店 | |
by | string | 是 | 谁预留的 |
byName | string | 是 | 姓名 |
app | string | 预留的应用 | |
state | string | 是 | live、confirmed、cancelled、expired |
expiresAt | string(date-time) | 是 | 到期时间 |
redemption | string | 已确认时的核销单 id | |
reason | string | 已取消时的原因 | |
createdAt | string(date-time) | 是 | 预留时间 |
replay | boolean | 是 | 同一个 key 已预留过,这是当时的预留 |
GET /entitlements/granters
列出其他应用声明的可发放项(granter)的名字
需要范围 app.entitlements:read。English: the names of what apps declare they can issue (entitlements.grantable in a manifest).
- 认证:
bearer - 范围:
app.entitlements:read - operationId:
listEntitlementGranters
响应
| 状态 | 说明 |
|---|---|
| 200 | 名字 |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 422 | 字段或参数不被接受(正文读不出来、有未知字段、缺必填、取值越界)。见 Unprocessable |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
200 响应正文(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
names | string[] | 是 | 已注册的名字,排序 |
POST /entitlements/granters/{name}/grants
通过其他应用声明的 granter 发放
需要范围 app.entitlements:write。English: asks the app that declares the granter to issue something; at least once, once per key.
key 在正文里,没写时用请求头 Idempotency-Key,必填;holder 必填。没有应用声明这个名字是 404 not_found。params 是 granter 自己的词汇;dry 为 true 或带 K3-Dry-Run: 1 时只预演。返回 granter 给出的 ref。
- 认证:
bearer - 范围:
app.entitlements:write - operationId:
grantEntitlementVia
参数
| 名称 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
name | path | string | 是 | granter 名字(“应用.内容”) |
K3-Dry-Run | header | string | 传 1 时只预演:回答和真做一样,什么也不留下 可选值: 1 | |
Idempotency-Key | header | string | 每个 POST 都收。SDK 未传入时会生成 uuid v4。24 小时内同键同正文重放第一次的回答 最短 1,最长 255 |
请求正文(必填)(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
key | string | 幂等键;省略时用请求头 Idempotency-Key。发放至少一次,同键必须得到同一个引用 | |
holder | string | 是 | 客户 id |
source | string | 来源 | |
origin | string | k3:// 引用 | |
paidCents | integer | 付款 | |
count | integer | 数量 | |
attribution | object | 归因 | |
params | object | granter 自己的词汇:发什么 | |
dry | boolean | 只预演,什么也不留下 |
响应
| 状态 | 说明 |
|---|---|
| 200 | granter 的回答 |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 404 | not_found:对应的记录不存在(客户中心没有这个客户,访客、服务或所指的东西不存在)。见 NotFound |
| 413 | payload_too_large:正文太大。见 PayloadTooLarge |
| 422 | 服务拒绝,或字段不被接受。见 Refused |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
200 响应正文(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
granter | string | 是 | granter 名字 |
ref | string | 是 | 发出之物的 k3:// 引用 |
GET /entitlements/codes/{code}
按券码读一项权益
需要范围 app.entitlements:read。English: the grant that carries the code.
不存在的券码和格式不对的券码得到同一个 404 not_found,所以猜码学不到任何东西。
- 认证:
bearer - 范围:
app.entitlements:read - operationId:
getEntitlementByCode
参数
| 名称 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
code | path | string | 是 | 券码 |
响应
| 状态 | 说明 |
|---|---|
| 200 | 权益 |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 404 | not_found:对应的记录不存在(客户中心没有这个客户,访客、服务或所指的东西不存在)。见 NotFound |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
200 响应正文(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
id | string | 是 | 权益 id |
template | string | 是 | 来源模板 id |
ownerApp | string | 是 | 模板归属的应用 |
kind | string | 是 | 种类 |
name | string | 是 | 名称 |
params | EntitlementParams | 是 | 种类相关的参数(字段名是 snake_case);哪个种类读哪些字段由服务在保存模板时检查 |
params.total_times | integer | 次数(count、count_period) | |
params.valid_days | integer | 有效天数(period、count_period 必填) | |
params.valid_from | string | "grant"(默认)或 "first_use" | |
params.daily_cap | integer | 每日上限(期卡) | |
params.weekly_cap | integer | 每周上限(期卡) | |
params.starts_on | string | 固定有效期开始,YYYY-MM-DD(券;覆盖 valid_days) | |
params.ends_on | string | 固定有效期结束,含当天 | |
params.form | string | 券的形式:cash、percent、service、code | |
params.amount_off_cents | integer | 满减金额(cash) | |
params.percent | integer | 折扣:减多少个百分点,1 到 99(percent) | |
params.threshold_cents | integer | 订单要达到的金额(cash、percent) | |
params.max_off_cents | integer | 最多减多少,0 为不封顶(percent) | |
params.restore_on_refund | boolean | 订单退款时把券还回去(由调用方读到后作废核销单) | |
params.description | string | 奖品说明 | |
params.fulfilment | string | 奖品如何交付(对平台不透明) | |
scope | string[] | 是 | 范围标签 |
transferable | boolean | 是 | 可转让 |
freezable | boolean | 是 | 可冻结 |
maxFreezeDays | integer | 是 | 最多冻结天数 |
holder | string | 是 | 持有的客户 id |
total | integer | 是 | 总次数 |
remaining | integer | 是 | 剩余次数 |
startsOn | string | 是 | 开始日期 |
endsOn | string | 是 | 结束日期 |
state | string | 是 | 对它做过什么 |
status | string | 是 | 对人说的状态:active、not_started、frozen、expired、used_up、used、refunded、voided、transferred(按今天算) |
frozenFrom | string | 冻结开始 | |
frozenUntil | string | 冻结到 | |
frozenDaysUsed | integer | 是 | 已冻结天数 |
source | string | 是 | 来源 |
paidCents | integer | 是 | 付款 |
refundedCents | integer | 是 | 已退 |
origin | string | k3:// 引用 | |
attribution | object | 归因 | |
code | string | 券码 | |
transferredFrom | string | 转让自哪一项 | |
held | EntitlementHold | 一个未支付订单对权益的占用 | |
held.id | string | 是 | 占用 id |
held.grant | string | 是 | 权益 id |
held.ref | string | 是 | 占用它的订单 |
held.expiresAt | string(date-time) | 是 | 占用到何时 |
createdBy | string | 是 | 发放者 |
createdAt | string(date-time) | 是 | 发放时间 |
ledger | EntitlementLedgerEntry[] | 只在读单项权益时有 | |
ledger[].id | integer | 是 | 流水 id |
ledger[].kind | string | 是 | 变动的种类 |
ledger[].delta | integer | 是 | 次数的增减 |
ledger[].balance | integer | 是 | 变动后的余额 |
ledger[].actorName | string | 是 | 谁做的 |
ledger[].reason | string | 是 | 原因 |
ledger[].ref | string | 关联的订单或预约 | |
ledger[].redemptionId | string | 关联的核销单 | |
ledger[].at | string(date-time) | 是 | 时间 |
GET /entitlements/granters/{name}/choices
列出一个 granter 能发放的东西
需要范围 app.entitlements:read。English: what the granter can issue, for a picker.
没有应用声明这个名字,或它不列出,data 是 []。priceCents 在 granter 按价出售时给出。
- 认证:
bearer - 范围:
app.entitlements:read - operationId:
listEntitlementGranterChoices
参数
| 名称 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
name | path | string | 是 | granter 名字(“应用.内容”) |
响应
| 状态 | 说明 |
|---|---|
| 200 | 可发放项 |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
200 响应正文(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
data | GranterChoice[] | 是 | |
data[].param | string | 是 | 放进 params 的哪个键 |
data[].value | string | 是 | 键的值 |
data[].label | string | 是 | 给人看的名字 |
data[].summary | string | ||
data[].priceCents | integer(int64) | 按价出售时的价格;不按价出售时省略 |
POST /entitlements/granters/{name}/refunds
请 granter 收回它发出的东西
需要范围 app.entitlements:write。English: asks the app that declares the granter to take back what it issued (an order refunds what it collected); idempotent by key.
ref 是发出之物的 k3:// 引用。amountCents 省略时按 granter 自己的规则算现在值多少并收回,写了就按这个数收回。key 在正文里,没写时用请求头 Idempotency-Key,同键重来返回第一次的结果、不再收回。preview 为 true 或带 K3-Dry-Run: 1 时只回答值多少,什么也不收。没有应用声明这个名字是 404 not_found;granter 不收回是 409(错误码 not_refundable);被拒绝时 422 用话说明原因。
- 认证:
bearer - 范围:
app.entitlements:write - operationId:
refundEntitlementVia
参数
| 名称 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
name | path | string | 是 | granter 名字(“应用.内容”) |
K3-Dry-Run | header | string | 传 1 时只预演:回答和真做一样,什么也不留下 可选值: 1 | |
Idempotency-Key | header | string | 每个 POST 都收。SDK 未传入时会生成 uuid v4。24 小时内同键同正文重放第一次的回答 最短 1,最长 255 |
请求正文(必填)(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
key | string | 幂等键;省略时用请求头 Idempotency-Key | |
preview | boolean | 只回答值多少,什么也不收 | |
ref | string | 发出之物的 k3:// 引用 | |
amountCents | integer(int64) | 按这个数收回;省略时按 granter 自己的规则算 | |
reason | string |
响应
| 状态 | 说明 |
|---|---|
| 200 | 收回的结果 |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 404 | not_found:对应的记录不存在(客户中心没有这个客户,访客、服务或所指的东西不存在)。见 NotFound |
| 409 | 见 Conflict |
| 413 | payload_too_large:正文太大。见 PayloadTooLarge |
| 422 | 服务拒绝,或字段不被接受。见 Refused |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
200 响应正文(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
amountCents | integer(int64) | 现在值多少 | |
effect | string | 给员工看的话 |
secrets
平台密钥库:用每个主体一把的钥匙加密、解密、销毁本应用的个人数据
POST /secrets/encrypt
用这个主体的钥匙加密本应用的一段个人数据
需要范围 app.secrets:use。English: encrypts personal data under the key of one subject of the calling app.
subject 是本应用自己的 <种类>:<id>(种类是小写字母、数字和 -,以字母开头,最多 40 字符;id 最多 200 字符),否则 422 invalid。平台把它归到本应用和令牌的组织下,应用碰不到别的应用、别的组织的钥匙。plaintext 是 base64。正文最多 64 KiB(明文约 48 KiB),超出是 413 payload_too_large。返回的 ciphertext(base64)由应用自己保存。平台没有密钥库时是 503。
- 认证:
bearer - 范围:
app.secrets:use - operationId:
encryptSecret
参数
| 名称 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
Idempotency-Key | header | string | 每个 POST 都收。SDK 未传入时会生成 uuid v4。24 小时内同键同正文重放第一次的回答 最短 1,最长 255 |
请求正文(必填)(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
subject | string | 是 | 本应用的主体 <种类>:<id>,例如 recipient:f_123 |
plaintext | string(byte) | 是 | 明文,base64;正文最多 64 KiB(明文约 48 KiB) |
响应
| 状态 | 说明 |
|---|---|
| 200 | 密文 |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 413 | payload_too_large:正文太大。见 PayloadTooLarge |
| 422 | 字段或参数不被接受(正文读不出来、有未知字段、缺必填、取值越界)。见 Unprocessable |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
200 响应正文(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
ciphertext | string(byte) | 是 | 密文,base64;由应用保存 |
POST /secrets/decrypt
用这个主体的钥匙解密本应用保存的密文
需要范围 app.secrets:use。English: decrypts a ciphertext of one subject of the calling app; the answer is not cached (Cache-Control: no-store).
subject 同加密时一样。ciphertext 是 base64,正文最多 64 KiB。钥匙已销毁,或密文不是这个主体的,都是 409 conflict,不说是哪一种。回答带 Cache-Control: no-store。解密的回答不为 Idempotency-Key 保存(带了也忽略,明文不留在平台):它不改变任何东西,重试就是再问一次。
- 认证:
bearer - 范围:
app.secrets:use - operationId:
decryptSecret
参数
| 名称 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
Idempotency-Key | header | string | 每个 POST 都收。SDK 未传入时会生成 uuid v4。24 小时内同键同正文重放第一次的回答 最短 1,最长 255 |
请求正文(必填)(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
subject | string | 是 | 加密时的主体 <种类>:<id> |
ciphertext | string(byte) | 是 | 加密时得到的密文,base64 |
响应
| 状态 | 说明 |
|---|---|
| 200 | 明文 |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 409 | 见 Conflict |
| 413 | payload_too_large:正文太大。见 PayloadTooLarge |
| 422 | 字段或参数不被接受(正文读不出来、有未知字段、缺必填、取值越界)。见 Unprocessable |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
200 响应正文(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
plaintext | string(byte) | 是 | 明文,base64 |
POST /secrets/shred
永久销毁这个主体的钥匙(它的密文从此解不开)
需要范围 app.secrets:use。English: destroys the key of one subject of the calling app for good; its ciphertexts can no longer be decrypted.
subject 同加密时一样。销毁不能撤回;之后解密这个主体的密文是 409 conflict。成功回答 204,没有正文。
- 认证:
bearer - 范围:
app.secrets:use - operationId:
shredSecret
参数
| 名称 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
Idempotency-Key | header | string | 每个 POST 都收。SDK 未传入时会生成 uuid v4。24 小时内同键同正文重放第一次的回答 最短 1,最长 255 |
请求正文(必填)(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
subject | string | 是 | 本应用的主体 <种类>:<id> |
响应
| 状态 | 说明 |
|---|---|
| 204 | 已销毁。没有正文 |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 413 | payload_too_large:正文太大。见 PayloadTooLarge |
| 422 | 字段或参数不被接受(正文读不出来、有未知字段、缺必填、取值越界)。见 Unprocessable |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
sites
企业站点的名称、状态与访问量
POST /sites/summaries
读企业站点的名称、状态和一段日期里的访问量
需要范围 app.sites:read。English: the name, state and request count of the tenant's sites, one answer per request, in order.
requests 最多 200 条,超出是 422。每条问一个站点从 from 那天到 to 那天(省略:到今天)的访问量。不存在的站点回答空名字、0 次访问、没有 state。平台没有接上站点时是 501 capability_off。
- 认证:
bearer - 范围:
app.sites:read - operationId:
summarizeSites
参数
| 名称 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
Idempotency-Key | header | string | 每个 POST 都收。SDK 未传入时会生成 uuid v4。24 小时内同键同正文重放第一次的回答 最短 1,最长 255 |
请求正文(必填)(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
requests | SiteUsageRequest[] | 是 | 最多 200 项 |
requests[].site | string | 是 | 站点 id |
requests[].from | string(date-time) | 是 | 从这一天(含) |
requests[].to | string(date-time) | 到这一天(含);省略为到今天 |
响应
| 状态 | 说明 |
|---|---|
| 200 | 每条请求一个回答,顺序相同 |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 413 | payload_too_large:正文太大。见 PayloadTooLarge |
| 422 | 字段或参数不被接受(正文读不出来、有未知字段、缺必填、取值越界)。见 Unprocessable |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
200 响应正文(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
summaries | SiteSummary[] | 是 | |
summaries[].site | string | 是 | 站点 id |
summaries[].name | string | 是 | 站点名称;站点不存在时为空 |
summaries[].requests | integer(int64) | 是 | 这段日期里的访问次数 |
summaries[].state | string | 访客现在看到什么:live 在线(liveNumber 是在线的版本),unpublished 从没发布过,ended 已下线(显示活动已结束,自 endedAt 起),disabled 地址打不开。站点不存在时没有 可选值: live、unpublished、ended、disabled | |
summaries[].liveNumber | integer | 在线的版本号 | |
summaries[].endedAt | string(date-time) | 下线时间 |
stores
组织里的门店,以及某人所在或管理的门店(只读)
GET /stores
列出组织里的门店,或某人所在、所管的门店
需要范围 app.stores:read。English: every store of the tenant in the tree's order, closed ones included; with of, the stores that person works at or manages.
省略 of:组织的全部门店(含已关闭的),按组织树的顺序。of 是人员的 subject:他所属或被任命的每个部门及其下面的门店(店员是自己的店,任命在大区的经理是大区下的每家店)。门店由平台维护,应用只读,用 id(部门 id)引用。平台没有接上门店时是 501 capability_off。
- 认证:
bearer - 范围:
app.stores:read - operationId:
listStores
参数
| 名称 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
of | query | string | 人员的 subject;省略为全部门店 |
响应
| 状态 | 说明 |
|---|---|
| 200 | 门店 |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 422 | 字段或参数不被接受(正文读不出来、有未知字段、缺必填、取值越界)。见 Unprocessable |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
200 响应正文(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
stores | Store[] | 是 | |
stores[].id | string | 是 | 部门 id;应用用它引用门店 |
stores[].code | string | 门店编码 | |
stores[].name | string | 是 | |
stores[].parentId | string | 上级部门 id | |
stores[].path | string | 是 | 部门在组织树里的路径 |
stores[].region | string | 门店上面的部门链,最上层在前,例如 山东省 / 鲁东区 / 济南 | |
stores[].province | string | ||
stores[].city | string | ||
stores[].district | string | ||
stores[].address | string | ||
stores[].lat | number(double) | ||
stores[].lng | number(double) | ||
stores[].phone | string | ||
stores[].hours | string | 营业时间 | |
stores[].status | string | 是 | planning、open、paused 或 closed;门店资料还没填时为空 |
stores[].openedOn | string | 开业日期 |
realtime
实时文档:本应用在清单里声明的协同文档(创建、服务端改动、投影、删除),同步连接由平台在应用自己的域名上提供
POST /realtime/docs
创建一份实时文档
需要范围 app.realtime:write。English: creates a real-time document of one of the kinds the app declares in realtime.docs[], and registers it as an instance of the kind's resource type.
kind 必须是本应用清单 realtime.docs[] 里声明的种类,否则 422 invalid。resource 是它所属资源的 id(资源类型由种类声明),文档的权限就是调用者在这个资源上的级别(见 resources 接口)。id 可省略,平台取 rd_…;自己取的 id 只能用字母、数字、- 和 _,最多 64 字符。创建是幂等的:同一命名空间里已有同 id、同种类、同资源类型的文档时返回 200 和它的文档头(应用可以在自己提交之前先建、失败后重试);同 id 的其他文档是 409 conflict。
初始内容按种类的编码给:yjs-v1 给 doc(ProseMirror 文档,省略是空文档),ymap-v1 给 data(JSON 对象,必填),board-v1 给 board(看板,必填),Office 编码给 state(base64,由读过文件的浏览器生成,必填)。正文最大 8 MiB。
返回 201 和文档头。页面会话只能用自己有权的资源;应用自己的令牌不受级别限制(文档归应用)。
- 认证:
bearer - 范围:
app.realtime:write - operationId:
createRealtimeDoc
参数
| 名称 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
Idempotency-Key | header | string | 每个 POST 都收。SDK 未传入时会生成 uuid v4。24 小时内同键同正文重放第一次的回答 最短 1,最长 255 |
请求正文(必填)(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
kind | string | 是 | 本应用清单 realtime.docs[] 里声明的种类 |
id | string | 文档 id,字母、数字、- 和 _;省略由平台取 最长 64 | |
resource | string | 是 | 所属资源的 id(资源类型由种类声明) 最长 200 |
doc | object | yjs-v1:ProseMirror 文档(省略是空文档) | |
data | object | ymap-v1:JSON 对象(必填) | |
board | object | board-v1:看板(必填) | |
state | string | Office 编码:base64 的初始状态(必填) |
响应
| 状态 | 说明 |
|---|---|
| 200 | 同 id、同种类的文档已在:它的文档头 |
| 201 | 文档已创建 |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 404 | not_found:对应的记录不存在(客户中心没有这个客户,访客、服务或所指的东西不存在)。见 NotFound |
| 409 | 见 Conflict |
| 413 | payload_too_large:正文太大。见 PayloadTooLarge |
| 422 | 字段或参数不被接受(正文读不出来、有未知字段、缺必填、取值越界)。见 Unprocessable |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
200 响应正文(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
id | string | 是 | |
kind | string | 是 | 清单声明的种类 |
codec | string | 是 | 编码:yjs-v1、ymap-v1、board-v1 或 Office 编码 |
epoch | integer | 是 | 纪元;每次重新开始加 1 |
schemaVer | integer | 是 | 文档结构的版本 |
headSeq | integer(int64) | 是 | 日志头的序号 |
projSeq | integer(int64) | 是 | 最近一次投影所在的序号 |
resource | RealtimeDocResource | 是 | 文档所属的资源 |
resource.type | string | 是 | 资源类型,{应用 id}.{名字} |
resource.id | string | 是 | 资源 id |
updatedAt | string(date-time) | 是 |
201 响应正文(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
id | string | 是 | |
kind | string | 是 | 清单声明的种类 |
codec | string | 是 | 编码:yjs-v1、ymap-v1、board-v1 或 Office 编码 |
epoch | integer | 是 | 纪元;每次重新开始加 1 |
schemaVer | integer | 是 | 文档结构的版本 |
headSeq | integer(int64) | 是 | 日志头的序号 |
projSeq | integer(int64) | 是 | 最近一次投影所在的序号 |
resource | RealtimeDocResource | 是 | 文档所属的资源 |
resource.type | string | 是 | 资源类型,{应用 id}.{名字} |
resource.id | string | 是 | 资源 id |
updatedAt | string(date-time) | 是 |
GET /realtime/docs/{id}
读一份实时文档的头信息
需要范围 app.realtime:read。English: the header of one document: codec, epoch, schema version, the sequence of the log head and of the last projection, and its resource.
页面会话需要对所属资源至少有查看级别,没有时一律是 404 not_found(不暴露文档是否存在)。别的应用的文档、平台内置应用的文档也是 404。
- 认证:
bearer - 范围:
app.realtime:read - operationId:
getRealtimeDoc
参数
| 名称 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
id | path | string | 是 | 文档 id(rd_…,或创建时自己取的 id) |
响应
| 状态 | 说明 |
|---|---|
| 200 | 文档头 |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 404 | not_found:对应的记录不存在(客户中心没有这个客户,访客、服务或所指的东西不存在)。见 NotFound |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
200 响应正文(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
id | string | 是 | |
kind | string | 是 | 清单声明的种类 |
codec | string | 是 | 编码:yjs-v1、ymap-v1、board-v1 或 Office 编码 |
epoch | integer | 是 | 纪元;每次重新开始加 1 |
schemaVer | integer | 是 | 文档结构的版本 |
headSeq | integer(int64) | 是 | 日志头的序号 |
projSeq | integer(int64) | 是 | 最近一次投影所在的序号 |
resource | RealtimeDocResource | 是 | 文档所属的资源 |
resource.type | string | 是 | 资源类型,{应用 id}.{名字} |
resource.id | string | 是 | 资源 id |
updatedAt | string(date-time) | 是 |
DELETE /realtime/docs/{id}
删除一份实时文档
需要范围 app.realtime:write。English: deletes the document, its log and its projection, and closes the open sync connections.
页面会话需要对所属资源有编辑级别以上,否则 404 not_found。资源的登记(访问名单)不随文档删除,由应用用 DELETE /access/{type}/{id} 另行删除。返回 204。
- 认证:
bearer - 范围:
app.realtime:write - operationId:
deleteRealtimeDoc
参数
| 名称 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
id | path | string | 是 | 文档 id(rd_…,或创建时自己取的 id) |
响应
| 状态 | 说明 |
|---|---|
| 204 | 已删除 |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 404 | not_found:对应的记录不存在(客户中心没有这个客户,访客、服务或所指的东西不存在)。见 NotFound |
| 409 | 见 Conflict |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
POST /realtime/docs/{id}/edits
由服务端改一份实时文档
需要范围 app.realtime:write。English: applies one server-side edit to the document as the caller, returns the sequence it landed at and the projection after it.
edit 里写且只写一种改动,按顺序取第一个出现的:replace(整份 ProseMirror 文档)、append(追加的块)、title、data(ymap-v1:整个对象)、board(board-v1:整个看板)。什么也没写是 422 invalid。origin 是 draft、restore 或 system(默认 system),说明这次改动的来历。dry 为 true 只预演:回答和真做一样,什么也不留下。
声明了 guard 的种类,写入前会先问应用(清单 providers.realtimeGuard),应用拒绝是 422 invalid。需要编辑级别;代理(agent)只读,是 422 invalid。正文最大 8 MiB。
- 认证:
bearer - 范围:
app.realtime:write - operationId:
editRealtimeDoc
参数
| 名称 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
id | path | string | 是 | 文档 id(rd_…,或创建时自己取的 id) |
Idempotency-Key | header | string | 每个 POST 都收。SDK 未传入时会生成 uuid v4。24 小时内同键同正文重放第一次的回答 最短 1,最长 255 |
请求正文(必填)(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
edit | RealtimeEditBody | 是 | 一种改动。只写一项:replace、append、title、data、board 之一 |
edit.replace | object | 整份 ProseMirror 文档 | |
edit.append | object[] | 追加到末尾的 ProseMirror 块 | |
edit.title | string | 新标题 | |
edit.data | object | ymap-v1:整个对象 | |
edit.board | object | board-v1:整个看板 | |
origin | string | 改动的来历,默认 system 可选值: draft、restore、system | |
dry | boolean | 为 true 只预演 |
响应
| 状态 | 说明 |
|---|---|
| 200 | 改动落在的序号和之后的投影 |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 404 | not_found:对应的记录不存在(客户中心没有这个客户,访客、服务或所指的东西不存在)。见 NotFound |
| 409 | 见 Conflict |
| 413 | payload_too_large:正文太大。见 PayloadTooLarge |
| 422 | 字段或参数不被接受(正文读不出来、有未知字段、缺必填、取值越界)。见 Unprocessable |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
200 响应正文(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
seq | integer(int64) | 是 | 改动落在的序号(预演时是将落在的序号) |
projection | RealtimeProjection | 是 | 文档投影出的内容。doc、data、board 按编码出现一个 |
projection.seq | integer(int64) | 是 | 投影所在的序号 |
projection.title | string | 是 | |
projection.plain | string | 是 | 纯文本 |
projection.words | integer | 是 | 字数 |
projection.refs | RealtimeRef[] | 是 | |
projection.refs[].ref | string | 是 | 被引用的对象(k3:// 引用、页面链接或网址) |
projection.refs[].kind | string | ||
projection.refs[].app | string | ||
projection.refs[].block | string | 所在顶层块的 blockId | |
projection.refs[].via | string | 是 | ref、refCard、pageLink 或 link |
projection.doc | object | yjs-v1 与 Office 编码:ProseMirror JSON | |
projection.data | object | ymap-v1:对象 | |
projection.board | object | board-v1:看板 |
POST /realtime/docs/{id}/epoch
让一份实时文档从新的内容重新开始(换纪元)
需要范围 app.realtime:write。English: starts the document over from the given content; epoch + 1, so open editors reconnect from the new state. Use it for restore and import.
只有 ProseMirror 文档(yjs-v1)能这样重开,doc 省略是空文档;其他编码是 422 invalid。需要编辑级别。
- 认证:
bearer - 范围:
app.realtime:write - operationId:
restartRealtimeDoc
参数
| 名称 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
id | path | string | 是 | 文档 id(rd_…,或创建时自己取的 id) |
Idempotency-Key | header | string | 每个 POST 都收。SDK 未传入时会生成 uuid v4。24 小时内同键同正文重放第一次的回答 最短 1,最长 255 |
请求正文(必填)(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
doc | object | 新的 ProseMirror 文档;省略是空文档 |
响应
| 状态 | 说明 |
|---|---|
| 200 | 新的纪元 |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 404 | not_found:对应的记录不存在(客户中心没有这个客户,访客、服务或所指的东西不存在)。见 NotFound |
| 409 | 见 Conflict |
| 413 | payload_too_large:正文太大。见 PayloadTooLarge |
| 422 | 字段或参数不被接受(正文读不出来、有未知字段、缺必填、取值越界)。见 Unprocessable |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
200 响应正文(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
epoch | integer | 是 | 新的纪元 |
GET /realtime/docs/{id}/projection
读一份实时文档现在的投影
需要范围 app.realtime:read。English: the projection now: title, plain text, word count, references, and the content in the codec's form.
内容的形状随编码:yjs-v1 与 Office 编码给 doc(ProseMirror JSON),ymap-v1 给 data,board-v1 给 board。需要查看级别,没有时 404 not_found。投影完成后平台会把事件 realtime.doc.projected 送给应用(见 webhooks)。
带 minSeq 时,平台先让投影至少到这个序号(必要时当场投影),最多等 wait 毫秒(不超过 5000);到时还没到是 409 behind,稍后再试。English: with minSeq, the platform first brings the projection to at least that sequence, waiting up to wait ms (at most 5000); 409 behind when it is not there in time.
- 认证:
bearer - 范围:
app.realtime:read - operationId:
getRealtimeProjection
参数
| 名称 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
id | path | string | 是 | 文档 id(rd_…,或创建时自己取的 id) |
minSeq | query | integer(int64) | 投影至少要到的序号 最小 0 | |
wait | query | integer | 等投影的最长时间(毫秒,最多 5000) 最小 0,最大 5000 |
响应
| 状态 | 说明 |
|---|---|
| 200 | 投影 |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 404 | not_found:对应的记录不存在(客户中心没有这个客户,访客、服务或所指的东西不存在)。见 NotFound |
| 409 | 见 Conflict |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
200 响应正文(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
seq | integer(int64) | 是 | 投影所在的序号 |
title | string | 是 | |
plain | string | 是 | 纯文本 |
words | integer | 是 | 字数 |
refs | RealtimeRef[] | 是 | |
refs[].ref | string | 是 | 被引用的对象(k3:// 引用、页面链接或网址) |
refs[].kind | string | ||
refs[].app | string | ||
refs[].block | string | 所在顶层块的 blockId | |
refs[].via | string | 是 | ref、refCard、pageLink 或 link |
doc | object | yjs-v1 与 Office 编码:ProseMirror JSON | |
data | object | ymap-v1:对象 | |
board | object | board-v1:看板 |
GET /realtime/docs/{id}/state
读一份实时文档完整的 CRDT 状态
需要范围 app.realtime:read。English: the document's whole CRDT state as it is now (its snapshot with every logged update merged), base64, and the sequence it is at.
应用把它存成一个版本(发布的副本),或交给只读的查看页。页面会话需要查看级别,没有时 404 not_found。
- 认证:
bearer - 范围:
app.realtime:read - operationId:
getRealtimeState
参数
| 名称 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
id | path | string | 是 | 文档 id(rd_…,或创建时自己取的 id) |
响应
| 状态 | 说明 |
|---|---|
| 200 | 完整状态 |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 404 | not_found:对应的记录不存在(客户中心没有这个客户,访客、服务或所指的东西不存在)。见 NotFound |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
200 响应正文(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
seq | integer(int64) | 是 | 状态所在的序号(日志头) |
codec | string | 是 | 编码 |
state | string | 是 | base64 的状态 |
POST /realtime/docs/{id}/scrub
把一份实时文档整理到平台现在的结构
需要范围 app.realtime:write。English: brings the document to the server's schema: removes from the CRDT what the schema no longer stores (a repair update) and compacts the log.
只收应用自己的令牌(页面会话是 403 forbidden);每个应用在每个企业有调用额度(每秒 20 次,峰值 200),超过是 429,带 Retry-After。文档正在别处投影或压缩时是 409 conflict,稍后再试。
- 认证:
bearer - 范围:
app.realtime:write - operationId:
scrubRealtimeDoc
参数
| 名称 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
id | path | string | 是 | 文档 id(rd_…,或创建时自己取的 id) |
Idempotency-Key | header | string | 每个 POST 都收。SDK 未传入时会生成 uuid v4。24 小时内同键同正文重放第一次的回答 最短 1,最长 255 |
响应
| 状态 | 说明 |
|---|---|
| 200 | 整理的结果 |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 404 | not_found:对应的记录不存在(客户中心没有这个客户,访客、服务或所指的东西不存在)。见 NotFound |
| 409 | 见 Conflict |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
200 响应正文(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
repaired | boolean | 是 | 写了一次修复(CRDT 里有结构不再保存的内容) |
compacted | boolean | 是 | 日志压缩成了快照 |
POST /realtime/docs/invalidate
让打开这些文档的连接重新核对权限
需要范围 app.realtime:write。English: re-authorises the sync connections that have these documents open (after a permission change, a move or a restore).
只收应用自己的令牌(页面会话是 403 forbidden);每个应用在每个企业有调用额度(每秒 20 次,峰值 200),超过是 429,带 Retry-After。ids 1 到 100 个,都必须是这个种类在它的命名空间里的文档,否则 404 not_found(别的应用的文档不在这里)。返回 202。
- 认证:
bearer - 范围:
app.realtime:write - operationId:
invalidateRealtimeDocs
参数
| 名称 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
Idempotency-Key | header | string | 每个 POST 都收。SDK 未传入时会生成 uuid v4。24 小时内同键同正文重放第一次的回答 最短 1,最长 255 |
请求正文(必填)(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
kind | string | 是 | 本应用清单 realtime.docs[] 里声明的种类 |
ids | string[] | 是 | 文档 id 最多 100 项 |
响应
| 状态 | 说明 |
|---|---|
| 202 | 已通知 |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 404 | not_found:对应的记录不存在(客户中心没有这个客户,访客、服务或所指的东西不存在)。见 NotFound |
| 422 | 字段或参数不被接受(正文读不出来、有未知字段、缺必填、取值越界)。见 Unprocessable |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
POST /realtime/docs/revoke
从所有连接上收回这些文档
需要范围 app.realtime:write。English: takes these documents away from every sync connection, with a reason: forbidden, trashed or deleted.
只收应用自己的令牌(页面会话是 403 forbidden);每个应用在每个企业有调用额度(每秒 20 次,峰值 200),超过是 429,带 Retry-After。reason 是 forbidden(默认)、trashed 或 deleted。之后应用还要让这些文档的资源对人不再可见(否则重新连上又能打开);DELETE /realtime/docs/{id} 已经收回了被删的文档。ids 的规则同上。返回 202。
- 认证:
bearer - 范围:
app.realtime:write - operationId:
revokeRealtimeDocs
参数
| 名称 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
Idempotency-Key | header | string | 每个 POST 都收。SDK 未传入时会生成 uuid v4。24 小时内同键同正文重放第一次的回答 最短 1,最长 255 |
请求正文(必填)(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
kind | string | 是 | 本应用清单 realtime.docs[] 里声明的种类 |
ids | string[] | 是 | 文档 id 最多 100 项 |
reason | string | 原因,默认 forbidden 可选值: forbidden、trashed、deleted |
响应
| 状态 | 说明 |
|---|---|
| 202 | 已收回 |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 404 | not_found:对应的记录不存在(客户中心没有这个客户,访客、服务或所指的东西不存在)。见 NotFound |
| 422 | 字段或参数不被接受(正文读不出来、有未知字段、缺必填、取值越界)。见 Unprocessable |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
POST /realtime/topics/{topic}/publish
告诉一个主题的订阅者它变了
需要范围 app.realtime:write。English: tells the sync clients subscribed to a topic that it changed (they refetch over REST); fire and forget.
只收应用自己的令牌(页面会话是 403 forbidden);每个应用在每个企业有调用额度(每秒 20 次,峰值 200),超过是 429,带 Retry-After。topic 是 <资源类型>:<id>(<资源类型>:* 是这个类型的列表),类型必须在这个种类的 topics 里声明,否则 404 not_found(别的应用的类型也是)。version 原样交给订阅者。返回 202。
- 认证:
bearer - 范围:
app.realtime:write - operationId:
publishRealtimeTopic
参数
| 名称 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
topic | path | string | 是 | 主题:<资源类型>:<id> |
Idempotency-Key | header | string | 每个 POST 都收。SDK 未传入时会生成 uuid v4。24 小时内同键同正文重放第一次的回答 最短 1,最长 255 |
请求正文(必填)(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
kind | string | 是 | 声明了这个主题类型(topics)的种类 |
version | integer(int64) | 交给订阅者的版本号 |
响应
| 状态 | 说明 |
|---|---|
| 202 | 已发出 |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 404 | not_found:对应的记录不存在(客户中心没有这个客户,访客、服务或所指的东西不存在)。见 NotFound |
| 422 | 字段或参数不被接受(正文读不出来、有未知字段、缺必填、取值越界)。见 Unprocessable |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
POST /realtime/connections/invalidate
让本企业的连接重新核对权限
需要范围 app.realtime:write。English: re-authorises every sync connection of the tenant (roles, departments or members changed), of one kind or, when kind is omitted, of every kind.
只收应用自己的令牌(页面会话是 403 forbidden);每个应用在每个企业有调用额度(每秒 20 次,峰值 200),超过是 429,带 Retry-After。正文可省略(省略即所有种类)。返回 202。
- 认证:
bearer - 范围:
app.realtime:write - operationId:
invalidateRealtimeConnections
参数
| 名称 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
Idempotency-Key | header | string | 每个 POST 都收。SDK 未传入时会生成 uuid v4。24 小时内同键同正文重放第一次的回答 最短 1,最长 255 |
请求正文(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
kind | string | 种类;省略是所有种类 |
响应
| 状态 | 说明 |
|---|---|
| 202 | 已通知 |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 404 | not_found:对应的记录不存在(客户中心没有这个客户,访客、服务或所指的东西不存在)。见 NotFound |
| 422 | 字段或参数不被接受(正文读不出来、有未知字段、缺必填、取值越界)。见 Unprocessable |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
POST /realtime/connections/uninstalled
关闭本应用在本企业的所有连接
需要范围 app.realtime:write。English: closes every sync connection of the app in the tenant (close code 4004), of every kind; another app sharing a namespace keeps its own.
只收应用自己的令牌(页面会话是 403 forbidden);每个应用在每个企业有调用额度(每秒 20 次,峰值 200),超过是 429,带 Retry-After。返回 202。
- 认证:
bearer - 范围:
app.realtime:write - operationId:
closeRealtimeConnections
参数
| 名称 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
Idempotency-Key | header | string | 每个 POST 都收。SDK 未传入时会生成 uuid v4。24 小时内同键同正文重放第一次的回答 最短 1,最长 255 |
响应
| 状态 | 说明 |
|---|---|
| 202 | 已关闭 |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 404 | not_found:对应的记录不存在(客户中心没有这个客户,访客、服务或所指的东西不存在)。见 NotFound |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
POST /realtime/codecs/{codec}/meta
用平台的编码读一份 Office 状态的属性
需要范围 app.realtime:read。English: reads the properties of an Office state (the title, the hashes of the file's preserved parts, the engine) with the platform's codec. Codecs run only in the platform, so an app outside it checks an import here: the browser built the state from the file, and the app compares the state's properties with the file before it creates the document.
只收应用自己的令牌(页面会话是 403 forbidden);每个应用在每个企业有调用额度(每秒 20 次,峰值 200),超过是 429,带 Retry-After。codec 必须是本应用清单 realtime.docs[] 里某个种类的编码,否则 404 not_found。只有 Office 编码(quire-v1、ledger-v1、lectern-v1)有属性;别的编码、读不了的状态是 422 invalid。state 是 base64,请求正文最大 24 MiB。English: the app's own token only, within the control budget; the codec must be one the app's manifest declares; only the Office codecs have properties; the body is at most 24 MiB.
- 认证:
bearer - 范围:
app.realtime:read - operationId:
readRealtimeCodecMeta
参数
| 名称 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
codec | path | string | 是 | 编码:quire-v1(Word)、ledger-v1(Excel)、lectern-v1(PowerPoint) |
Idempotency-Key | header | string | 每个 POST 都收。SDK 未传入时会生成 uuid v4。24 小时内同键同正文重放第一次的回答 最短 1,最长 255 |
请求正文(必填)(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
state | string | 是 | base64 的状态(Yjs update v1,浏览器读文件时建的) |
响应
| 状态 | 说明 |
|---|---|
| 200 | 状态的属性 |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 404 | not_found:对应的记录不存在(客户中心没有这个客户,访客、服务或所指的东西不存在)。见 NotFound |
| 413 | payload_too_large:正文太大。见 PayloadTooLarge |
| 422 | 字段或参数不被接受(正文读不出来、有未知字段、缺必填、取值越界)。见 Unprocessable |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
200 响应正文(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
meta | map[string, string] | 是 | 属性:title、base / fragments(文件保留部分的 SHA-256)、engine 等 |
resources
资源与分享:本应用声明的资源类型,由平台保存所有者、名单、通用访问、开关和申请,并批量回答谁能看;带 parent 的类型走树模型(继承的节点名单、状态、集合)
GET /access/{type}/{id}
读一个资源的访问名单(按调用者能看到的)
需要范围 app.resources:read。English: the list of one resource as the caller may see it: owner, general access, switches, grants, the caller's level.
正文与规则同平台内置应用的 /api/access/{type}/{id}…(同一套访问内核:规则、审计、通知都一样)。只收页面会话:应用自己的令牌是 403 forbidden(分享是人做的事)。类型不是本应用声明的,或资源没登记,一律 404 not_found。名单变了以后,平台把事件 access.changed 送给应用(见 webhooks)。
平铺类型上,应用自己的令牌可以读整个名单(包括已过期的条目,应用按自己的时钟判断):me 为 manage。用于应用按自己的权限点决定谁能授权的类型(例如会员的敏感记录)。English: on a flat type the app's own token reads the whole list, expired grants included.
调用者对资源没有查看级别时是 404 not_found,要申请访问见 POST …/requests。
树类型:返回 AccessTreeView:显式名单 entries、根或节点指向的集合 set、调用者经状态限制后的级别 level 和原因 reason。页面会话没有查看级别时 404 not_found;应用自己的令牌可带 user 查某人的级别(不带就只有名单和集合),根或节点不存在时 404 not_found。English: on a tree type the answer is the explicit entries, the set and the caller's level after the states.
- 认证:
bearer - 范围:
app.resources:read - operationId:
getResourceAccess
参数
| 名称 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
type | path | string | 是 | 资源类型,本应用在清单 resources[] 里声明的 {应用 id}.{名字} |
id | path | string | 是 | 资源 id(应用自己的记录 id,最多 200 字符) |
user | query | string | 树类型、应用自己的令牌:查谁的级别(可省略) | |
agent | query | boolean | 树类型:按这个人的智能体算级别(最多 comment) |
响应
| 状态 | 说明 |
|---|---|
| 200 | 名单 |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 404 | not_found:对应的记录不存在(客户中心没有这个客户,访客、服务或所指的东西不存在)。见 NotFound |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
200 响应正文(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
type | string | 是 | |
id | string | 是 | |
owner | string | 是 | 所有者的 user id |
ownerName | string | 是 | 所有者的显示名;不知道时为空 |
general | string | 是 | 通用访问:空字符串、view、comment 或 edit。空字符串是只有名单上的人 |
toggles | map[string, boolean] | 是 | 类型声明的每个开关和它现在的值 |
grants | ResourceGrant[] | 是 | |
grants[].kind | string | 是 | user、unit(部门)、role 或 everyone |
grants[].principal | string | 是 | 对象 id;everyone 为空字符串 |
grants[].name | string | 是 | 显示名 |
grants[].level | string | 是 | 访问级别,由低到高。类型可以不开放 comment 或 manage 以上的级别 可选值: view、comment、edit、manage |
grants[].note | string | 说明(为什么给),没有时省略 | |
grants[].expiresAt | string(date-time) | ||
grants[].createdBy | string | 是 | |
grants[].createdAt | string(date-time) | 是 | |
me | string | 是 | 调用者的级别 |
canShare | boolean | 是 | |
isOwner | boolean | 是 | |
pending | integer | 是 | 等着处理的申请数(只有能处理的人看得到) |
managers | string[] | 是 | 能管理的人的显示名(所有者在前,最多 5 个),让只读的人知道该找谁 |
levels | string[] | 是 | 这个类型提供的级别,由低到高 |
POST /access/{type}/{id}
登记一个资源(写下它的所有者)
需要范围 app.resources:write。English: registers a resource of a declared type with its owner; idempotent.
type 必须是本应用清单 resources[] 里声明的类型(以 {本应用 id}. 开头),否则 404 not_found。页面会话登记的资源,所有者就是这个人;应用自己的令牌必须在正文里写 owner。正文可省略。重复登记同一个资源不会出错。登记后文档、记录的名单、通用访问、开关都由平台保存。
树类型(清单里带 parent 的类型和被它当作 parent 的类型,规则见 POST …/check):正文是 AccessTreePut。根类型写 archived、publishOnly;节点类型写 root(在根的顶层时必填,有 parent 时以父节点的根为准)、parent、inherit(省略为 true)、trashed。移到别的父节点或别的根时整棵子树跟着走,平台重新计算受影响节点的集合。只收应用自己的令牌(页面会话是 403 forbidden:移动会改变节点继承的名单,树的形状由应用按自己的规则维护)。返回 AccessTreeChanged,changed 是集合变了的节点 id 到新集合 id。一次改动最多重新计算 5000 个节点(整个根 20000 个),超过是 422 invalid。English: on a tree type the body puts a root's state or a node's place and state (idempotent, the app's token only); the answer lists the nodes whose set changed.
- 认证:
bearer - 范围:
app.resources:write - operationId:
registerResource
参数
| 名称 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
type | path | string | 是 | 资源类型,本应用在清单 resources[] 里声明的 {应用 id}.{名字} |
id | path | string | 是 | 资源 id(应用自己的记录 id,最多 200 字符) |
Idempotency-Key | header | string | 每个 POST 都收。SDK 未传入时会生成 uuid v4。24 小时内同键同正文重放第一次的回答 最短 1,最长 255 |
请求正文(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
owner | string | 所有者的 user id。应用自己的令牌必填(平铺类型) | |
root | string | 树类型的节点:所在的根(顶层节点必填) | |
parent | string | 树类型的节点:父节点;省略为根的顶层 | |
inherit | boolean | 树类型的节点:是否继承上级名单,省略为 true | |
trashed | boolean | 树类型的节点:在应用的回收站里 | |
archived | boolean | 树类型的根:已归档 | |
publishOnly | boolean | 树类型的根:edit 以下按已发布版本读 |
响应
| 状态 | 说明 |
|---|---|
| 200 | 已登记 |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 404 | not_found:对应的记录不存在(客户中心没有这个客户,访客、服务或所指的东西不存在)。见 NotFound |
| 409 | 见 Conflict |
| 413 | payload_too_large:正文太大。见 PayloadTooLarge |
| 422 | 字段或参数不被接受(正文读不出来、有未知字段、缺必填、取值越界)。见 Unprocessable |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
200 响应正文(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
type | string | 是 | |
id | string | 是 | |
owner | string | 是 |
DELETE /access/{type}/{id}
删除一个资源的登记(连同名单和申请)
需要范围 app.resources:write。English: drops the resource's row: its list and its requests.
页面会话需要对这个资源有管理级别,否则 404 not_found;应用自己的令牌不受级别限制。返回 204。
树类型:只收应用自己的令牌(页面会话是 403 forbidden)。删除节点只删这一个(应用写出整棵子树的每个节点),删除根连同它下面的全部节点和名单。English: on a tree type only the app's token removes; a node is removed alone (the app names the whole subtree), a root with every node under it.
- 认证:
bearer - 范围:
app.resources:write - operationId:
dropResource
参数
| 名称 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
type | path | string | 是 | 资源类型,本应用在清单 resources[] 里声明的 {应用 id}.{名字} |
id | path | string | 是 | 资源 id(应用自己的记录 id,最多 200 字符) |
响应
| 状态 | 说明 |
|---|---|
| 204 | 已删除 |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 404 | not_found:对应的记录不存在(客户中心没有这个客户,访客、服务或所指的东西不存在)。见 NotFound |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
PUT /access/{type}/{id}/grants
整体替换树类型一个根或节点的显式名单
需要范围 app.resources:write。English: replaces every explicit entry of a root or node of a tree type and recomputes the sets that changes.
只用于树类型(平铺类型是 404 not_found)。entries 是全部条目:kind 为 user、unit(部门,含下级)、role、everyone(principal 为空字符串),level 为 view、comment、edit、manage,name 是显示名的快照。应用自己的令牌可以调用,并可用 by 写明替谁改;页面会话需要管理级别(名单给出的级别),看不到是 404 not_found,不能管理是 403 forbidden。返回 AccessTreeChanged;平台把事件 access.changed 送给应用,并记审计 access.tree.entries。
- 认证:
bearer - 范围:
app.resources:write - operationId:
replaceResourceEntries
参数
| 名称 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
type | path | string | 是 | 资源类型,本应用在清单 resources[] 里声明的 {应用 id}.{名字} |
id | path | string | 是 | 资源 id(应用自己的记录 id,最多 200 字符) |
请求正文(必填)(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
entries | AccessTreeEntry[] | 是 | |
entries[].kind | string | 是 | user、unit(部门,含下级)、role 或 everyone 可选值: user、unit、role、everyone |
entries[].principal | string | 是 | 对象 id;everyone 为空字符串 |
entries[].level | string | 是 | 访问级别,由低到高。类型可以不开放 comment 或 manage 以上的级别 可选值: view、comment、edit、manage |
entries[].name | string | 显示名的快照;判断只看 kind 和 principal | |
entries[].at | string(date-time) | 这条写入的时间(显式名单才有;有效名单里为空) | |
entries[].expiresAt | string(date-time),可为 null | 到期时间:之后这条不再给任何权限,平台把它清掉并重新计算集合;省略或 null 是不限时;已经过去的时间是 422 invalid(有效名单里没有) | |
by | string | 应用自己的令牌:替谁改,记在名单上;页面会话忽略 |
响应
| 状态 | 说明 |
|---|---|
| 200 | 集合变了的节点 |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 404 | not_found:对应的记录不存在(客户中心没有这个客户,访客、服务或所指的东西不存在)。见 NotFound |
| 422 | 字段或参数不被接受(正文读不出来、有未知字段、缺必填、取值越界)。见 Unprocessable |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
200 响应正文(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
type | string | ||
id | string | ||
changed | map[string, string] | 是 | 节点 id 到它现在的集合 id(重新鉴权它打开的文档,更新应用保存的集合 id) |
示例:
{
"type": "wiki.page",
"id": "pg_1",
"changed": {
"pg_1": "5f0c2a9e41d7b3c8a6e2f104",
"pg_2": "5f0c2a9e41d7b3c8a6e2f104"
}
}POST /access/{type}/{id}/grants
分享给一个人、部门、角色或所有人
需要范围 app.resources:write。English: adds or changes one grant on the resource.
正文与规则同平台内置应用的 /api/access/{type}/{id}…(同一套访问内核:规则、审计、通知都一样)。只收页面会话:应用自己的令牌是 403 forbidden(分享是人做的事)。类型不是本应用声明的,或资源没登记,一律 404 not_found。名单变了以后,平台把事件 access.changed 送给应用(见 webhooks)。
平铺类型上,应用自己的令牌也可以调用:以应用的名义加一条或改一条(不看调用者的级别,规则由应用自己定,例如会员的敏感记录只有持有管理授权权限的人能授),资源没登记时一并登记(所有者为 app:{应用 id});by 写明替谁授(名单上的 createdBy),note 是说明。级别、对象和到期时间的规则同上;不通知对方。审计动作 access.share。English: on a flat type the app's own token adds or replaces a grant as the app (registering the resource), with by and note.
kind 是 user、unit(部门)、role、everyone(所有人)之一,level 是 view、comment、edit 或 manage,expiresAt 省略为不过期。调用者需要有分享的权力(管理级别,或类型开着允许分享的开关)。给人的分享会通知对方。
树类型:在根或节点的显式名单上加一条或改一条(同一 kind + principal 只有一条),正文同上,expiresAt 是这一条的到期时间。级别不能超过类型声明的 levels。应用自己的令牌可以调用;页面会话需要对这个根或节点有管理级别(名单给出的级别,不看状态),或者在开了 reshare 的根下能编辑这个节点(只能给到、改到 edit),看不到是 404 not_found,看得到但不能管理是 403 forbidden。返回 AccessTreeChanged。审计动作 access.tree.entries。English: on a tree type adds or changes one explicit entry; a person needs manage.
- 认证:
bearer - 范围:
app.resources:write - operationId:
shareResource
参数
| 名称 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
type | path | string | 是 | 资源类型,本应用在清单 resources[] 里声明的 {应用 id}.{名字} |
id | path | string | 是 | 资源 id(应用自己的记录 id,最多 200 字符) |
Idempotency-Key | header | string | 每个 POST 都收。SDK 未传入时会生成 uuid v4。24 小时内同键同正文重放第一次的回答 最短 1,最长 255 |
请求正文(必填)(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
kind | string | 是 | user、unit(部门)、role 或 everyone |
principal | string | 是 | 对象 id |
name | string | 显示名,留在名单上 | |
level | string | 是 | 访问级别,由低到高。类型可以不开放 comment 或 manage 以上的级别 可选值: view、comment、edit、manage |
expiresAt | string(date-time) | 省略为不过期 | |
note | string | 说明,留在名单上(为什么给) 最长 200 | |
by | string | 只用于应用自己的令牌:替谁授(名单上的 createdBy);省略为应用自己 |
响应
| 状态 | 说明 |
|---|---|
| 200 | 写入的分享 |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 404 | not_found:对应的记录不存在(客户中心没有这个客户,访客、服务或所指的东西不存在)。见 NotFound |
| 409 | 见 Conflict |
| 413 | payload_too_large:正文太大。见 PayloadTooLarge |
| 422 | 字段或参数不被接受(正文读不出来、有未知字段、缺必填、取值越界)。见 Unprocessable |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
200 响应正文(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
kind | string | 是 | user、unit(部门)、role 或 everyone |
principal | string | 是 | 对象 id;everyone 为空字符串 |
name | string | 是 | 显示名 |
level | string | 是 | 访问级别,由低到高。类型可以不开放 comment 或 manage 以上的级别 可选值: view、comment、edit、manage |
note | string | 说明(为什么给),没有时省略 | |
expiresAt | string(date-time) | ||
createdBy | string | 是 | |
createdAt | string(date-time) | 是 |
DELETE /access/{type}/{id}/grants/{kind}/{principal}
撤销一条分享
需要范围 app.resources:write。English: removes one grant.
正文与规则同平台内置应用的 /api/access/{type}/{id}…(同一套访问内核:规则、审计、通知都一样)。只收页面会话:应用自己的令牌是 403 forbidden(分享是人做的事)。类型不是本应用声明的,或资源没登记,一律 404 not_found。名单变了以后,平台把事件 access.changed 送给应用(见 webhooks)。
平铺类型上,应用自己的令牌也可以调用:以应用的名义删掉一条(没有这条是 404 not_found)。审计动作 access.revoke。English: on a flat type the app's own token removes a grant as the app.
对象是 everyone 的分享,principal 写 -。
树类型:从根或节点的显式名单删掉一条(没有这条是 404 not_found),权限规则同 POST …/grants,返回 AccessTreeChanged。English: on a tree type removes one explicit entry.
- 认证:
bearer - 范围:
app.resources:write - operationId:
revokeResourceGrant
参数
| 名称 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
type | path | string | 是 | 资源类型,本应用在清单 resources[] 里声明的 {应用 id}.{名字} |
id | path | string | 是 | 资源 id(应用自己的记录 id,最多 200 字符) |
kind | path | string | 是 | 分享对象的种类:user、unit、role、everyone |
principal | path | string | 是 | 分享对象的 id(everyone 写 -) |
响应
| 状态 | 说明 |
|---|---|
| 200 | 已撤销 |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 404 | not_found:对应的记录不存在(客户中心没有这个客户,访客、服务或所指的东西不存在)。见 NotFound |
| 409 | 见 Conflict |
| 422 | 字段或参数不被接受(正文读不出来、有未知字段、缺必填、取值越界)。见 Unprocessable |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
200 响应正文(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
ok | boolean | 是 |
PUT /access/{type}/{id}/general
设置通用访问(企业内知道链接的人能做什么)
需要范围 app.resources:write。English: sets the general access of the resource.
正文与规则同平台内置应用的 /api/access/{type}/{id}…(同一套访问内核:规则、审计、通知都一样)。只收页面会话:应用自己的令牌是 403 forbidden(分享是人做的事)。类型不是本应用声明的,或资源没登记,一律 404 not_found。名单变了以后,平台把事件 access.changed 送给应用(见 webhooks)。
level 是空字符串(只有名单上的人)、view、comment 或 edit;类型不开放评论时不能设 comment。
- 认证:
bearer - 范围:
app.resources:write - operationId:
setResourceGeneral
参数
| 名称 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
type | path | string | 是 | 资源类型,本应用在清单 resources[] 里声明的 {应用 id}.{名字} |
id | path | string | 是 | 资源 id(应用自己的记录 id,最多 200 字符) |
请求正文(必填)(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
level | string | 是 | 空字符串:只有名单上的人 可选值:``、 view、comment、edit |
响应
| 状态 | 说明 |
|---|---|
| 200 | 新的通用访问 |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 404 | not_found:对应的记录不存在(客户中心没有这个客户,访客、服务或所指的东西不存在)。见 NotFound |
| 409 | 见 Conflict |
| 413 | payload_too_large:正文太大。见 PayloadTooLarge |
| 422 | 字段或参数不被接受(正文读不出来、有未知字段、缺必填、取值越界)。见 Unprocessable |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
200 响应正文(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
general | string | 是 | 设置后的通用访问 |
PUT /access/{type}/{id}/toggles
设置资源的开关
需要范围 app.resources:write。English: sets the switches the type declares (resources[].switches), e.g. explore, and returns the list.
正文与规则同平台内置应用的 /api/access/{type}/{id}…(同一套访问内核:规则、审计、通知都一样)。只收页面会话:应用自己的令牌是 403 forbidden(分享是人做的事)。类型不是本应用声明的,或资源没登记,一律 404 not_found。名单变了以后,平台把事件 access.changed 送给应用(见 webhooks)。
正文是 {开关名: true|false},只能写类型声明过的开关。
- 认证:
bearer - 范围:
app.resources:write - operationId:
setResourceToggles
参数
| 名称 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
type | path | string | 是 | 资源类型,本应用在清单 resources[] 里声明的 {应用 id}.{名字} |
id | path | string | 是 | 资源 id(应用自己的记录 id,最多 200 字符) |
请求正文(必填)(application/json)
类型 ResourceToggles。开关名到值,只能写类型声明过的开关
响应
| 状态 | 说明 |
|---|---|
| 200 | 更新后的名单 |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 404 | not_found:对应的记录不存在(客户中心没有这个客户,访客、服务或所指的东西不存在)。见 NotFound |
| 409 | 见 Conflict |
| 413 | payload_too_large:正文太大。见 PayloadTooLarge |
| 422 | 字段或参数不被接受(正文读不出来、有未知字段、缺必填、取值越界)。见 Unprocessable |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
200 响应正文(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
type | string | 是 | |
id | string | 是 | |
owner | string | 是 | 所有者的 user id |
ownerName | string | 是 | 所有者的显示名;不知道时为空 |
general | string | 是 | 通用访问:空字符串、view、comment 或 edit。空字符串是只有名单上的人 |
toggles | map[string, boolean] | 是 | 类型声明的每个开关和它现在的值 |
grants | ResourceGrant[] | 是 | |
grants[].kind | string | 是 | user、unit(部门)、role 或 everyone |
grants[].principal | string | 是 | 对象 id;everyone 为空字符串 |
grants[].name | string | 是 | 显示名 |
grants[].level | string | 是 | 访问级别,由低到高。类型可以不开放 comment 或 manage 以上的级别 可选值: view、comment、edit、manage |
grants[].note | string | 说明(为什么给),没有时省略 | |
grants[].expiresAt | string(date-time) | ||
grants[].createdBy | string | 是 | |
grants[].createdAt | string(date-time) | 是 | |
me | string | 是 | 调用者的级别 |
canShare | boolean | 是 | |
isOwner | boolean | 是 | |
pending | integer | 是 | 等着处理的申请数(只有能处理的人看得到) |
managers | string[] | 是 | 能管理的人的显示名(所有者在前,最多 5 个),让只读的人知道该找谁 |
levels | string[] | 是 | 这个类型提供的级别,由低到高 |
POST /access/{type}/{id}/owner
转让资源的所有权
需要范围 app.resources:write。English: transfers the owner of the resource to another person; notifies them.
正文与规则同平台内置应用的 /api/access/{type}/{id}…(同一套访问内核:规则、审计、通知都一样)。只收页面会话:应用自己的令牌是 403 forbidden(分享是人做的事)。类型不是本应用声明的,或资源没登记,一律 404 not_found。名单变了以后,平台把事件 access.changed 送给应用(见 webhooks)。
只有所有者(或管理员)能转让。to 必填,name 是对方的显示名。
- 认证:
bearer - 范围:
app.resources:write - operationId:
transferResource
参数
| 名称 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
type | path | string | 是 | 资源类型,本应用在清单 resources[] 里声明的 {应用 id}.{名字} |
id | path | string | 是 | 资源 id(应用自己的记录 id,最多 200 字符) |
Idempotency-Key | header | string | 每个 POST 都收。SDK 未传入时会生成 uuid v4。24 小时内同键同正文重放第一次的回答 最短 1,最长 255 |
请求正文(必填)(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
to | string | 是 | 新所有者的 user id |
name | string | 新所有者的显示名 |
响应
| 状态 | 说明 |
|---|---|
| 200 | 新的所有者 |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 404 | not_found:对应的记录不存在(客户中心没有这个客户,访客、服务或所指的东西不存在)。见 NotFound |
| 409 | 见 Conflict |
| 413 | payload_too_large:正文太大。见 PayloadTooLarge |
| 422 | 字段或参数不被接受(正文读不出来、有未知字段、缺必填、取值越界)。见 Unprocessable |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
200 响应正文(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
owner | string | 是 | 新的所有者 |
GET /access/{type}/{id}/requests
读调用者自己对一个资源的申请
需要范围 app.resources:read。English: the caller's own requests on the resource, newest first, at most 100.
正文与规则同平台内置应用的 /api/access/{type}/{id}…(同一套访问内核:规则、审计、通知都一样)。只收页面会话:应用自己的令牌是 403 forbidden(分享是人做的事)。类型不是本应用声明的,或资源没登记,一律 404 not_found。名单变了以后,平台把事件 access.changed 送给应用(见 webhooks)。
- 认证:
bearer - 范围:
app.resources:read - operationId:
listResourceRequests
参数
| 名称 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
type | path | string | 是 | 资源类型,本应用在清单 resources[] 里声明的 {应用 id}.{名字} |
id | path | string | 是 | 资源 id(应用自己的记录 id,最多 200 字符) |
响应
| 状态 | 说明 |
|---|---|
| 200 | 申请 |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 404 | not_found:对应的记录不存在(客户中心没有这个客户,访客、服务或所指的东西不存在)。见 NotFound |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
200 响应正文(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
requests | ResourceRequest[] | 是 | |
requests[].id | string | 是 | |
requests[].type | string | 是 | |
requests[].resource | string | 是 | |
requests[].requester | string | 是 | |
requests[].requesterName | string | 是 | |
requests[].note | string | 是 | |
requests[].status | string | 是 | 可选值:pending、approved、denied、cancelled |
requests[].decidedBy | string | ||
requests[].decidedByName | string | ||
requests[].expiresAt | string(date-time) | ||
requests[].createdAt | string(date-time) | 是 | |
requests[].decidedAt | string(date-time) | ||
requests[].reason | string | 拒绝的原因 | |
requests[].app | string | 申请从哪个应用提出 | |
requests[].origin | string | 应用里的哪个页面 | |
requests[].level | string | 是 | 申请的级别 |
requests[].granted | string | 批准的级别 | |
requests[].retryAfter | string(date-time) | 被拒绝后 24 小时的冷却何时结束 | |
requests[].title | string | 资源的标题,只给能处理它的人 |
POST /access/{type}/{id}/requests
为自己申请访问一个资源
需要范围 app.resources:write。English: files a request for access (or a higher level) on the resource, as the caller; notifies the people who decide.
正文与规则同平台内置应用的 /api/access/{type}/{id}…(同一套访问内核:规则、审计、通知都一样)。只收页面会话:应用自己的令牌是 403 forbidden(分享是人做的事)。类型不是本应用声明的,或资源没登记,一律 404 not_found。名单变了以后,平台把事件 access.changed 送给应用(见 webhooks)。
类型没有开放申请,或调用者已经有这个级别,是 409 conflict;被拒绝后 24 小时内不能再申请(retryAfter)。level 省略是 view。
- 认证:
bearer - 范围:
app.resources:write - operationId:
requestResourceAccess
参数
| 名称 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
type | path | string | 是 | 资源类型,本应用在清单 resources[] 里声明的 {应用 id}.{名字} |
id | path | string | 是 | 资源 id(应用自己的记录 id,最多 200 字符) |
Idempotency-Key | header | string | 每个 POST 都收。SDK 未传入时会生成 uuid v4。24 小时内同键同正文重放第一次的回答 最短 1,最长 255 |
请求正文(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
level | string | 访问级别,由低到高。类型可以不开放 comment 或 manage 以上的级别 可选值: view、comment、edit、manage | |
note | string | 给处理的人看的话 |
响应
| 状态 | 说明 |
|---|---|
| 200 | 申请 |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 404 | not_found:对应的记录不存在(客户中心没有这个客户,访客、服务或所指的东西不存在)。见 NotFound |
| 409 | 见 Conflict |
| 413 | payload_too_large:正文太大。见 PayloadTooLarge |
| 422 | 字段或参数不被接受(正文读不出来、有未知字段、缺必填、取值越界)。见 Unprocessable |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
200 响应正文(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
id | string | 是 | |
type | string | 是 | |
resource | string | 是 | |
requester | string | 是 | |
requesterName | string | 是 | |
note | string | 是 | |
status | string | 是 | 可选值:pending、approved、denied、cancelled |
decidedBy | string | ||
decidedByName | string | ||
expiresAt | string(date-time) | ||
createdAt | string(date-time) | 是 | |
decidedAt | string(date-time) | ||
reason | string | 拒绝的原因 | |
app | string | 申请从哪个应用提出 | |
origin | string | 应用里的哪个页面 | |
level | string | 是 | 申请的级别 |
granted | string | 批准的级别 | |
retryAfter | string(date-time) | 被拒绝后 24 小时的冷却何时结束 | |
title | string | 资源的标题,只给能处理它的人 |
GET /access/requests
读调用者能处理的待处理申请
需要范围 app.resources:read。English: every pending request on this app's types that the caller may decide, with the resource's title, oldest first.
正文与规则同平台内置应用的 /api/access/requests…。只收页面会话:应用自己的令牌是 403 forbidden(申请和处理都是人做的事)。只含本应用在清单里声明、开放申请(requestable)的类型。平面类型由访问内核的名单决定谁处理(所有者和管理者);树类型(知识库页面)的名单是应用自己的树,由应用通过提供者 accessRequests 回答调用者在资源上的级别、通知谁、批准怎么写入;应用不提供时,树类型不收申请(404)。
- 认证:
bearer - 范围:
app.resources:read - operationId:
listDecidableResourceRequests
响应
| 状态 | 说明 |
|---|---|
| 200 | 申请列表 |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
200 响应正文(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
requests | ResourceRequest[] | 是 | |
requests[].id | string | 是 | |
requests[].type | string | 是 | |
requests[].resource | string | 是 | |
requests[].requester | string | 是 | |
requests[].requesterName | string | 是 | |
requests[].note | string | 是 | |
requests[].status | string | 是 | 可选值:pending、approved、denied、cancelled |
requests[].decidedBy | string | ||
requests[].decidedByName | string | ||
requests[].expiresAt | string(date-time) | ||
requests[].createdAt | string(date-time) | 是 | |
requests[].decidedAt | string(date-time) | ||
requests[].reason | string | 拒绝的原因 | |
requests[].app | string | 申请从哪个应用提出 | |
requests[].origin | string | 应用里的哪个页面 | |
requests[].level | string | 是 | 申请的级别 |
requests[].granted | string | 批准的级别 | |
requests[].retryAfter | string(date-time) | 被拒绝后 24 小时的冷却何时结束 | |
requests[].title | string | 资源的标题,只给能处理它的人 |
GET /access/requests/mine
读调用者自己的申请
需要范围 app.resources:read。English: the caller's own requests on this app's types, newest first, at most 100 (no titles).
正文与规则同平台内置应用的 /api/access/requests…。只收页面会话:应用自己的令牌是 403 forbidden(申请和处理都是人做的事)。只含本应用在清单里声明、开放申请(requestable)的类型。平面类型由访问内核的名单决定谁处理(所有者和管理者);树类型(知识库页面)的名单是应用自己的树,由应用通过提供者 accessRequests 回答调用者在资源上的级别、通知谁、批准怎么写入;应用不提供时,树类型不收申请(404)。
- 认证:
bearer - 范围:
app.resources:read - operationId:
listMyResourceRequests
响应
| 状态 | 说明 |
|---|---|
| 200 | 申请列表 |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
200 响应正文(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
requests | ResourceRequest[] | 是 | |
requests[].id | string | 是 | |
requests[].type | string | 是 | |
requests[].resource | string | 是 | |
requests[].requester | string | 是 | |
requests[].requesterName | string | 是 | |
requests[].note | string | 是 | |
requests[].status | string | 是 | 可选值:pending、approved、denied、cancelled |
requests[].decidedBy | string | ||
requests[].decidedByName | string | ||
requests[].expiresAt | string(date-time) | ||
requests[].createdAt | string(date-time) | 是 | |
requests[].decidedAt | string(date-time) | ||
requests[].reason | string | 拒绝的原因 | |
requests[].app | string | 申请从哪个应用提出 | |
requests[].origin | string | 应用里的哪个页面 | |
requests[].level | string | 是 | 申请的级别 |
requests[].granted | string | 批准的级别 | |
requests[].retryAfter | string(date-time) | 被拒绝后 24 小时的冷却何时结束 | |
requests[].title | string | 资源的标题,只给能处理它的人 |
POST /access/requests/{rid}/approve
批准一条申请
需要范围 app.resources:write。English: approves a pending request the caller may decide: the level (at most what was asked; omitted: what was asked), optionally until expiresAt.
正文与规则同平台内置应用的 /api/access/requests…。只收页面会话:应用自己的令牌是 403 forbidden(申请和处理都是人做的事)。只含本应用在清单里声明、开放申请(requestable)的类型。平面类型由访问内核的名单决定谁处理(所有者和管理者);树类型(知识库页面)的名单是应用自己的树,由应用通过提供者 accessRequests 回答调用者在资源上的级别、通知谁、批准怎么写入;应用不提供时,树类型不收申请(404)。调用者不能处理是 404;已处理过是 409。树类型由应用写入批准,应用拒绝(例如超出处理人能给的级别)时原样返回它的状态和说明。
- 认证:
bearer - 范围:
app.resources:write - operationId:
approveResourceRequest
参数
| 名称 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
rid | path | string | 是 | 申请 id |
Idempotency-Key | header | string | 每个 POST 都收。SDK 未传入时会生成 uuid v4。24 小时内同键同正文重放第一次的回答 最短 1,最长 255 |
请求正文(必填)(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
level | string | 批准的级别(view、comment、edit),省略为申请的级别 | |
expiresAt | string(date-time) | 到期时间,省略为长期 |
响应
| 状态 | 说明 |
|---|---|
| 200 | 申请 |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 404 | not_found:对应的记录不存在(客户中心没有这个客户,访客、服务或所指的东西不存在)。见 NotFound |
| 409 | 见 Conflict |
| 422 | 字段或参数不被接受(正文读不出来、有未知字段、缺必填、取值越界)。见 Unprocessable |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
200 响应正文(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
id | string | 是 | |
type | string | 是 | |
resource | string | 是 | |
requester | string | 是 | |
requesterName | string | 是 | |
note | string | 是 | |
status | string | 是 | 可选值:pending、approved、denied、cancelled |
decidedBy | string | ||
decidedByName | string | ||
expiresAt | string(date-time) | ||
createdAt | string(date-time) | 是 | |
decidedAt | string(date-time) | ||
reason | string | 拒绝的原因 | |
app | string | 申请从哪个应用提出 | |
origin | string | 应用里的哪个页面 | |
level | string | 是 | 申请的级别 |
granted | string | 批准的级别 | |
retryAfter | string(date-time) | 被拒绝后 24 小时的冷却何时结束 | |
title | string | 资源的标题,只给能处理它的人 |
POST /access/requests/{rid}/deny
拒绝一条申请
需要范围 app.resources:write。English: refuses a pending request the caller may decide, with the reason the requester is told (required, at most 200 characters).
正文与规则同平台内置应用的 /api/access/requests…。只收页面会话:应用自己的令牌是 403 forbidden(申请和处理都是人做的事)。只含本应用在清单里声明、开放申请(requestable)的类型。平面类型由访问内核的名单决定谁处理(所有者和管理者);树类型(知识库页面)的名单是应用自己的树,由应用通过提供者 accessRequests 回答调用者在资源上的级别、通知谁、批准怎么写入;应用不提供时,树类型不收申请(404)。
- 认证:
bearer - 范围:
app.resources:write - operationId:
denyResourceRequest
参数
| 名称 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
rid | path | string | 是 | 申请 id |
Idempotency-Key | header | string | 每个 POST 都收。SDK 未传入时会生成 uuid v4。24 小时内同键同正文重放第一次的回答 最短 1,最长 255 |
请求正文(必填)(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
reason | string | 是 | 拒绝的原因,申请人会看到 最长 200 |
响应
| 状态 | 说明 |
|---|---|
| 200 | 申请 |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 404 | not_found:对应的记录不存在(客户中心没有这个客户,访客、服务或所指的东西不存在)。见 NotFound |
| 409 | 见 Conflict |
| 422 | 字段或参数不被接受(正文读不出来、有未知字段、缺必填、取值越界)。见 Unprocessable |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
200 响应正文(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
id | string | 是 | |
type | string | 是 | |
resource | string | 是 | |
requester | string | 是 | |
requesterName | string | 是 | |
note | string | 是 | |
status | string | 是 | 可选值:pending、approved、denied、cancelled |
decidedBy | string | ||
decidedByName | string | ||
expiresAt | string(date-time) | ||
createdAt | string(date-time) | 是 | |
decidedAt | string(date-time) | ||
reason | string | 拒绝的原因 | |
app | string | 申请从哪个应用提出 | |
origin | string | 应用里的哪个页面 | |
level | string | 是 | 申请的级别 |
granted | string | 批准的级别 | |
retryAfter | string(date-time) | 被拒绝后 24 小时的冷却何时结束 | |
title | string | 资源的标题,只给能处理它的人 |
DELETE /access/requests/{rid}
撤回自己的申请
需要范围 app.resources:write。English: withdraws the caller's own pending request.
正文与规则同平台内置应用的 /api/access/requests…。只收页面会话:应用自己的令牌是 403 forbidden(申请和处理都是人做的事)。只含本应用在清单里声明、开放申请(requestable)的类型。平面类型由访问内核的名单决定谁处理(所有者和管理者);树类型(知识库页面)的名单是应用自己的树,由应用通过提供者 accessRequests 回答调用者在资源上的级别、通知谁、批准怎么写入;应用不提供时,树类型不收申请(404)。
- 认证:
bearer - 范围:
app.resources:write - operationId:
cancelResourceRequest
参数
| 名称 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
rid | path | string | 是 | 申请 id |
响应
| 状态 | 说明 |
|---|---|
| 200 | 申请 |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 404 | not_found:对应的记录不存在(客户中心没有这个客户,访客、服务或所指的东西不存在)。见 NotFound |
| 409 | 见 Conflict |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
200 响应正文(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
id | string | 是 | |
type | string | 是 | |
resource | string | 是 | |
requester | string | 是 | |
requesterName | string | 是 | |
note | string | 是 | |
status | string | 是 | 可选值:pending、approved、denied、cancelled |
decidedBy | string | ||
decidedByName | string | ||
expiresAt | string(date-time) | ||
createdAt | string(date-time) | 是 | |
decidedAt | string(date-time) | ||
reason | string | 拒绝的原因 | |
app | string | 申请从哪个应用提出 | |
origin | string | 应用里的哪个页面 | |
level | string | 是 | 申请的级别 |
granted | string | 批准的级别 | |
retryAfter | string(date-time) | 被拒绝后 24 小时的冷却何时结束 | |
title | string | 资源的标题,只给能处理它的人 |
GET /access/{type}
一个资源类型的声明
需要范围 app.resources:read。English: the declared kind as the platform keeps it: what one resource of it is called (name in Chinese, nameEn in English, from the manifest's resources[]; empty when not declared), its levels and switches, whether it takes requests or can be published, and whether it is a tree type (tree, with parent on a node type).
平台的分享对话框用 name / nameEn 称呼这个资源(「这个笔记」);没写时说「这个内容」。levels 没声明时是全部四级,switches 没声明时是空对象。本应用当前安装的版本没有声明这个类型(或类型不以 {本应用 id}. 开头)是 404 not_found:分享对话框据此区分「类型没登记」和「这一项找不到」。
- 认证:
bearer - 范围:
app.resources:read - operationId:
getResourceKind
参数
| 名称 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
type | path | string | 是 | 资源类型,本应用在清单 resources[] 里声明的 {应用 id}.{名字} |
响应
| 状态 | 说明 |
|---|---|
| 200 | 类型的声明 |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 404 | not_found:对应的记录不存在(客户中心没有这个客户,访客、服务或所指的东西不存在)。见 NotFound |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
200 响应正文(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
type | string | 是 | {应用 id}.{名字} |
name | string | 是 | 一个这种资源的叫法(中文,最多 20 字,如「笔记」);没声明时为空字符串 |
nameEn | string | 是 | 同一个叫法的英文(如 note);没声明时为空字符串 |
parent | string | 节点类型所在的根类型;平铺类型和根类型省略 | |
tree | boolean | 是 | 树类型(带 parent 的类型,或被别的类型当作 parent 的类型) |
levels | string[] | 是 | 这个类型提供的级别,由低到高;没声明时是全部四级 |
switches | map[string, boolean] | 是 | 类型声明的开关和默认值 |
requestable | boolean | 是 | 开放访问申请 |
publishable | boolean | 是 | 可以发布给名单之外的读者 |
POST /access/{type}/check
批量查一个人对多个资源的级别
需要范围 app.resources:read。English: the level of a person on each of up to 500 resources of one type (replaces a visibility SQL join).
ids 1 到 500 个。level 可省略;写了就另外给出每个 id 是否达到了这个级别(allowed)。页面会话查的是自己;应用自己的令牌必须在 user 写明查谁,否则 422 invalid。未登记的资源,级别是空字符串。单次读取要鉴权时用它,列表过滤用 GET …/visible。
树类型(清单里带 parent 的节点类型,和被它当作 parent 的根类型):平台保存根和节点、它们的显式名单和状态,并把每个根和节点的有效名单存成不可变、去重的集合。节点继承父节点(顶层继承根)的名单再加上自己的条目;inherit 为 false 的节点只看自己的条目。每个 id 的级别是名单给出的级别经状态限制后的结果,reasons 给出原因:节点在回收站(trashed)时管理级别以下没有权限(原因 trashed);根归档(archived)时最多 comment(原因 archived);根只读发布版(publishOnly)时 edit 以下和智能体读已发布版本(原因 published_only,级别不变)。智能体最多 comment(正文 agent: true)。企业管理员绕过名单,等于处处 manage,同样受状态限制。不存在的根或节点级别为空字符串。English: on a tree type each id's level is the lists' level clamped by the states (trashed: nothing below manage; archived: at most comment; publish-only: read as published below edit and for an agent), with the reason.
- 认证:
bearer - 范围:
app.resources:read - operationId:
checkResourceAccess
参数
| 名称 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
type | path | string | 是 | 资源类型,本应用在清单 resources[] 里声明的 {应用 id}.{名字} |
Idempotency-Key | header | string | 每个 POST 都收。SDK 未传入时会生成 uuid v4。24 小时内同键同正文重放第一次的回答 最短 1,最长 255 |
请求正文(必填)(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
ids | string[] | 是 | 要查的资源 id 最多 500 项 |
level | string | 可省略;写了就另外给出是否达到 | |
user | string | 应用自己的令牌必填:查谁 | |
agent | boolean | 树类型:按这个人的智能体算(最多 comment,publishOnly 时读发布版) |
响应
| 状态 | 说明 |
|---|---|
| 200 | 每个 id 的级别 |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 404 | not_found:对应的记录不存在(客户中心没有这个客户,访客、服务或所指的东西不存在)。见 NotFound |
| 413 | payload_too_large:正文太大。见 PayloadTooLarge |
| 422 | 字段或参数不被接受(正文读不出来、有未知字段、缺必填、取值越界)。见 Unprocessable |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
200 响应正文(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
levels | map[string, string] | 是 | id 到级别;空字符串是没有权限或没登记 |
allowed | map[string, boolean] | id 到是否达到所问的级别;只在请求写了 level 时出现 | |
reasons | map[string, string] | 树类型:id 到状态给的原因(trashed、archived、published_only);没有原因的 id 不出现 |
GET /access/{type}/visible
分页列出一个人能看到的资源 id
需要范围 app.resources:read。English: the ids of the type's resources the person may see at least at the level, in id order, paged by cursor.
level 默认 view,limit 默认 200、最多 1000,cursor 用上一页的 next。页面会话列的是自己;应用自己的令牌必须带 user,否则 422 invalid。应用若维护自己的可见性镜像,用它刷新(再配合事件 access.changed),最终一致;单次读取仍应用 check。
树类型:列出这个类型(根类型列根、节点类型列节点)里此人经状态限制后达到 level 的 id,按 id 分页;企业管理员看到全部(仍受状态限制)。English: on a tree type the nodes (or roots) the person sees at the level after the states.
- 认证:
bearer - 范围:
app.resources:read - operationId:
listVisibleResources
参数
| 名称 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
type | path | string | 是 | 资源类型,本应用在清单 resources[] 里声明的 {应用 id}.{名字} |
level | query | string | 最低级别:view(默认)、comment、edit、manage | |
limit | query | integer | 每页条数,默认 200,最多 1000 | |
cursor | query | string | 上一页的 next | |
user | query | string | 应用自己的令牌必须带:查谁 | |
agent | query | boolean | 树类型:按这个人的智能体算(最多 comment) | |
raw | query | boolean | 树类型:只按名单算,不套状态(回收站、归档、只读发布版)也不套企业管理员的越权,agent 不起作用;回收站里的节点也列出,每个 id 的级别在 levels。给在自己的 SQL 里过滤列表、自己套状态和越权的应用(不留节点集合 id 的副本)。English: the lists alone, before the states and the bypass, with each id's level in levels |
响应
| 状态 | 说明 |
|---|---|
| 200 | 一页 id |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 404 | not_found:对应的记录不存在(客户中心没有这个客户,访客、服务或所指的东西不存在)。见 NotFound |
| 422 | 字段或参数不被接受(正文读不出来、有未知字段、缺必填、取值越界)。见 Unprocessable |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
200 响应正文(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
ids | string[] | 是 | 按 id 排序的一页 |
next | string | 是 | 下一页的 cursor;空字符串是到头了 |
levels | map[string, string] | 只在树类型带 raw=true 时有:id → 名单给出的级别(view、comment、edit、manage) |
POST /access/{type}/naming
列出点到某个人的分享(按资源)
需要范围 app.resources:read。English: the grants of a flat type that name a person, their departments or their roles (expired ones too), by resource id; for an app that keeps the rules over the kernel's list (a member's sensitive records) and works a person's explicit level out before its own transaction.
只收应用自己的令牌(页面会话是 403 forbidden)。user 必填;units 是此人所在的部门(含上级:部门的条目也给下级)、roles 是此人的角色(企业角色 id,平台角色写作 platform:<角色>),都由应用自己算好传来,每项最多 500 个。ids 可省略:省略时查这个类型的全部资源,写了就只查这些(最多 500 个)。返回 grants:资源 id 到点到此人的分享(user 本人、所在部门、角色或 everyone),过期的也在内,由应用按自己的时钟判断;没有分享的资源不出现。企业管理员不因身份多出条目(这里只列名单,不做判断)。树类型 404 not_found。English: the app's own token only; units and roles are the app's own reading of the person; ids optional (absent: every resource of the type).
- 认证:
bearer - 范围:
app.resources:read - operationId:
listResourceGrantsNaming
参数
| 名称 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
type | path | string | 是 | 资源类型,本应用在清单 resources[] 里声明的 {应用 id}.{名字} |
Idempotency-Key | header | string | 每个 POST 都收。SDK 未传入时会生成 uuid v4。24 小时内同键同正文重放第一次的回答 最短 1,最长 255 |
请求正文(必填)(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
user | string | 是 | 查谁(user id) |
units | string[] | 此人所在的部门,含上级 最多 500 项 | |
roles | string[] | 此人的角色:企业角色 id,平台角色写作 platform:<角色> 最多 500 项 | |
ids | string[] | 可省略:只查这些资源 最多 500 项 |
示例:
{
"user": "u_1",
"units": [
"d_ops"
],
"roles": [
"platform:tenant.member"
],
"ids": [
"mb_1"
]
}响应
| 状态 | 说明 |
|---|---|
| 200 | 按资源列出的分享 |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 404 | not_found:对应的记录不存在(客户中心没有这个客户,访客、服务或所指的东西不存在)。见 NotFound |
| 413 | payload_too_large:正文太大。见 PayloadTooLarge |
| 422 | 字段或参数不被接受(正文读不出来、有未知字段、缺必填、取值越界)。见 Unprocessable |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
200 响应正文(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
grants | map[string, ResourceGrant[]] | 是 | 资源 id 到点到此人的分享;没有的资源不出现 |
POST /access/{type}/departure
收回点到一个离开的人的全部分享
需要范围 app.resources:write。English: the offboarding handover's part of a flat type whose rules are the app's: every grant naming the person (kind user, expired ones too) goes, and their pending access requests on the type are withdrawn (decided by to).
只收应用自己的令牌(页面会话是 403 forbidden)。user 和 to 必填且不能相同,否则 422 invalid。重复调用没有副作用。名单变了的每个资源都会发事件 access.changed,并写审计 access.departure。树类型 404 not_found。English: the app's own token only; idempotent; access.changed for every resource whose list changed.
- 认证:
bearer - 范围:
app.resources:write - operationId:
departResourceGrants
参数
| 名称 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
type | path | string | 是 | 资源类型,本应用在清单 resources[] 里声明的 {应用 id}.{名字} |
Idempotency-Key | header | string | 每个 POST 都收。SDK 未传入时会生成 uuid v4。24 小时内同键同正文重放第一次的回答 最短 1,最长 255 |
请求正文(必填)(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
user | string | 是 | 离开的人 |
to | string | 是 | 接手的人(记为撤回申请的人) |
示例:
{
"user": "u_1",
"to": "u_2"
}响应
| 状态 | 说明 |
|---|---|
| 200 | 已收回 |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 404 | not_found:对应的记录不存在(客户中心没有这个客户,访客、服务或所指的东西不存在)。见 NotFound |
| 413 | payload_too_large:正文太大。见 PayloadTooLarge |
| 422 | 字段或参数不被接受(正文读不出来、有未知字段、缺必填、取值越界)。见 Unprocessable |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
200 响应正文(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
ok | boolean | 是 |
GET /access/{type}/mine
一个人在树模型每个集合里的级别
需要范围 app.resources:read。English: the person's level in every set of the tree model that names them, a page at a time (the app filters its own lists by the set id it keeps for each node).
type 是本应用的一个树类型,或 *(集合对所有类型是同一份)。页面会话查的是自己;应用自己的令牌必须带 user,否则 422 invalid。一页最多 10000 个集合,truncated 为 true 时用 next 作 after 再取。企业管理员绕过名单,集合里不体现:bypass 为 true 时应用把此人当作处处 manage(再受状态限制)。
- 认证:
bearer - 范围:
app.resources:read - operationId:
mineResourceSets
参数
| 名称 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
type | path | string | 是 | 本应用的树类型 {应用 id}.{名字},或 * |
after | query | string | 上一页的 next | |
user | query | string | 应用自己的令牌必须带:查谁 |
响应
| 状态 | 说明 |
|---|---|
| 200 | 集合 id 到级别 |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 404 | not_found:对应的记录不存在(客户中心没有这个客户,访客、服务或所指的东西不存在)。见 NotFound |
| 422 | 字段或参数不被接受(正文读不出来、有未知字段、缺必填、取值越界)。见 Unprocessable |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
200 响应正文(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
sets | map[string, string] | 是 | 集合 id 到级别(view、comment、edit、manage) |
truncated | boolean | 是 | 还有下一页 |
next | string | 是 | 下一页的 after |
bypass | boolean | 是 | 企业管理员:集合里不体现,应用按处处 manage 处理(再受状态限制) |
示例:
{
"sets": {
"5f0c2a9e41d7b3c8a6e2f104": "edit"
},
"truncated": false,
"next": "",
"bypass": false
}PUT /access/{type}/{id}/inherit
节点停止或恢复继承上面的名单
需要范围 app.resources:write。English: a node of a tree type stops or restores inheriting what is above it (the platform's share dialog: 「仅名单上的人可访问」). Its place does not change; moving stays the app's.
只用于树类型的节点类型。页面会话的人要能管理这个节点(状态限制之前的级别),应用自己的令牌不受限。停止继承时,节点现在的有效名单成为它自己的名单(名字从写下每一条的地方取),停止的人保留管理级别,所以开关本身不会让谁失去访问;没有管理者时是 422。恢复继承时,去掉上面已经以相同或更高级别给出的条目。和现在相同时什么也不改。之后发 access.changed,记审计 access.tree.inherit。返回集合变了的节点。
- 认证:
bearer - 范围:
app.resources:write - operationId:
setResourceInherit
参数
| 名称 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
type | path | string | 是 | 本应用的树类型的节点类型 {应用 id}.{名字} |
id | path | string | 是 | 节点 id |
Idempotency-Key | header | string | 每个 POST 都收。SDK 未传入时会生成 uuid v4。24 小时内同键同正文重放第一次的回答 最短 1,最长 255 |
请求正文(必填)(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
inherit | boolean | 是 |
示例:
{
"inherit": false
}响应
| 状态 | 说明 |
|---|---|
| 200 | 集合变了的节点 |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 404 | not_found:对应的记录不存在(客户中心没有这个客户,访客、服务或所指的东西不存在)。见 NotFound |
| 422 | 字段或参数不被接受(正文读不出来、有未知字段、缺必填、取值越界)。见 Unprocessable |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
200 响应正文(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
type | string | ||
id | string | ||
changed | map[string, string] | 是 | 节点 id 到它现在的集合 id(重新鉴权它打开的文档,更新应用保存的集合 id) |
示例:
{
"type": "wiki.page",
"id": "pg_1",
"changed": {
"pg_1": "5f0c2a9e41d7b3c8a6e2f104",
"pg_2": "5f0c2a9e41d7b3c8a6e2f104"
}
}POST /access/{type}/{id}/reconcile
用应用自己的树校正平台里一个根下的节点
需要范围 app.resources:write。English: makes the kernel's nodes of one root what the app's tree says (an app outside the platform writes the kernel first and its own rows after; a periodic reconcile repairs a failure between the two).
只用于树类型的根类型(id 是根),只收应用自己的令牌(页面会话是 403 forbidden)。spec 是根的状态,nodes 是这个根下应用的全部节点(inherit 省略为 true):没列出的节点被删除,其余的按位置、继承和回收站状态写入。显式名单不校正(只存在平台里)。返回改了几个节点;大于 0 时记审计 access.tree.reconcile。
- 认证:
bearer - 范围:
app.resources:write - operationId:
reconcileResourceTree
参数
| 名称 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
type | path | string | 是 | 资源类型,本应用在清单 resources[] 里声明的 {应用 id}.{名字} |
id | path | string | 是 | 根的 id |
Idempotency-Key | header | string | 每个 POST 都收。SDK 未传入时会生成 uuid v4。24 小时内同键同正文重放第一次的回答 最短 1,最长 255 |
请求正文(必填)(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
spec | object | 根的状态 | |
spec.archived | boolean | ||
spec.publishOnly | boolean | ||
nodes | object[] | 是 | |
nodes[].id | string | 是 | |
nodes[].root | string | ||
nodes[].parent | string | 省略为根的顶层 | |
nodes[].inherit | boolean | 省略为 true | |
nodes[].trashed | boolean |
响应
| 状态 | 说明 |
|---|---|
| 200 | 改了几个节点 |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 404 | not_found:对应的记录不存在(客户中心没有这个客户,访客、服务或所指的东西不存在)。见 NotFound |
| 413 | payload_too_large:正文太大。见 PayloadTooLarge |
| 422 | 字段或参数不被接受(正文读不出来、有未知字段、缺必填、取值越界)。见 Unprocessable |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
200 响应正文(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
changed | integer | 是 | 改了几个节点(写入的加删除的) |
errors
本应用的错误:脱敏后给开发者组织(开发者平台「错误」、k3 logs --errors)
POST /errors
向开发者平台报告本应用的错误
需要范围 app.errors:report。English: reports the app's own errors to its developer organisation (ADR-0130 H8).
平台在保存前脱敏:message 与 frames 里的值(引号里的内容、数字、邮箱、网址、令牌、key=value 的值,以及 message 里所有非 ASCII 的文字,如中文)换成占位符;想让开发者读得懂,就报 code + 固定的 template(应用代码里的常量,原文保留)+ params,route 里像值的段换成 :id,code 与 kind 只收标识符。开发者平台只看到脱敏后的样子,看不到企业;params 是消息引用的值,永远不进开发者视图,只在企业批准的限时诊断里(去掉密钥后)给开发者看。一次 1–50 条,回答 202。每个应用每分钟最多保存 120 条,超过的不保存。
- 认证:
bearer - 范围:
app.errors:report - operationId:
reportErrors
参数
| 名称 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
Idempotency-Key | header | string | 每个 POST 都收。SDK 未传入时会生成 uuid v4。24 小时内同键同正文重放第一次的回答 最短 1,最长 255 |
请求正文(必填)(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
errors | ErrorOccurrence[] | 是 | 最多 50 项 |
errors[].kind | string | 错误类型(异常类名等标识符) | |
errors[].code | string | 应用自己的错误码(标识符,最长 64) | |
errors[].template | string | 固定模板:应用代码里的常量(如「会员不存在:{name}」),开发者看到原文(其中的数字、引号内容等仍脱敏);值放进 params | |
errors[].message | string | 自由文本:开发者看到的是脱敏后的样子,值换成占位符,所有非 ASCII 的文字(中文等)也换成 <text>;想让开发者读得懂,用 template + params | |
errors[].params | string[] | 消息引用的值:不进开发者视图 最多 10 项 | |
errors[].frames | string[] | 调用栈,最上面一帧在前 最多 20 项 | |
errors[].method | string | ||
errors[].route | string | 出错的路径;查询串去掉,像值的段换成 :id | |
errors[].requestId | string | ||
errors[].version | string | 应用版本 | |
errors[].at | string(date-time) | 发生时间;缺省或差一天以上用平台时间 |
响应
| 状态 | 说明 |
|---|---|
| 202 | 已收下 |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 413 | payload_too_large:正文太大。见 PayloadTooLarge |
| 422 | 字段或参数不被接受(正文读不出来、有未知字段、缺必填、取值越界)。见 Unprocessable |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
202 响应正文(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
accepted | integer | 是 |
logs
本应用主动写的结构化日志:按企业脱敏后留 24 小时,给开发者组织实时看(开发者平台「实时日志」、k3 tail)
POST /logs
写本应用的结构化日志
需要范围 app.logs:write。English: writes the app's own structured log lines for its developer organisation (ADR-0149 §3); the developer reads them live (k3 tail, GET /api/dev/apps/{id}/tail). The process's stdout and stderr never reach the developer: only what the app writes here.
平台在保存前按企业脱敏:开发者组织自己的测试企业保留原文,只去掉密钥一类(令牌、sk-live-… 之类的密钥、password=…);其他企业的 message 和每个字段值都脱敏(手机号、身份证、邮箱、长数字、引号里的值、key=value 的值、所有非 ASCII 文字换成占位符),字段名保留(不是标识符的字段名也脱敏),企业只给不透明的 tenantRef,原文不落库。template: true 声明消息是固定模板(应用代码里的常量):模板里的中文保留,值仍脱敏,字段值照样脱敏。一次 1–100 行;message 最多 2 KiB、字段最多 20 个、每个值最多 256 字节,超出截断并标记。每个应用每秒最多保存 50 行,超出的丢弃并计数(开发者在实时日志里看到「丢了 N 行」),回答里的 dropped 是这一批丢了几行。回答 202。
- 认证:
bearer - 范围:
app.logs:write - operationId:
writeLogs
参数
| 名称 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
Idempotency-Key | header | string | 每个 POST 都收。SDK 未传入时会生成 uuid v4。24 小时内同键同正文重放第一次的回答 最短 1,最长 255 |
请求正文(必填)(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
version | string | 应用版本(托管进程的 K3_VERSION);行里的 version 优先 | |
lines | LogLine[] | 是 | 最多 100 项 |
lines[].level | string | 级别;warning 当 warn,fatal 当 error,其他当 info 可选值: debug、info、warn、error | |
lines[].message | string | 是 | 消息,最多 2 KiB;线上企业的脱敏后保存 |
lines[].fields | map[string, string] | 字段:名保留,值按文本保存(最多 256 字节;数字和布尔值也收,按 JSON 的写法存成文本),线上企业的值脱敏 | |
lines[].template | boolean | 消息是固定模板(应用代码里的常量):模板里的中文保留,值仍脱敏 | |
lines[].version | string | 这一行的应用版本 | |
lines[].traceId | string | 写这一行时所在请求的追踪 id(traceparent 里的;SDK 自动带上),实时日志据此链接到那次请求;不合格式的丢弃 格式 ^[0-9a-f]{32}$ | |
lines[].at | string(date-time) | 发生时间;缺省或差一天以上用平台时间 |
响应
| 状态 | 说明 |
|---|---|
| 202 | 已收下 |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 413 | payload_too_large:正文太大。见 PayloadTooLarge |
| 422 | 字段或参数不被接受(正文读不出来、有未知字段、缺必填、取值越界)。见 Unprocessable |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
202 响应正文(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
accepted | integer | 是 | 保存的行数 |
dropped | integer | 是 | 超过每秒 50 行丢弃的行数 |
truncated | integer | 是 | 截断过的行数 |
traces
本应用对请求追踪加的段:处理请求的那一段和应用自己加的步骤(ADR-0155 §2)
POST /traces
写本应用的请求追踪段
需要范围 app.traces:write。English: sends the app's own spans of the platform's request traces (ADR-0155 §2): the handler of a request (kind server, the SDK's middleware) and the steps the app adds (kind internal, appkit.Trace.Span). The platform records the edge's, the gateway's and every /app/v1 call's span itself.
平台的网关为托管应用的每个请求开一个追踪,交给应用 traceparent 和带平台标记的 tracestate(raise=…)。每个段要带上它所在请求的 traceId 和这个标记(mark):标记由平台为「本应用 + 这个令牌的企业 + 这个追踪」签发,对不上的段拒收(refused)。平台在尾部决定保留哪些追踪(所有 5xx、慢于本应用 p99 的,其余线上 1 %,测试企业按开发者的设置),段先缓冲 30 秒等决定。段名是应用代码里的常量:线上企业的段名保留文字、值脱敏;属性只收登记过的名字(http.method http.route http.status_code k3.version k3.op k3.dataset k3.table k3.event k3.service k3.provider k3.items db.system db.operation error.code error.type peer.service cache.hit retry.count messaging.operation rpc.method),值按企业脱敏,其他名字丢弃并计入 truncated。一次 1–200 段;每个应用在每个副本上每秒最多缓冲 500 段,超出的丢弃并计数。回答 202。
- 认证:
bearer - 范围:
app.traces:write - operationId:
writeTraceSpans
参数
| 名称 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
Idempotency-Key | header | string | 每个 POST 都收。SDK 未传入时会生成 uuid v4。24 小时内同键同正文重放第一次的回答 最短 1,最长 255 |
请求正文(必填)(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
version | string | 应用版本(托管进程的 K3_VERSION) | |
spans | TraceSpan[] | 是 | 最多 200 项 |
spans[].traceId | string | 是 | 请求的 traceparent 里的追踪 id 格式 ^[0-9a-f]{32}$ |
spans[].spanId | string | 是 | 这一段的 id(应用生成,随机) 格式 ^[0-9a-f]{16}$ |
spans[].parentId | string | 上一层段的 id:处理请求的段的上一层是 traceparent 里的父段 格式 ^[0-9a-f]{16}$ | |
spans[].mark | string | 是 | 请求的 tracestate 里平台成员 raise= 的值 |
spans[].name | string | 是 | 段名,最多 128 字节;应用代码里的常量,不放值 |
spans[].kind | string | server:处理请求的那一段;internal(缺省):应用自己加的步骤 可选值: server、internal | |
spans[].start | string(date-time) | 是 | 开始时间;一小时以前或五分钟以后的拒收 |
spans[].durationUs | integer(int64) | 是 | 耗时,微秒;超过一小时按一小时 最小 0 |
spans[].status | integer | 状态码(HTTP 状态一类) | |
spans[].error | boolean | 这一步失败了;状态码 500 以上也算 | |
spans[].attrs | map[string, string] | 属性:只收登记过的名字(见接口说明),最多 32 个,值最多 256 字节,线上企业的值脱敏 |
响应
| 状态 | 说明 |
|---|---|
| 202 | 已收下 |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 413 | payload_too_large:正文太大。见 PayloadTooLarge |
| 422 | 字段或参数不被接受(正文读不出来、有未知字段、缺必填、取值越界)。见 Unprocessable |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
202 响应正文(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
accepted | integer | 是 | 缓冲下来的段数 |
dropped | integer | 是 | 超过每秒限额丢弃的段数 |
refused | integer | 是 | 标记对不上、id 不合格式或时间不合理而拒收的段数 |
truncated | integer | 是 | 丢了属性或截断过的段数 |
analytics
本应用自定义的分析数据点:按清单登记的数据集写入,按企业脱敏后留 31 天,开发者组织按字段名查询(k3 analytics query)
POST /analytics
写本应用的分析数据点
需要范围 app.analytics:write。English: writes data points into the datasets the app's manifest declares (analytics: [{name, blobs, doubles}], ADR-0155 §1), for its developer organisation to query by field name (POST /api/dev/apps/{id}/analytics/query, k3 analytics query).
一个点属于一个数据集:最多 1 个索引 index(≤ 96 字节)、按登记顺序的字符串 blobs(最多 20 个,每个 ≤ 256 字节,超出截断)和数值 doubles(最多 20 个,有限数)。平台补上企业(只给不透明的 tenant 引用)、版本和 test/live。开发者组织自己的测试企业保留字符串原文(只去掉密钥一类);其他企业的 index 和每个字符串都按日志的规则脱敏,原文不落库;数值原样保存。没登记的数据集、比登记多的值、超长的索引丢弃并计数;每个应用每秒最多保存 200 点,超出的丢弃并计数(开发者查询时看到 dropped)。保留 31 天,只追加不改。一次 1–250 点,回答 202。
- 认证:
bearer - 范围:
app.analytics:write - operationId:
writeAnalytics
参数
| 名称 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
Idempotency-Key | header | string | 每个 POST 都收。SDK 未传入时会生成 uuid v4。24 小时内同键同正文重放第一次的回答 最短 1,最长 255 |
请求正文(必填)(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
version | string | 应用版本(托管进程的 K3_VERSION):数据集按这个版本的清单认 | |
points | AnalyticsPoint[] | 是 | 最多 250 项 |
points[].dataset | string | 是 | 清单 analytics 里登记的数据集名 |
points[].index | string | 索引(可选),线上企业的脱敏后保存 最长 96 | |
points[].blobs | string[] | 字符串值,按数据集登记的 blobs 顺序;每个最多 256 字节,线上企业的脱敏后保存 最多 20 项 | |
points[].doubles | number[] | 数值,按数据集登记的 doubles 顺序 最多 20 项 | |
points[].at | string(date-time) | 发生时间;缺省、超前 5 分钟以上或早于一天用平台时间 |
响应
| 状态 | 说明 |
|---|---|
| 202 | 已收下 |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 413 | payload_too_large:正文太大。见 PayloadTooLarge |
| 422 | 字段或参数不被接受(正文读不出来、有未知字段、缺必填、取值越界)。见 Unprocessable |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
202 响应正文(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
accepted | integer | 是 | 保存的点数 |
dropped | integer | 是 | 丢弃的点数 |
truncated | integer | 是 | 字符串截断过的点数 |
reasons | map[string, integer] | 按原因的丢弃数:rate_limited(超过每秒 200 点)、unknown_dataset(版本没登记的数据集)、invalid(比登记多的值、超长的索引、不是有限数) |
blobs
企业文件存储里本应用自己的文件夹:存取、元数据、列出、复制、删除,以及直传用的预签名地址
GET /blobs/objects/{key...}
读取本应用文件夹里一个对象的字节
需要范围 app.blobs:read。English: streams the bytes of the object key of the app's folder.
回答的正文是对象的原始字节,Content-Type、Content-Length、Last-Modified 取自对象,并带 X-Content-Type-Options: nosniff。对象不存在是 404 not_found。
SDK:Go App.Blobs.Get 回答 RawResponse(调用方读完 Body 后关闭),TS app.blobs.get 回答 fetch 的 Response。只要元数据用 blobs.head。
- 认证:
bearer - 范围:
app.blobs:read - operationId:
getBlob
参数
| 名称 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
key | path | string | 是 | 对象的键,以 apps/{本应用 id}/ 开头,可以含 /(路径里的 / 不要转义) |
响应
| 状态 | 说明 |
|---|---|
| 200 | 对象的字节 |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 404 | not_found:对应的记录不存在(客户中心没有这个客户,访客、服务或所指的东西不存在)。见 NotFound |
| 422 | 字段或参数不被接受(正文读不出来、有未知字段、缺必填、取值越界)。见 Unprocessable |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
200 响应正文(application/octet-stream)
类型 string(binary)
PUT /blobs/objects/{key...}
把一段字节存成本应用文件夹里的一个对象
需要范围 app.blobs:write。English: stores the request body, raw bytes, as the object key in the app's folder of the tenant's file store (the platform's, or the tenant's own bucket).
路径里的 {key...} 吃掉余下的整个路径,键必须以 apps/{本应用 id}/ 开头,且其后至少还有一个字符;不能有空的、. 或 .. 段,不能有反斜杠和控制字符,最长 1024 字节。正文就是对象的字节(不是 JSON),Content-Type 请求头是对象的类型(没有时按 application/octet-stream),必须带 Content-Length(没有是 411)。经平台存的单个对象最大 512 MiB,更大的用 POST /blobs/presign 拿上传地址直传。企业的存储额度对两条路都有效。成功回答 204,没有正文。
SDK:Go App.Blobs.Put(io.Reader、长度、类型),TS app.blobs.put(Blob、ArrayBuffer、Uint8Array 或流)。
- 认证:
bearer - 范围:
app.blobs:write - operationId:
putBlob
参数
| 名称 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
key | path | string | 是 | 对象的键,以 apps/{本应用 id}/ 开头,可以含 /(路径里的 / 不要转义) |
请求正文(必填)(application/octet-stream)
类型 string(binary)
对象的字节
响应
| 状态 | 说明 |
|---|---|
| 204 | 已存下。没有正文 |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 411 | 没带 Content-Length。见 LengthRequired |
| 413 | payload_too_large:正文太大。见 PayloadTooLarge |
| 422 | 字段或参数不被接受(正文读不出来、有未知字段、缺必填、取值越界)。见 Unprocessable |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
DELETE /blobs/objects/{key...}
删除本应用文件夹里的一个对象
需要范围 app.blobs:write。English: deletes the object key; deleting what is not there is done.
成功回答 204,没有正文;对象本来就不存在也是 204。
- 认证:
bearer - 范围:
app.blobs:write - operationId:
deleteBlob
参数
| 名称 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
key | path | string | 是 | 对象的键,以 apps/{本应用 id}/ 开头,可以含 /(路径里的 / 不要转义) |
响应
| 状态 | 说明 |
|---|---|
| 204 | 已删除(或本来就不在)。没有正文 |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 422 | 字段或参数不被接受(正文读不出来、有未知字段、缺必填、取值越界)。见 Unprocessable |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
GET /blobs/meta/{key...}
读取一个对象的元数据
需要范围 app.blobs:read。English: the size, type and last write time of the object key, without its bytes.
对象不存在是 404 not_found。
- 认证:
bearer - 范围:
app.blobs:read - operationId:
headBlob
参数
| 名称 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
key | path | string | 是 | 对象的键,以 apps/{本应用 id}/ 开头,可以含 /(路径里的 / 不要转义) |
响应
| 状态 | 说明 |
|---|---|
| 200 | 对象的元数据 |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 404 | not_found:对应的记录不存在(客户中心没有这个客户,访客、服务或所指的东西不存在)。见 NotFound |
| 422 | 字段或参数不被接受(正文读不出来、有未知字段、缺必填、取值越界)。见 Unprocessable |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
200 响应正文(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
key | string | 是 | 对象的键,以 apps/{本应用 id}/ 开头 |
size | integer | 是 | 字节数 |
contentType | string | 对象的类型。可能为空 | |
modTime | string(date-time) | 是 | 最后写入的时间 |
示例:
{
"key": "apps/crm/exports/2026-10.csv",
"size": 20480,
"contentType": "text/csv",
"modTime": "2026-10-31T08:00:00Z"
}GET /blobs
列出本应用文件夹里某个前缀下的对象
需要范围 app.blobs:read。English: lists the objects below a prefix of the app's folder.
prefix 省略时列出整个文件夹 apps/{本应用 id}/;给了就必须在本应用的文件夹里,可以以 / 结尾。返回 {items}。
- 认证:
bearer - 范围:
app.blobs:read - operationId:
listBlobs
参数
| 名称 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
prefix | query | string | 前缀,以 apps/{本应用 id}/ 开头。省略时是整个文件夹 |
响应
| 状态 | 说明 |
|---|---|
| 200 | 对象 |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 422 | 字段或参数不被接受(正文读不出来、有未知字段、缺必填、取值越界)。见 Unprocessable |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
200 响应正文(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
items | BlobInfo[] | 是 | 对象 |
items[].key | string | 是 | 对象的键,以 apps/{本应用 id}/ 开头 |
items[].size | integer | 是 | 字节数 |
items[].contentType | string | 对象的类型。可能为空 | |
items[].modTime | string(date-time) | 是 | 最后写入的时间 |
示例:
{
"items": [
{
"key": "apps/crm/exports/2026-10.csv",
"size": 20480,
"contentType": "text/csv",
"modTime": "2026-10-31T08:00:00Z"
}
]
}POST /blobs/copy
在本应用的文件夹里复制一个对象
需要范围 app.blobs:write。English: copies the object src to dst, both in the app's folder.
src 不存在是 404 not_found。成功回答 204,没有正文。
- 认证:
bearer - 范围:
app.blobs:write - operationId:
copyBlob
参数
| 名称 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
Idempotency-Key | header | string | 每个 POST 都收。SDK 未传入时会生成 uuid v4。24 小时内同键同正文重放第一次的回答 最短 1,最长 255 |
请求正文(必填)(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
src | string | 是 | 来源对象的键 |
dst | string | 是 | 目标对象的键。已有同名对象会被覆盖 |
示例:
{
"src": "apps/crm/exports/2026-10.csv",
"dst": "apps/crm/archive/2026-10.csv"
}响应
| 状态 | 说明 |
|---|---|
| 204 | 已复制。没有正文 |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 404 | not_found:对应的记录不存在(客户中心没有这个客户,访客、服务或所指的东西不存在)。见 NotFound |
| 413 | payload_too_large:正文太大。见 PayloadTooLarge |
| 422 | 字段或参数不被接受(正文读不出来、有未知字段、缺必填、取值越界)。见 Unprocessable |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
POST /blobs/delete-prefix
删除本应用文件夹里某个前缀下的全部对象
需要范围 app.blobs:write。English: deletes every object below prefix of the app's folder.
prefix 可以就是整个文件夹 apps/{本应用 id}/(删光本应用的文件)。成功回答 204,没有正文。
- 认证:
bearer - 范围:
app.blobs:write - operationId:
deleteBlobPrefix
参数
| 名称 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
Idempotency-Key | header | string | 每个 POST 都收。SDK 未传入时会生成 uuid v4。24 小时内同键同正文重放第一次的回答 最短 1,最长 255 |
请求正文(必填)(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
prefix | string | 是 | 前缀,以 apps/{本应用 id}/ 开头;可以就是整个文件夹 |
示例:
{
"prefix": "apps/crm/tmp/"
}响应
| 状态 | 说明 |
|---|---|
| 204 | 已删除。没有正文 |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 413 | payload_too_large:正文太大。见 PayloadTooLarge |
| 422 | 字段或参数不被接受(正文读不出来、有未知字段、缺必填、取值越界)。见 Unprocessable |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
POST /blobs/presign
为一个对象拿一个不带令牌的上传或下载地址
需要范围 app.blobs:read;method 为 PUT(上传)时还需要 app.blobs:write,缺了是 403。English: a URL to PUT (upload) or GET (download) one object of the app's folder, usable without a token until expiresAt.
字节直接走到文件存储,不经平台,所以没有 512 MiB 的限制;企业的存储额度仍然有效。ttlSeconds 省略时取最大值:上传 900 秒、下载 300 秒,超过是 422。上传必须给 size(确切字节数,≤ 512 MiB):大小签进地址,长度不符的上传被存储拒绝;放不进企业剩余额度的在签发前就是 413。下载地址要求对象已存在,不存在是 404 not_found。
- 认证:
bearer - 范围:
app.blobs:read - operationId:
presignBlob
参数
| 名称 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
Idempotency-Key | header | string | 每个 POST 都收。SDK 未传入时会生成 uuid v4。24 小时内同键同正文重放第一次的回答 最短 1,最长 255 |
请求正文(必填)(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
key | string | 是 | 对象的键 |
method | string | 是 | PUT 上传(还需要 app.blobs:write),GET 下载 可选值: PUT、GET |
ttlSeconds | integer | 地址的有效秒数。省略(或 0)取最大值:上传(PUT)900、下载(GET)300 最小 0,最大 900 | |
size | integer(int64) | 上传(PUT)必填:上传的确切字节数,最多 512 MiB。大小签进地址,存储只收这么多字节;签发前按企业剩余的存储额度检查,放不下是 413。下载不带 最小 0,最大 536870912 |
示例:
{
"key": "apps/crm/imports/2026-10.csv",
"method": "PUT",
"ttlSeconds": 900,
"size": 48213
}响应
| 状态 | 说明 |
|---|---|
| 200 | 地址 |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 404 | not_found:对应的记录不存在(客户中心没有这个客户,访客、服务或所指的东西不存在)。见 NotFound |
| 413 | payload_too_large:正文太大。见 PayloadTooLarge |
| 422 | 字段或参数不被接受(正文读不出来、有未知字段、缺必填、取值越界)。见 Unprocessable |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
200 响应正文(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
url | string | 是 | 直接对文件存储用的地址 |
method | string | 是 | 用这个方法去请求它:PUT 或 GET |
expiresAt | string(date-time) | 是 | 地址失效的时间 |
示例:
{
"url": "https://files.example.com/apps/crm/exports/2026-10.csv?X-Signature=abc123",
"method": "GET",
"expiresAt": "2026-10-31T08:10:00Z"
}notify
以本应用的名义给企业成员发站内通知
POST /notify
以本应用的名义给企业成员发一条站内通知
需要范围 app.notify:send。English: tells people of the tenant something in the platform's message centre, as the app (its name, a link into it); best effort.
users 是企业成员的用户 id(空白项忽略,去掉后至少 1 个,最多 500 个),title 必填,body 是正文,link 只能是应用内的路由(以 / 开头)、k3:// 引用,或本应用清单 egress 里声明的域名下的 https:// 地址,其余 422。class 说明通知的性质,供推送到平台以外的渠道使用:approval.task、approval.result、mention,省略由渠道决定。只发给本企业的在职成员:其余的人数计入 rejected,不说明原因。同一个调用方(页面会话的人或应用本身)十分钟内最多通知 1000 人次,超过是 429 并带 Retry-After。回答 202,accepted 是收到通知的人数。
- 认证:
bearer - 范围:
app.notify:send - operationId:
sendNotice
参数
| 名称 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
Idempotency-Key | header | string | 每个 POST 都收。SDK 未传入时会生成 uuid v4。24 小时内同键同正文重放第一次的回答 最短 1,最长 255 |
请求正文(必填)(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
users | string[] | 是 | 企业成员的用户 id,最多 500 个 |
title | string | 是 | 标题。必填 |
body | string | 正文 | |
link | string | 点开后去哪:应用内的路由、https:// 或 k3:// 地址 | |
class | string | 通知的性质,供推送到平台以外的渠道用。省略由渠道决定 可选值: approval.task、approval.result、mention |
示例:
{
"users": [
"u_1001",
"u_1002"
],
"title": "有 3 张工单等你处理",
"body": "客户“李明”的报修已分配给你",
"link": "/tickets?status=open",
"class": "approval.task"
}响应
| 状态 | 说明 |
|---|---|
| 202 | 已交给消息中心 |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 413 | payload_too_large:正文太大。见 PayloadTooLarge |
| 422 | 字段或参数不被接受(正文读不出来、有未知字段、缺必填、取值越界)。见 Unprocessable |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
202 响应正文(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
accepted | integer | 是 | 收到通知的人数 |
rejected | integer | 是 | 没有发出的人数(不是本企业的在职成员) |
示例:
{
"accepted": 2,
"rejected": 0
}drafts
草稿:为成员起草变更由本人确认,以及当前人员审阅、修改、放弃、应用涉及本应用的草稿项,和记录的来源
GET /drafts
列出当前人员涉及本应用的草稿
需要范围 app.drafts:read。English: the person's drafts that have an item of this app.
只收页面会话:这里的“人”是令牌里的人,应用自己的令牌是 403 forbidden。返回 {drafts},最多 50 条;每条里本应用的项是完整的,其他应用的项只有数量。
- 认证:
bearer - 范围:
app.drafts:read - operationId:
listDrafts
参数
| 名称 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
status | query | string | 草稿状态:省略是 open 与 partial,all 是全部 | |
target | query | string | 只要作用于这个 k3:// 引用的草稿 | |
session | query | string | 只要这次对话里起草的草稿 |
响应
| 状态 | 说明 |
|---|---|
| 200 | 草稿 |
| 400 | 草稿服务的拒绝,状态由它定(400、403、404、409、422 等)。见 DraftRefused |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
200 响应正文(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
drafts | DraftView[] | 是 | |
drafts[].id | string | 是 | |
drafts[].tenant | string | ||
drafts[].owner | string | 是 | 草稿属于的人;只有他们能应用 |
drafts[].sessionId | string | ||
drafts[].origin | string | 来源。普通草稿为空 | |
drafts[].summary | string | ||
drafts[].status | string | 是 | 可选值:open、applied、discarded、partial |
drafts[].items | DraftItem[] | 是 | |
drafts[].items[].id | string | 是 | |
drafts[].items[].app | string | 是 | |
drafts[].items[].op | string | 是 | |
drafts[].items[].target | string | 要改或删的记录的 k3:// 引用 | |
drafts[].items[].revision | integer | 是 | 每次改动加一;应用时必须与本人看到的一致 |
drafts[].items[].state | string | 状态。省略是 pending 可选值: pending、applied、abandoned | |
drafts[].items[].group | string | ||
drafts[].items[].reason | string | ||
drafts[].items[].fields | map[string, DraftField] | 是 | 按字段名的值与提议 |
drafts[].items[].dependsOn | string[] | ||
drafts[].items[].baseVersion | string | 起草时应用报告的版本;之后预演报告了别的就是过期 | |
drafts[].items[].dryRun | DraftExecuteResult | 一次预演或执行的结果 | |
drafts[].items[].dryRun.applied | boolean | 已生效 | |
drafts[].items[].dryRun.ref | string | 受影响记录的 k3:// 引用 | |
drafts[].items[].dryRun.summary | string | 一句话说明这个操作做了什么 | |
drafts[].items[].dryRun.mark | string | 检查结论:ready、warning、choose、invalid | |
drafts[].items[].dryRun.issues | object[] | 发现的问题 | |
drafts[].items[].result | DraftExecuteResult | 一次预演或执行的结果 | |
drafts[].items[].result.applied | boolean | 已生效 | |
drafts[].items[].result.ref | string | 受影响记录的 k3:// 引用 | |
drafts[].items[].result.summary | string | 一句话说明这个操作做了什么 | |
drafts[].items[].result.mark | string | 检查结论:ready、warning、choose、invalid | |
drafts[].items[].result.issues | object[] | 发现的问题 | |
drafts[].items[].mark | string | 现算的检查结论 | |
drafts[].items[].applicable | boolean | 现算的:能否应用 | |
drafts[].items[].turns | string[] | 提议过这一项的轮次,旧的在前 | |
drafts[].createdAt | string(date-time) | 是 | |
drafts[].updatedAt | string(date-time) | 是 | |
drafts[].others | DraftOtherApp[] | 其他应用的项的数量 | |
drafts[].others[].app | string | 是 | |
drafts[].others[].pending | integer | 是 | |
drafts[].others[].applied | integer | 是 | |
drafts[].ops | map[string, object] | 返回的项用到的操作的声明,键是“应用.操作”:标题、输入模式、风险和本人要做的事 | |
drafts[].merged | DraftItemRef[] | 并入了已有待办项的请求项,以及它们现在在哪 | |
drafts[].merged[].draftId | string | 是 | |
drafts[].merged[].itemId | string | 是 | |
drafts[].merged[].key | string | 请求里给它的 key |
POST /drafts
为一位成员起草一批变更,由本人确认后才生效
需要范围 app.drafts:write。English: proposes changes with the app's own ops for a person to confirm, as the agent does.
正文是草稿服务自己的创建正文(sessionId、turn、summary、items)外加 for,即草稿属于的人。草稿是这个人的,由本应用代写(委托,作者是 app:{应用 id}):本人在工作台或本应用的页面里审阅并应用;没有他们预先签下的策略,什么都不会自动生效。每个 items[].app 只能是本应用(省略时补上),否则 422。应用自己的令牌必须给 for(企业的在职成员;不是的一律 403 forbidden,不说明这个人是否存在);页面会话的 for 省略或等于本人,给别人是 422。本应用十分钟内给同一个人最多起草 30 份,超过是 429 并带 Retry-After。应用凭证不因此获得这个人的任何权限:草稿只给本人审阅,委托方不能应用。草稿有待办项时,平台会通知本人“有 N 项变更等你确认”。返回 201 和草稿视图。
- 认证:
bearer - 范围:
app.drafts:write - operationId:
createDraft
参数
| 名称 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
Idempotency-Key | header | string | 每个 POST 都收。SDK 未传入时会生成 uuid v4。24 小时内同键同正文重放第一次的回答 最短 1,最长 255 |
请求正文(必填)(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
for | string | 草稿属于的人(企业成员的用户 id)。应用自己的令牌必须给;页面会话省略或等于本人 | |
sessionId | string | 起草所在的对话 | |
turn | string | 提议所在的那一轮,随每个提议的值保存 | |
summary | string | 一句话:草稿做什么、为什么 | |
items | DraftItemInput[] | 是 | 提议的变更 |
items[].key | string | 这项在本次请求里的名字,供其他项依赖 | |
items[].app | string | 操作所属的应用。省略时是本应用,写了就必须是本应用 | |
items[].op | string | 是 | 操作名,本应用在清单里声明的 op |
items[].target | string | 要改或删的记录的 k3:// 引用;新建时省略 | |
items[].group | string | 起草者给这项的意图标签 | |
items[].reason | string | 为什么这样改 | |
items[].dependsOn | string[] | 本次请求里其他项的 key | |
items[].proposed | object | 是 | 提议的字段值,按操作的输入模式写 |
items[].candidates | map[string, DraftCandidate[]] | 按字段给出的候选值,让本人挑 |
示例:
{
"for": "u_1001",
"summary": "把李明的会员有效期延长到 2027-03-31",
"items": [
{
"key": "extend",
"op": "member.update",
"target": "k3://members/member/m_42",
"reason": "客户投诉后补偿",
"proposed": {
"validUntil": "2027-03-31"
}
}
]
}响应
| 状态 | 说明 |
|---|---|
| 201 | 草稿 |
| 400 | 草稿服务的拒绝,状态由它定(400、403、404、409、422 等)。见 DraftRefused |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 413 | payload_too_large:正文太大。见 PayloadTooLarge |
| 422 | 字段或参数不被接受(正文读不出来、有未知字段、缺必填、取值越界)。见 Unprocessable |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
201 响应正文(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
id | string | 是 | |
tenant | string | ||
owner | string | 是 | 草稿属于的人;只有他们能应用 |
sessionId | string | ||
origin | string | 来源。普通草稿为空 | |
summary | string | ||
status | string | 是 | 可选值:open、applied、discarded、partial |
items | DraftItem[] | 是 | |
items[].id | string | 是 | |
items[].app | string | 是 | |
items[].op | string | 是 | |
items[].target | string | 要改或删的记录的 k3:// 引用 | |
items[].revision | integer | 是 | 每次改动加一;应用时必须与本人看到的一致 |
items[].state | string | 状态。省略是 pending 可选值: pending、applied、abandoned | |
items[].group | string | ||
items[].reason | string | ||
items[].fields | map[string, DraftField] | 是 | 按字段名的值与提议 |
items[].dependsOn | string[] | ||
items[].baseVersion | string | 起草时应用报告的版本;之后预演报告了别的就是过期 | |
items[].dryRun | DraftExecuteResult | 一次预演或执行的结果 | |
items[].dryRun.applied | boolean | 已生效 | |
items[].dryRun.ref | string | 受影响记录的 k3:// 引用 | |
items[].dryRun.summary | string | 一句话说明这个操作做了什么 | |
items[].dryRun.mark | string | 检查结论:ready、warning、choose、invalid | |
items[].dryRun.issues | object[] | 发现的问题 | |
items[].result | DraftExecuteResult | 一次预演或执行的结果 | |
items[].result.applied | boolean | 已生效 | |
items[].result.ref | string | 受影响记录的 k3:// 引用 | |
items[].result.summary | string | 一句话说明这个操作做了什么 | |
items[].result.mark | string | 检查结论:ready、warning、choose、invalid | |
items[].result.issues | object[] | 发现的问题 | |
items[].mark | string | 现算的检查结论 | |
items[].applicable | boolean | 现算的:能否应用 | |
items[].turns | string[] | 提议过这一项的轮次,旧的在前 | |
createdAt | string(date-time) | 是 | |
updatedAt | string(date-time) | 是 | |
others | DraftOtherApp[] | 其他应用的项的数量 | |
others[].app | string | 是 | |
others[].pending | integer | 是 | |
others[].applied | integer | 是 | |
ops | map[string, object] | 返回的项用到的操作的声明,键是“应用.操作”:标题、输入模式、风险和本人要做的事 | |
merged | DraftItemRef[] | 并入了已有待办项的请求项,以及它们现在在哪 | |
merged[].draftId | string | 是 | |
merged[].itemId | string | 是 | |
merged[].key | string | 请求里给它的 key |
示例:
{
"id": "d_01HZX",
"owner": "u_1001",
"summary": "把李明的会员有效期延长到 2027-03-31",
"status": "open",
"items": [
{
"id": "i_1",
"app": "crm",
"op": "member.update",
"target": "k3://members/member/m_42",
"revision": 1,
"state": "pending",
"fields": {},
"mark": "ready",
"applicable": true
}
],
"createdAt": "2026-10-31T08:00:00Z",
"updatedAt": "2026-10-31T08:00:00Z"
}GET /drafts/{id}
读取一份草稿:本应用的项是完整的
需要范围 app.drafts:read。English: one draft with this app's items in full (the review page).
只收页面会话:这里的“人”是令牌里的人,应用自己的令牌是 403 forbidden。revalidate=1 先把检查重跑一遍再回答。
- 认证:
bearer - 范围:
app.drafts:read - operationId:
getDraft
参数
| 名称 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
id | path | string | 是 | 草稿 id |
revalidate | query | string | 传 1 时先重跑检查 可选值: 1 |
响应
| 状态 | 说明 |
|---|---|
| 200 | 草稿 |
| 400 | 草稿服务的拒绝,状态由它定(400、403、404、409、422 等)。见 DraftRefused |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
200 响应正文(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
id | string | 是 | |
tenant | string | ||
owner | string | 是 | 草稿属于的人;只有他们能应用 |
sessionId | string | ||
origin | string | 来源。普通草稿为空 | |
summary | string | ||
status | string | 是 | 可选值:open、applied、discarded、partial |
items | DraftItem[] | 是 | |
items[].id | string | 是 | |
items[].app | string | 是 | |
items[].op | string | 是 | |
items[].target | string | 要改或删的记录的 k3:// 引用 | |
items[].revision | integer | 是 | 每次改动加一;应用时必须与本人看到的一致 |
items[].state | string | 状态。省略是 pending 可选值: pending、applied、abandoned | |
items[].group | string | ||
items[].reason | string | ||
items[].fields | map[string, DraftField] | 是 | 按字段名的值与提议 |
items[].dependsOn | string[] | ||
items[].baseVersion | string | 起草时应用报告的版本;之后预演报告了别的就是过期 | |
items[].dryRun | DraftExecuteResult | 一次预演或执行的结果 | |
items[].dryRun.applied | boolean | 已生效 | |
items[].dryRun.ref | string | 受影响记录的 k3:// 引用 | |
items[].dryRun.summary | string | 一句话说明这个操作做了什么 | |
items[].dryRun.mark | string | 检查结论:ready、warning、choose、invalid | |
items[].dryRun.issues | object[] | 发现的问题 | |
items[].result | DraftExecuteResult | 一次预演或执行的结果 | |
items[].result.applied | boolean | 已生效 | |
items[].result.ref | string | 受影响记录的 k3:// 引用 | |
items[].result.summary | string | 一句话说明这个操作做了什么 | |
items[].result.mark | string | 检查结论:ready、warning、choose、invalid | |
items[].result.issues | object[] | 发现的问题 | |
items[].mark | string | 现算的检查结论 | |
items[].applicable | boolean | 现算的:能否应用 | |
items[].turns | string[] | 提议过这一项的轮次,旧的在前 | |
createdAt | string(date-time) | 是 | |
updatedAt | string(date-time) | 是 | |
others | DraftOtherApp[] | 其他应用的项的数量 | |
others[].app | string | 是 | |
others[].pending | integer | 是 | |
others[].applied | integer | 是 | |
ops | map[string, object] | 返回的项用到的操作的声明,键是“应用.操作”:标题、输入模式、风险和本人要做的事 | |
merged | DraftItemRef[] | 并入了已有待办项的请求项,以及它们现在在哪 | |
merged[].draftId | string | 是 | |
merged[].itemId | string | 是 | |
merged[].key | string | 请求里给它的 key |
示例:
{
"id": "d_01HZX",
"owner": "u_1001",
"summary": "把李明的会员有效期延长到 2027-03-31",
"status": "open",
"items": [
{
"id": "i_1",
"app": "crm",
"op": "member.update",
"target": "k3://members/member/m_42",
"revision": 1,
"state": "pending",
"fields": {},
"mark": "ready",
"applicable": true
}
],
"createdAt": "2026-10-31T08:00:00Z",
"updatedAt": "2026-10-31T08:00:00Z"
}PATCH /drafts/{id}/items/{item}
记下本人对一个草稿项的值和选择
需要范围 app.drafts:review。English: the person's values and choices for one item.
只收页面会话:这里的“人”是令牌里的人,应用自己的令牌是 403 forbidden。revision 是本人看到的版本;fields 是他们填的值;pick 按字段说选哪个值(base 保持原样,某一轮则取那一轮的提议,空串取最新)。返回 {item}。
- 认证:
bearer - 范围:
app.drafts:review - operationId:
reviewDraftItem
参数
| 名称 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
id | path | string | 是 | 草稿 id |
item | path | string | 是 | 草稿项 id |
请求正文(必填)(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
revision | integer | 是 | 本人看到的版本 |
fields | object | 本人填的值,按字段名 | |
pick | map[string, string] | 按字段选哪个值:base 保持原样,某一轮则取那一轮的提议,空串取最新 |
示例:
{
"revision": 1,
"fields": {
"validUntil": "2027-06-30"
}
}响应
| 状态 | 说明 |
|---|---|
| 200 | 更新后的草稿项 |
| 400 | 草稿服务的拒绝,状态由它定(400、403、404、409、422 等)。见 DraftRefused |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 413 | payload_too_large:正文太大。见 PayloadTooLarge |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
200 响应正文(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
item | DraftItem | 是 | 草稿里的一项:一个应用的一个操作 |
item.id | string | 是 | |
item.app | string | 是 | |
item.op | string | 是 | |
item.target | string | 要改或删的记录的 k3:// 引用 | |
item.revision | integer | 是 | 每次改动加一;应用时必须与本人看到的一致 |
item.state | string | 状态。省略是 pending 可选值: pending、applied、abandoned | |
item.group | string | ||
item.reason | string | ||
item.fields | map[string, DraftField] | 是 | 按字段名的值与提议 |
item.dependsOn | string[] | ||
item.baseVersion | string | 起草时应用报告的版本;之后预演报告了别的就是过期 | |
item.dryRun | DraftExecuteResult | 一次预演或执行的结果 | |
item.dryRun.applied | boolean | 已生效 | |
item.dryRun.ref | string | 受影响记录的 k3:// 引用 | |
item.dryRun.summary | string | 一句话说明这个操作做了什么 | |
item.dryRun.mark | string | 检查结论:ready、warning、choose、invalid | |
item.dryRun.issues | object[] | 发现的问题 | |
item.result | DraftExecuteResult | 一次预演或执行的结果 | |
item.result.applied | boolean | 已生效 | |
item.result.ref | string | 受影响记录的 k3:// 引用 | |
item.result.summary | string | 一句话说明这个操作做了什么 | |
item.result.mark | string | 检查结论:ready、warning、choose、invalid | |
item.result.issues | object[] | 发现的问题 | |
item.mark | string | 现算的检查结论 | |
item.applicable | boolean | 现算的:能否应用 | |
item.turns | string[] | 提议过这一项的轮次,旧的在前 |
POST /drafts/{id}/items/{item}/abandon
放弃一个草稿项
需要范围 app.drafts:review。English: drops one item.
只收页面会话:这里的“人”是令牌里的人,应用自己的令牌是 403 forbidden。返回 {ok: true}。
- 认证:
bearer - 范围:
app.drafts:review - operationId:
abandonDraftItem
参数
| 名称 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
id | path | string | 是 | 草稿 id |
item | path | string | 是 | 草稿项 id |
Idempotency-Key | header | string | 每个 POST 都收。SDK 未传入时会生成 uuid v4。24 小时内同键同正文重放第一次的回答 最短 1,最长 255 |
响应
| 状态 | 说明 |
|---|---|
| 200 | 已放弃 |
| 400 | 草稿服务的拒绝,状态由它定(400、403、404、409、422 等)。见 DraftRefused |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
200 响应正文(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
ok | boolean | 是 |
示例:
{
"ok": true
}POST /drafts/{id}/items/{item}/rebase
以记录现在的样子为基础继续这个草稿项
需要范围 app.drafts:review。English: goes on from the record as it is now.
只收页面会话:这里的“人”是令牌里的人,应用自己的令牌是 403 forbidden。返回 {item}。
- 认证:
bearer - 范围:
app.drafts:review - operationId:
rebaseDraftItem
参数
| 名称 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
id | path | string | 是 | 草稿 id |
item | path | string | 是 | 草稿项 id |
Idempotency-Key | header | string | 每个 POST 都收。SDK 未传入时会生成 uuid v4。24 小时内同键同正文重放第一次的回答 最短 1,最长 255 |
响应
| 状态 | 说明 |
|---|---|
| 200 | 重新定基后的草稿项 |
| 400 | 草稿服务的拒绝,状态由它定(400、403、404、409、422 等)。见 DraftRefused |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
200 响应正文(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
item | DraftItem | 是 | 草稿里的一项:一个应用的一个操作 |
item.id | string | 是 | |
item.app | string | 是 | |
item.op | string | 是 | |
item.target | string | 要改或删的记录的 k3:// 引用 | |
item.revision | integer | 是 | 每次改动加一;应用时必须与本人看到的一致 |
item.state | string | 状态。省略是 pending 可选值: pending、applied、abandoned | |
item.group | string | ||
item.reason | string | ||
item.fields | map[string, DraftField] | 是 | 按字段名的值与提议 |
item.dependsOn | string[] | ||
item.baseVersion | string | 起草时应用报告的版本;之后预演报告了别的就是过期 | |
item.dryRun | DraftExecuteResult | 一次预演或执行的结果 | |
item.dryRun.applied | boolean | 已生效 | |
item.dryRun.ref | string | 受影响记录的 k3:// 引用 | |
item.dryRun.summary | string | 一句话说明这个操作做了什么 | |
item.dryRun.mark | string | 检查结论:ready、warning、choose、invalid | |
item.dryRun.issues | object[] | 发现的问题 | |
item.result | DraftExecuteResult | 一次预演或执行的结果 | |
item.result.applied | boolean | 已生效 | |
item.result.ref | string | 受影响记录的 k3:// 引用 | |
item.result.summary | string | 一句话说明这个操作做了什么 | |
item.result.mark | string | 检查结论:ready、warning、choose、invalid | |
item.result.issues | object[] | 发现的问题 | |
item.mark | string | 现算的检查结论 | |
item.applicable | boolean | 现算的:能否应用 | |
item.turns | string[] | 提议过这一项的轮次,旧的在前 |
POST /drafts/{id}/apply
应用本人审阅过的草稿项
需要范围 app.drafts:review。English: applies this app's items the person reviewed, with the pending items they depend on.
只收页面会话:这里的“人”是令牌里的人,应用自己的令牌是 403 forbidden。items 里每项是 {id, revision, confirmed?},revision 必须是本人看到的版本。返回草稿的新状态和每一项的结果(results 按项 id 索引)。
- 认证:
bearer - 范围:
app.drafts:review - operationId:
applyDraft
参数
| 名称 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
id | path | string | 是 | 草稿 id |
Idempotency-Key | header | string | 每个 POST 都收。SDK 未传入时会生成 uuid v4。24 小时内同键同正文重放第一次的回答 最短 1,最长 255 |
请求正文(必填)(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
items | DraftApplyItem[] | 是 | |
items[].id | string | 是 | |
items[].revision | integer | 是 | |
items[].confirmed | boolean | 本人确认了操作 intervention.confirm 里写的事 |
示例:
{
"items": [
{
"id": "i_1",
"revision": 1,
"confirmed": true
}
]
}响应
| 状态 | 说明 |
|---|---|
| 200 | 应用的结果 |
| 400 | 草稿服务的拒绝,状态由它定(400、403、404、409、422 等)。见 DraftRefused |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 413 | payload_too_large:正文太大。见 PayloadTooLarge |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
200 响应正文(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
status | string | 是 | 可选值:open、applied、discarded、partial |
results | map[string, DraftExecuteResult] | 是 | 按项 id |
示例:
{
"status": "applied",
"results": {
"i_1": {
"applied": true,
"ref": "k3://members/member/m_42",
"summary": "有效期延至 2027-03-31"
}
}
}GET /provenance
查一条记录是谁写的
需要范围 app.drafts:read。English: who wrote a record of this app: a draft the person applied, or a policy they pre-signed.
只收页面会话:这里的“人”是令牌里的人,应用自己的令牌是 403 forbidden。ref 必填,是记录的 k3:// 引用。返回 {provenance}。
- 认证:
bearer - 范围:
app.drafts:read - operationId:
getProvenance
参数
| 名称 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
ref | query | string | 是 | 记录的 k3:// 引用 |
响应
| 状态 | 说明 |
|---|---|
| 200 | 来源 |
| 400 | 草稿服务的拒绝,状态由它定(400、403、404、409、422 等)。见 DraftRefused |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
200 响应正文(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
provenance | DraftProvenance[] | 是 | |
provenance[].ref | string | 是 | |
provenance[].at | string(date-time) | 是 | |
provenance[].app | string | 是 | |
provenance[].op | string | 是 | |
provenance[].via | string | 是 | 本人应用了一份草稿,还是预先签了策略 可选值: draft、policy |
provenance[].draftId | string | 是 | |
provenance[].itemId | string | 是 | |
provenance[].policyId | string | ||
provenance[].subject | string | 是 | 本人的用户 id |
provenance[].name | string |
示例:
{
"provenance": [
{
"ref": "k3://members/member/m_42",
"at": "2026-10-31T08:05:00Z",
"app": "crm",
"op": "member.update",
"via": "draft",
"draftId": "d_01HZX",
"itemId": "i_1",
"subject": "u_1001",
"name": "王芳"
}
]
}outreach
触达:向客户排短信或公众号模板消息,读渠道、模板和消息记录(是否发出由平台在发送时判断)
POST /outreach/send
向一位客户排一条触达消息
需要范围 app.outreach:send。English: queues a message to a customer by a template of the tenant's; the platform decides at send time whether it may go.
应用不发送,也看不到手机号:同意、退订、免打扰、频次和企业上限都由平台在发送时判断。key 是这条消息的幂等键,必填;同键再来不会加新消息,回 200 和当初那条的 id(existing 为 true);新排上的回 202。purpose 是 service(服务通知)或 marketing(营销)。
- 认证:
bearer - 范围:
app.outreach:send - operationId:
sendOutreach
参数
| 名称 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
Idempotency-Key | header | string | 每个 POST 都收。SDK 未传入时会生成 uuid v4。24 小时内同键同正文重放第一次的回答 最短 1,最长 255 |
请求正文(必填)(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
key | string | 是 | 这条消息的幂等键。同键再来不会加新消息 |
customer | string | 是 | 客户 id |
channel | string | 是 | 渠道种类,例如 sms |
template | string | 是 | 模板 id |
vars | map[string, string] | 模板里的变量,按名字 | |
purpose | string | 是 | 服务通知,或营销 可选值: service、marketing |
triggerRef | string | 是什么引起的,k3:// 引用,写进日志,不含个人信息 |
示例:
{
"key": "o:k3://order/order/o_1|c_88|sms",
"customer": "c_88",
"channel": "sms",
"template": "tpl_order_ok",
"vars": {
"order": "A1024"
},
"purpose": "service",
"triggerRef": "k3://order/order/o_1"
}响应
| 状态 | 说明 |
|---|---|
| 202 | 已排上(同键再来是 200,existing 为 true) |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 404 | not_found:对应的记录不存在(客户中心没有这个客户,访客、服务或所指的东西不存在)。见 NotFound |
| 413 | payload_too_large:正文太大。见 PayloadTooLarge |
| 422 | 字段或参数不被接受(正文读不出来、有未知字段、缺必填、取值越界)。见 Unprocessable |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
202 响应正文(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
id | string | 是 | 消息 id |
existing | boolean | 是 | 这个 key 以前排过:没有加新消息,id 是当初那条 |
示例:
{
"id": "msg_01HZY",
"existing": false
}GET /outreach/channels
列出触达渠道及其是否就绪
需要范围 app.outreach:read。English: the tenant's outreach channels and whether each can send.
返回 {items}。渠道的密钥不会出现,只有 secret.set 和指纹。
- 认证:
bearer - 范围:
app.outreach:read - operationId:
listOutreachChannels
响应
| 状态 | 说明 |
|---|---|
| 200 | 渠道 |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 422 | 字段或参数不被接受(正文读不出来、有未知字段、缺必填、取值越界)。见 Unprocessable |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
200 响应正文(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
items | OutreachChannel[] | 是 | |
items[].kind | string | 是 | 渠道种类,例如 sms |
items[].name | string | 是 | |
items[].registered | boolean | 是 | 平台这个进程能经它发送 |
items[].configured | boolean | 是 | |
items[].enabled | boolean | 是 | |
items[].ready | boolean | 是 | 已配置、已打开(公众号还要已绑定) |
items[].provider | string | ||
items[].signature | string | ||
items[].keyId | string | ||
items[].region | string | ||
items[].appId | string | ||
items[].secret | OutreachSecretInfo | 是 | |
items[].secret.set | boolean | 是 | 已设置密钥 |
items[].secret.fingerprint | string | 密钥的指纹 | |
items[].callbackUrl | string | ||
items[].replyUrl | string | ||
items[].status | string | ||
items[].note | string | ||
items[].account | string | ||
items[].lastTest | object | 上一次测试发送的结果 | |
items[].updatedBy | string | ||
items[].updatedAt | string(date-time) | ||
items[].capabilities | object | 是 | 渠道的能力:needsTemplate、receipts、unsubReply、idempotent 等 |
示例:
{
"items": [
{
"kind": "sms",
"name": "短信",
"registered": true,
"configured": true,
"enabled": true,
"ready": true,
"provider": "aliyun",
"signature": "示例企业",
"secret": {
"set": true,
"fingerprint": "a1b2c3"
},
"capabilities": {
"needsTemplate": true,
"receipts": true
}
}
]
}GET /outreach/templates
列出消息模板
需要范围 app.outreach:read。English: the tenant's message templates.
channel 只要这个渠道的模板;archived=1 连归档的也要。返回 {items}。
- 认证:
bearer - 范围:
app.outreach:read - operationId:
listOutreachTemplates
参数
| 名称 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
channel | query | string | 渠道种类,例如 sms | |
archived | query | string | 传 1 时包含归档的模板 |
响应
| 状态 | 说明 |
|---|---|
| 200 | 模板 |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 422 | 字段或参数不被接受(正文读不出来、有未知字段、缺必填、取值越界)。见 Unprocessable |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
200 响应正文(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
items | OutreachTemplate[] | 是 | |
items[].id | string | 是 | |
items[].channel | string | 是 | |
items[].name | string | 是 | |
items[].purpose | string | 是 | 可选值:service、marketing |
items[].body | string | 是 | 正文,变量写成 {变量名} |
items[].fields | OutreachTemplateField[] | ||
items[].fields[].name | string | 是 | |
items[].fields[].value | string | 是 | |
items[].paramNames | string[] | ||
items[].channelTemplateId | string | 渠道方(短信商、公众号)的模板编号 | |
items[].url | string | ||
items[].approvalState | string | 是 | 审核状态,例如 unsubmitted、approved |
items[].approvalNote | string | ||
items[].version | integer | 是 | |
items[].active | boolean | 是 | |
items[].variables | string[] | 正文里用到的变量 | |
items[].warnings | string[] | ||
items[].used | integer | 用它发过的消息数 | |
items[].createdBy | string | ||
items[].updatedBy | string | ||
items[].createdAt | string(date-time) | ||
items[].updatedAt | string(date-time) |
GET /outreach/templates/{id}
读取一个消息模板
需要范围 app.outreach:read。English: one message template.
不存在是 404 not_found。
- 认证:
bearer - 范围:
app.outreach:read - operationId:
getOutreachTemplate
参数
| 名称 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
id | path | string | 是 | 模板 id |
响应
| 状态 | 说明 |
|---|---|
| 200 | 模板 |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 404 | not_found:对应的记录不存在(客户中心没有这个客户,访客、服务或所指的东西不存在)。见 NotFound |
| 422 | 字段或参数不被接受(正文读不出来、有未知字段、缺必填、取值越界)。见 Unprocessable |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
200 响应正文(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
id | string | 是 | |
channel | string | 是 | |
name | string | 是 | |
purpose | string | 是 | 可选值:service、marketing |
body | string | 是 | 正文,变量写成 {变量名} |
fields | OutreachTemplateField[] | ||
fields[].name | string | 是 | |
fields[].value | string | 是 | |
paramNames | string[] | ||
channelTemplateId | string | 渠道方(短信商、公众号)的模板编号 | |
url | string | ||
approvalState | string | 是 | 审核状态,例如 unsubmitted、approved |
approvalNote | string | ||
version | integer | 是 | |
active | boolean | 是 | |
variables | string[] | 正文里用到的变量 | |
warnings | string[] | ||
used | integer | 用它发过的消息数 | |
createdBy | string | ||
updatedBy | string | ||
createdAt | string(date-time) | ||
updatedAt | string(date-time) |
示例:
{
"id": "tpl_order_ok",
"channel": "sms",
"name": "订单确认",
"purpose": "service",
"body": "您的订单{order}已确认",
"channelTemplateId": "SMS_NOTICE",
"approvalState": "approved",
"version": 1,
"active": true,
"variables": [
"order"
],
"used": 128,
"createdAt": "2026-09-01T08:00:00Z",
"updatedAt": "2026-09-01T08:00:00Z"
}GET /outreach/messages/{id}
读取一条触达消息的状态
需要范围 app.outreach:read。English: one message of the outreach log, with its state and, when it was not sent, the reason.
不存在是 404 not_found。
- 认证:
bearer - 范围:
app.outreach:read - operationId:
getOutreachMessage
参数
| 名称 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
id | path | string | 是 | 消息 id(发送时回答的 id) |
响应
| 状态 | 说明 |
|---|---|
| 200 | 消息 |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 404 | not_found:对应的记录不存在(客户中心没有这个客户,访客、服务或所指的东西不存在)。见 NotFound |
| 422 | 字段或参数不被接受(正文读不出来、有未知字段、缺必填、取值越界)。见 Unprocessable |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
200 响应正文(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
id | string | 是 | |
customer | string | 是 | |
customerName | string | ||
channel | string | 是 | |
template | string | 是 | |
templateName | string | ||
templateVersion | integer | ||
purpose | string | ||
triggerApp | string | ||
triggerRef | string | ||
vars | map[string, string] | ||
state | string | 是 | 状态,例如 queued、sent、delivered、failed、skipped |
reason | string | 没发出时的原因码 | |
reasonText | string | 原因的话 | |
detail | string | ||
attempts | integer | 是 | |
providerRef | string | ||
cost | integer | ||
deliverAfter | string(date-time) | ||
sentAt | string(date-time) | ||
deliveredAt | string(date-time) | ||
createdBy | string | ||
createdAt | string(date-time) | 是 | |
updatedAt | string(date-time) | 是 |
示例:
{
"id": "msg_01HZY",
"customer": "c_88",
"channel": "sms",
"template": "tpl_order_ok",
"templateName": "订单确认",
"templateVersion": 1,
"purpose": "service",
"vars": {
"order": "A1024"
},
"state": "sent",
"attempts": 1,
"cost": 1,
"sentAt": "2026-10-31T08:00:05Z",
"createdAt": "2026-10-31T08:00:00Z",
"updatedAt": "2026-10-31T08:00:05Z"
}GET /outreach/customers/{id}/messages
本企业一位客户在各渠道收到过的消息(opv2 J2 ⑤)
需要范围 app.outreach:reach。English: the messages a customer of the tenant was sent on every channel, newest first, trimmed.
只限本企业的客户:别的 id 是 404 not_found;合并过的客户按主客户读(返回的 customer 是主客户)。应用自己的调用(企业令牌)可读本企业任何客户;页面会话里的人只能读他在客户应用里「查看客户」(customer.read)数据范围内的客户,范围外的与不存在一样返回 404。每条只有渠道、用途、状态、原因与时间;模板和触发来源只在本应用自己发的消息上给(mine)。没有消息内容、变量和接收号码。
- 认证:
bearer - 范围:
app.outreach:reach - operationId:
listCustomerOutreach
参数
| 名称 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
id | path | string | 是 | 客户 id |
since | query | string(date-time) | 只列这个时间及以后建的消息(RFC 3339) | |
limit | query | integer | 最多几条 默认 50最小 1,最大 200 |
响应
| 状态 | 说明 |
|---|---|
| 200 | 消息,新的在前 |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 404 | not_found:对应的记录不存在(客户中心没有这个客户,访客、服务或所指的东西不存在)。见 NotFound |
| 422 | 字段或参数不被接受(正文读不出来、有未知字段、缺必填、取值越界)。见 Unprocessable |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
200 响应正文(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
customer | string | 是 | 主客户 id |
items | SentMessage[] | 是 | |
items[].id | string | 是 | 消息 id |
items[].channel | string | 是 | 渠道种类 |
items[].purpose | string | 是 | service 或 marketing |
items[].state | string | 是 | queued、sent、delivered、skipped、failed 或 cancelled |
items[].reason | string | 没发出或失败的原因代码 | |
items[].mine | boolean | 是 | 本应用发的 |
items[].template | string | 模板 id(只在 mine 时) | |
items[].triggerRef | string | 触发来源(只在 mine 时) | |
items[].createdAt | string(date-time) | 是 | |
items[].sentAt | string(date-time) | ||
items[].deliveredAt | string(date-time) |
POST /outreach/reachable
发送前问:这位客户现在能不能经这个渠道、为这个用途被触达(opv2 J2 ⑤)
需要范围 app.outreach:reach。English: whether the customer can be reached on the channel for the purpose now; nothing is reserved.
按发送时同样的顺序检查,只答能或不能和第一个不能的原因:渠道没开(channel_off);撤回了同意(withdrawn);营销消息没有同意(no_consent);没有手机号或 openid(no_identity);30 天内被服务商拦截过(blocked);营销的每日、每周频控(freq_day、freq_week);企业每日营销上限(tenant_cap)。能触达但在免打扰时段时,later 是会发出的时间。只读,不占频次;真正发送时平台会再查一遍。只限本企业的客户(别的 id 404);页面会话里的人只限他「查看客户」数据范围内的客户,范围外 404。
- 认证:
bearer - 范围:
app.outreach:reach - operationId:
checkReachable
参数
| 名称 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
Idempotency-Key | header | string | 每个 POST 都收。SDK 未传入时会生成 uuid v4。24 小时内同键同正文重放第一次的回答 最短 1,最长 255 |
请求正文(必填)(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
customer | string | 是 | 客户 id |
channel | string | 是 | 渠道种类,例如 sms |
purpose | string | 是 | service 或 marketing |
响应
| 状态 | 说明 |
|---|---|
| 200 | 能或不能 |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 404 | not_found:对应的记录不存在(客户中心没有这个客户,访客、服务或所指的东西不存在)。见 NotFound |
| 422 | 字段或参数不被接受(正文读不出来、有未知字段、缺必填、取值越界)。见 Unprocessable |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
200 响应正文(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
reachable | boolean | 是 | 现在能不能触达 |
reason | string | 第一个不能的原因代码 | |
later | string(date-time) | 免打扰时段里营销消息会发出的时间 |
options
选项列表:企业为本应用的文本字段维护的可选值
GET /options/{list}
读取企业为本应用某个字段维护的选项列表
需要范围 app.options:read。English: the list of choices the tenant keeps for a text field of the app.
企业从没保存过时,回答的是 default 给的默认值。返回 {items}。
- 认证:
bearer - 范围:
app.options:read - operationId:
getOptions
参数
| 名称 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
list | path | string | 是 | 列表的键:小写字母开头,只含小写字母、数字和 -,最长 64 |
default | query | string | 企业从没保存过这个列表时的默认选项。可以重复;SDK 的参数一次只带一个 |
响应
| 状态 | 说明 |
|---|---|
| 200 | 选项 |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 422 | 字段或参数不被接受(正文读不出来、有未知字段、缺必填、取值越界)。见 Unprocessable |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
200 响应正文(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
items | string[] | 是 | 选项 |
示例:
{
"items": [
"门店",
"线上",
"转介绍"
]
}PUT /options/{list}
整体替换或追加一个选项列表
需要范围 app.options:write。English: replaces the whole list (items), or adds one option (add).
items 与 add 至少给一个。列表的声明(title、maxLen、defaults)每次随调用带上。带 K3-Dry-Run: 1 时只检查,不保存。返回改动前(old)和改动后(now)的列表。
- 认证:
bearer - 范围:
app.options:write - operationId:
putOptions
参数
| 名称 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
list | path | string | 是 | 列表的键:小写字母开头,只含小写字母、数字和 -,最长 64 |
K3-Dry-Run | header | string | 传 1 时只预演:回答和真做一样,什么也不留下 可选值: 1 |
请求正文(必填)(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
title | string | 列表的名字。省略时用键 | |
maxLen | integer | 每个选项最多多少个字符 | |
defaults | string[] | 企业从没保存过时的默认选项 | |
items | string[] | 整个列表,替换原来的 | |
add | string | 追加一个选项 |
示例:
{
"title": "客户来源",
"maxLen": 20,
"add": "展会"
}响应
| 状态 | 说明 |
|---|---|
| 200 | 改动前后的列表 |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 413 | payload_too_large:正文太大。见 PayloadTooLarge |
| 422 | 字段或参数不被接受(正文读不出来、有未知字段、缺必填、取值越界)。见 Unprocessable |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
200 响应正文(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
old | string[] | 是 | 改动前 |
now | string[] | 是 | 改动后 |
示例:
{
"old": [
"门店",
"线上"
],
"now": [
"门店",
"线上",
"展会"
]
}models
企业的服务模型:起草文字、读图片、转写语音(计入企业的用量与预算)
GET /models
问企业有没有开放服务模型
需要范围 app.models:use。English: whether a service model is on offer, whether speech is transcribed, and the model's name.
返回 model(有无模型)、transcribe(能否转写语音)、serviceModel(模型名,平台不说时省略)。
- 认证:
bearer - 范围:
app.models:use - operationId:
getModelStatus
响应
| 状态 | 说明 |
|---|---|
| 200 | 模型状态 |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
200 响应正文(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
model | boolean | 是 | 有服务模型可用 |
transcribe | boolean | 是 | 能转写语音 |
serviceModel | string | 服务模型的名字。平台不说时省略 |
示例:
{
"model": true,
"transcribe": true,
"serviceModel": "service-default"
}POST /models/complete
用企业的服务模型起草文字
需要范围 app.models:use。English: drafts text with the model the tenant's administrator chose for service scenes.
调用算调用者的:页面会话的人被屏蔽、企业的预算和限流都照常生效,用量按 scene 计。scene 是小写字母开头的字母、数字和下划线(最长 64),system 加 user 最多 256 KiB。图片走 /models/read。企业没有开放模型时是 503,正文里 code 为 model_off(不在 ErrorCode 里,按状态和这个字段判断);预算或限流的拒绝保留模型路由器的状态和原话。
- 认证:
bearer - 范围:
app.models:use - operationId:
completeModel
参数
| 名称 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
Idempotency-Key | header | string | 每个 POST 都收。SDK 未传入时会生成 uuid v4。24 小时内同键同正文重放第一次的回答 最短 1,最长 255 |
请求正文(必填)(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
scene | string | 是 | 这次用途的名字,用量报表按它分开 格式 ^[a-z][a-z0-9_]{0,63}$ |
system | string | 系统提示 | |
user | string | 是 | 用户的话。不能为空 |
images | ModelImage[] | 图片。只有 /models/read 收 | |
images[].mime | string | 是 | 图片类型 可选值: image/png、image/jpeg、image/webp |
images[].data | string(byte) | 是 | 图片字节的 base64 |
示例:
{
"scene": "reply_draft",
"system": "你是客服,用简短、礼貌的口吻回复。",
"user": "客户问:订单什么时候发货?"
}响应
| 状态 | 说明 |
|---|---|
| 200 | 模型的回答 |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 413 | payload_too_large:正文太大。见 PayloadTooLarge |
| 422 | 字段或参数不被接受(正文读不出来、有未知字段、缺必填、取值越界)。见 Unprocessable |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
200 响应正文(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
text | string | 是 |
示例:
{
"text": "您好,订单会在 24 小时内发出,发货后会短信通知您。"
}POST /models/read
让企业的服务模型读文字加图片
需要范围 app.models:use。English: reads a document with pictures with the service model.
images 每张是 {mime, data}:mime 为 image/png、image/jpeg 或 image/webp,data 是 base64。整个请求最大 24 MiB。企业没有开放模型时是 503,正文里 code 为 model_off(不在 ErrorCode 里,按状态和这个字段判断);预算或限流的拒绝保留模型路由器的状态和原话。
- 认证:
bearer - 范围:
app.models:use - operationId:
readWithModel
参数
| 名称 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
Idempotency-Key | header | string | 每个 POST 都收。SDK 未传入时会生成 uuid v4。24 小时内同键同正文重放第一次的回答 最短 1,最长 255 |
请求正文(必填)(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
scene | string | 是 | 这次用途的名字,用量报表按它分开 格式 ^[a-z][a-z0-9_]{0,63}$ |
system | string | 系统提示 | |
user | string | 是 | 用户的话。不能为空 |
images | ModelImage[] | 图片。只有 /models/read 收 | |
images[].mime | string | 是 | 图片类型 可选值: image/png、image/jpeg、image/webp |
images[].data | string(byte) | 是 | 图片字节的 base64 |
示例:
{
"scene": "reply_draft",
"system": "你是客服,用简短、礼貌的口吻回复。",
"user": "客户问:订单什么时候发货?"
}响应
| 状态 | 说明 |
|---|---|
| 200 | 模型的回答 |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 413 | payload_too_large:正文太大。见 PayloadTooLarge |
| 422 | 字段或参数不被接受(正文读不出来、有未知字段、缺必填、取值越界)。见 Unprocessable |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
200 响应正文(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
text | string | 是 |
示例:
{
"text": "您好,订单会在 24 小时内发出,发货后会短信通知您。"
}POST /models/transcribe
把一段录音转成文字
需要范围 app.models:use。English: turns the recording in the body into text.
正文是录音的原始字节,Content-Type 必须是 audio/…,最大 25 MB,不能为空。回答 {text}。企业没有开放模型时是 503,正文里 code 为 model_off(不在 ErrorCode 里,按状态和这个字段判断);预算或限流的拒绝保留模型路由器的状态和原话。
SDK:Go App.Models.Transcribe,TS app.models.transcribe;录音的 Content-Type 由调用方给出。
- 认证:
bearer - 范围:
app.models:use - operationId:
transcribeAudio
参数
| 名称 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
Idempotency-Key | header | string | 每个 POST 都收。SDK 未传入时会生成 uuid v4。24 小时内同键同正文重放第一次的回答 最短 1,最长 255 |
请求正文(必填)(audio/*)
类型 string(binary)
录音的字节
响应
| 状态 | 说明 |
|---|---|
| 200 | 转写的文字 |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 413 | payload_too_large:正文太大。见 PayloadTooLarge |
| 422 | 字段或参数不被接受(正文读不出来、有未知字段、缺必填、取值越界)。见 Unprocessable |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
200 响应正文(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
text | string | 是 |
示例:
{
"text": "您好,订单会在 24 小时内发出,发货后会短信通知您。"
}intent
意图解析:把当前人员的一句话(可带图片)解析成本应用某个操作的输入建议,由本人确认后再提交
POST /intent/parse
把一句话解析成本应用某个操作的输入建议
需要范围 app.intent:parse。English: turns one sentence of the page session's person (and up to 3 photos) into a proposal for the input of one of this app's ops, the same answer an app in the platform's process gets at /api/intent/parse on its own origin. Nothing is submitted: the person confirms the proposal with the op itself.
只收页面会话:应用自己的令牌是 403,正文里 code 为 person_required(解析按人进行:他能用的操作、他看得到的记录)。app 可省略,省略时就是本应用;写了别的应用是 422。op 必须是本应用清单里的操作:当前人员看不到本应用是 404(code 为 app_not_available),操作不能解析是 422(code 为 op_not_parsable)。规则能读出的(日期、时间、金额、手机号、数量、页面所在的记录)不调模型、不计费;其余的经企业的服务模型(场景 intent)读出,按用量计点,usage 说明这次花了多少。text 最多 2000 个字符;attachments 最多 3 张图片(png、jpeg、webp、gif,每张最大 5 MiB,base64 或 data: URL),整个请求约 21 MiB;context.refs 最多 20 个 k3:// 引用。每人每分钟最多 30 次,超过是 429。Idempotency-Key 收下但不保存回答:解析不写任何东西,重试就是再解析一次(再计一次用量)。企业没有开放模型时只用规则读(by 为 rules)。平台没有接上解析服务时是 501(code 为 capability_off),接上了但没有配置解析器时是 503(code 为 intent_off);模型这次读不出来是 502,code 为 intent_failed(页面改让人填表)。这几个 code 不在 ErrorCode 里,按状态和这个字段判断。
- 认证:
bearer - 范围:
app.intent:parse - operationId:
parseIntent
参数
| 名称 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
Idempotency-Key | header | string | 每个 POST 都收。SDK 未传入时会生成 uuid v4。24 小时内同键同正文重放第一次的回答 最短 1,最长 255 |
请求正文(必填)(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
app | string | 应用 id。省略就是本应用,写别的应用是 422 | |
op | string | 是 | 本应用清单里的操作名 |
text | string | 这句话。没有图片时不能为空 最长 2000 | |
attachments | IntentAttachment[] | 图片(例如发票照片) 最多 3 项 | |
attachments[].name | string | 文件名 | |
attachments[].mime | string | image/png、image/jpeg、image/webp 或 image/gif;data 是 data: URL 时可省略 | |
attachments[].data | string | 是 | 图片字节的 base64,或 data: URL。最大 5 MiB |
context | IntentContext | 页面知道的:页面所在的记录、当前人员的时间与时区 | |
context.refs | string[] | 页面所在记录的 k3:// 引用 最多 20 项 | |
context.now | string(date-time) | 当前时间(RFC 3339),省略用平台的时钟 | |
context.tz | string | IANA 时区名,省略是 Asia/Shanghai |
示例:
{
"op": "visit.create",
"text": "张三明天下午三点复诊,做肩颈康复",
"context": {
"tz": "Asia/Shanghai"
}
}响应
| 状态 | 说明 |
|---|---|
| 200 | 输入建议 |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 404 | not_found:对应的记录不存在(客户中心没有这个客户,访客、服务或所指的东西不存在)。见 NotFound |
| 413 | payload_too_large:正文太大。见 PayloadTooLarge |
| 422 | 字段或参数不被接受(正文读不出来、有未知字段、缺必填、取值越界)。见 Unprocessable |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
200 响应正文(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
input | object | 是 | 操作的输入(按操作的输入结构校验过) |
fields | map[string, IntentField] | 是 | 每个值从哪来,按字段名 |
missing | string[] | 是 | 还没有值的必填项,确认卡片会问 |
rejected | IntentRejection[] | 读出来但不符合操作的值(名字对不上记录、选项里没有) | |
rejected[].field | string | 是 | |
rejected[].reason | string | 是 | |
by | string | 是 | rules 是只用规则(不计费),model 是调了模型 可选值: rules、model |
usage | IntentUsage | 是 | 这次解析花了多少:计费的 micros,和点数(1 点 = 10,000 micros,两位小数;花了就至少 0.01) |
usage.points | number | 是 | |
usage.micros | integer(int64) | 是 |
示例:
{
"input": {
"customer": "c_8f2",
"startsAt": "2026-11-03T15:00:00+08:00"
},
"fields": {
"customer": {
"source": "stated",
"ref": "k3://customer/customer/c_8f2",
"label": "张三"
},
"startsAt": {
"source": "stated"
}
},
"missing": [],
"by": "model",
"usage": {
"points": 0.02,
"micros": 180
}
}pay
收款:经企业自己的支付宝或微信收款账户向客户收款、关闭未付的单、退款(只看得到本应用的收款单)
POST /pay/orders
经企业的收款账户向客户发起一笔收款
需要范围 app.pay:write。English: asks the tenant's customer to pay through the tenant's own Alipay or WeChat Pay account.
本应用是这张收款单的来源应用,只看得到自己的收款单;款项到账后,平台把结果送到本应用声明的 event:payment 服务。key 是这笔收款的幂等键:同一个业务动作只问一次,同键再来回答第一张单;没写时用请求头 Idempotency-Key,都没有是 422。这个键属于企业,别的应用用过的键是 409 conflict。amountCents 是整数分,ttlSeconds 是多久不付就失效。返回 201、收款单和客户的付款页 link;JSAPI 交易另有 payParams(交给微信的已签名参数,JSON 文本)。
- 认证:
bearer - 范围:
app.pay:write - operationId:
createPayOrder
参数
| 名称 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
Idempotency-Key | header | string | 每个 POST 都收。SDK 未传入时会生成 uuid v4。24 小时内同键同正文重放第一次的回答 最短 1,最长 255 |
请求正文(必填)(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
channel | string | 是 | 收款渠道,例如 alipay、wechat |
product | string | 渠道里的产品。省略是渠道的第一个 | |
amountCents | integer | 是 | 金额,整数分 |
subject | string | 是 | 付款页上的标题 |
sourceRef | string | 这笔收款对应的记录,k3:// 引用 | |
key | string | 幂等键;省略时用请求头 Idempotency-Key | |
ttlSeconds | integer | 多少秒不付就失效。省略用平台默认 | |
returnUrl | string | 付完后浏览器回到哪里(支付宝页面支付、微信 H5) | |
openId | string | JSAPI 交易的付款人 openid | |
clientIp | string | H5 交易付款人的 IP |
示例:
{
"channel": "wechat",
"amountCents": 9900,
"subject": "会员年费",
"sourceRef": "k3://members/member/m_42",
"key": "renew-m_42-2026",
"ttlSeconds": 1800
}响应
| 状态 | 说明 |
|---|---|
| 201 | 收款单 |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 404 | not_found:对应的记录不存在(客户中心没有这个客户,访客、服务或所指的东西不存在)。见 NotFound |
| 409 | 见 Conflict |
| 413 | payload_too_large:正文太大。见 PayloadTooLarge |
| 422 | 字段或参数不被接受(正文读不出来、有未知字段、缺必填、取值越界)。见 Unprocessable |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
201 响应正文(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
tenant | string | ||
id | string | 是 | |
channel | string | 是 | |
product | string | ||
outTradeNo | string | 给渠道的商户单号 | |
amountCents | integer | 是 | |
currency | string | ||
subject | string | ||
status | string | 是 | 状态,例如 pending、paid、closed、refunded |
sourceApp | string | 来源应用,即本应用 | |
sourceRef | string | ||
payToken | string | ||
codeUrl | string | 扫码支付的链接 | |
payUrl | string | 渠道的付款链接 | |
appId | string | ||
channelTradeNo | string | ||
expiresAt | string(date-time) | 是 | |
paidAt | string(date-time) | ||
closedAt | string(date-time) | ||
refundedCents | integer | 是 | 已退多少 |
createdBy | string | ||
createdAt | string(date-time) | 是 | |
settledAt | string(date-time) | ||
settleAttempts | integer | ||
lastError | string | ||
link | string | 客户的付款页 | |
payParams | string | JSAPI 交易交给微信的已签名参数(JSON 文本) |
示例:
{
"id": "po_01HZZ",
"channel": "wechat",
"product": "native",
"outTradeNo": "po_01HZZ",
"amountCents": 9900,
"currency": "CNY",
"subject": "会员年费",
"status": "pending",
"sourceApp": "crm",
"sourceRef": "k3://members/member/m_42",
"expiresAt": "2026-10-31T09:00:00Z",
"refundedCents": 0,
"createdAt": "2026-10-31T08:30:00Z",
"settleAttempts": 0,
"link": "https://pay.example.com/p/abc123"
}GET /pay/orders/{id}
读取本应用的一张收款单
需要范围 app.pay:read。English: one order of the app.
不存在或不是本应用的是 404 not_found。
- 认证:
bearer - 范围:
app.pay:read - operationId:
getPayOrder
参数
| 名称 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
id | path | string | 是 | 收款单 id |
响应
| 状态 | 说明 |
|---|---|
| 200 | 收款单 |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 404 | not_found:对应的记录不存在(客户中心没有这个客户,访客、服务或所指的东西不存在)。见 NotFound |
| 422 | 字段或参数不被接受(正文读不出来、有未知字段、缺必填、取值越界)。见 Unprocessable |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
200 响应正文(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
tenant | string | ||
id | string | 是 | |
channel | string | 是 | |
product | string | ||
outTradeNo | string | 给渠道的商户单号 | |
amountCents | integer | 是 | |
currency | string | ||
subject | string | ||
status | string | 是 | 状态,例如 pending、paid、closed、refunded |
sourceApp | string | 来源应用,即本应用 | |
sourceRef | string | ||
payToken | string | ||
codeUrl | string | 扫码支付的链接 | |
payUrl | string | 渠道的付款链接 | |
appId | string | ||
channelTradeNo | string | ||
expiresAt | string(date-time) | 是 | |
paidAt | string(date-time) | ||
closedAt | string(date-time) | ||
refundedCents | integer | 是 | 已退多少 |
createdBy | string | ||
createdAt | string(date-time) | 是 | |
settledAt | string(date-time) | ||
settleAttempts | integer | ||
lastError | string | ||
link | string | 客户的付款页 | |
payParams | string | JSAPI 交易交给微信的已签名参数(JSON 文本) |
示例:
{
"id": "po_01HZZ",
"channel": "wechat",
"product": "native",
"outTradeNo": "po_01HZZ",
"amountCents": 9900,
"currency": "CNY",
"subject": "会员年费",
"status": "pending",
"sourceApp": "crm",
"sourceRef": "k3://members/member/m_42",
"expiresAt": "2026-10-31T09:00:00Z",
"refundedCents": 0,
"createdAt": "2026-10-31T08:30:00Z",
"settleAttempts": 0,
"link": "https://pay.example.com/p/abc123"
}POST /pay/orders/{id}/cancel
关闭一张还没付的收款单
需要范围 app.pay:write。English: closes an unpaid order.
已付的单不能关(用退款),那是 409 conflict。返回关闭后的收款单。
- 认证:
bearer - 范围:
app.pay:write - operationId:
cancelPayOrder
参数
| 名称 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
id | path | string | 是 | 收款单 id |
Idempotency-Key | header | string | 每个 POST 都收。SDK 未传入时会生成 uuid v4。24 小时内同键同正文重放第一次的回答 最短 1,最长 255 |
响应
| 状态 | 说明 |
|---|---|
| 200 | 关闭后的收款单 |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 404 | not_found:对应的记录不存在(客户中心没有这个客户,访客、服务或所指的东西不存在)。见 NotFound |
| 409 | 见 Conflict |
| 422 | 字段或参数不被接受(正文读不出来、有未知字段、缺必填、取值越界)。见 Unprocessable |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
200 响应正文(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
tenant | string | ||
id | string | 是 | |
channel | string | 是 | |
product | string | ||
outTradeNo | string | 给渠道的商户单号 | |
amountCents | integer | 是 | |
currency | string | ||
subject | string | ||
status | string | 是 | 状态,例如 pending、paid、closed、refunded |
sourceApp | string | 来源应用,即本应用 | |
sourceRef | string | ||
payToken | string | ||
codeUrl | string | 扫码支付的链接 | |
payUrl | string | 渠道的付款链接 | |
appId | string | ||
channelTradeNo | string | ||
expiresAt | string(date-time) | 是 | |
paidAt | string(date-time) | ||
closedAt | string(date-time) | ||
refundedCents | integer | 是 | 已退多少 |
createdBy | string | ||
createdAt | string(date-time) | 是 | |
settledAt | string(date-time) | ||
settleAttempts | integer | ||
lastError | string | ||
link | string | 客户的付款页 | |
payParams | string | JSAPI 交易交给微信的已签名参数(JSON 文本) |
示例:
{
"id": "po_01HZZ",
"channel": "wechat",
"product": "native",
"outTradeNo": "po_01HZZ",
"amountCents": 9900,
"currency": "CNY",
"subject": "会员年费",
"status": "pending",
"sourceApp": "crm",
"sourceRef": "k3://members/member/m_42",
"expiresAt": "2026-10-31T09:00:00Z",
"refundedCents": 0,
"createdAt": "2026-10-31T08:30:00Z",
"settleAttempts": 0,
"link": "https://pay.example.com/p/abc123"
}GET /pay/orders/{id}/refunds
列出一张收款单的退款
需要范围 app.pay:read。English: the refunds of an order.
返回 {items}。
- 认证:
bearer - 范围:
app.pay:read - operationId:
listPayRefunds
参数
| 名称 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
id | path | string | 是 | 收款单 id |
响应
| 状态 | 说明 |
|---|---|
| 200 | 退款 |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 404 | not_found:对应的记录不存在(客户中心没有这个客户,访客、服务或所指的东西不存在)。见 NotFound |
| 422 | 字段或参数不被接受(正文读不出来、有未知字段、缺必填、取值越界)。见 Unprocessable |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
200 响应正文(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
items | PayRefund[] | 是 | |
items[].tenant | string | ||
items[].id | string | 是 | |
items[].orderId | string | 是 | |
items[].outRefundNo | string | ||
items[].amountCents | integer | 是 | |
items[].reason | string | ||
items[].status | string | 是 | |
items[].channelRefundId | string | ||
items[].createdBy | string | ||
items[].createdAt | string(date-time) | 是 | |
items[].settledAt | string(date-time) | ||
items[].settleAttempts | integer | ||
items[].lastError | string |
POST /pay/orders/{id}/refunds
给一张已付的收款单退款
需要范围 app.pay:write。English: refunds a paid order, in part or what is left.
amountCents 为 0 或省略是退剩下的全部。key 是这笔退款的幂等键,没写时用请求头 Idempotency-Key,都没有是 422。返回 201 和退款。
- 认证:
bearer - 范围:
app.pay:write - operationId:
refundPayOrder
参数
| 名称 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
id | path | string | 是 | 收款单 id |
Idempotency-Key | header | string | 每个 POST 都收。SDK 未传入时会生成 uuid v4。24 小时内同键同正文重放第一次的回答 最短 1,最长 255 |
请求正文(必填)(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
amountCents | integer | 退多少,整数分 | |
reason | string | 退款原因 | |
key | string | 幂等键;省略时用请求头 Idempotency-Key |
示例:
{
"amountCents": 3000,
"reason": "部分退款",
"key": "refund-o_1-1"
}响应
| 状态 | 说明 |
|---|---|
| 201 | 退款 |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 404 | not_found:对应的记录不存在(客户中心没有这个客户,访客、服务或所指的东西不存在)。见 NotFound |
| 409 | 见 Conflict |
| 413 | payload_too_large:正文太大。见 PayloadTooLarge |
| 422 | 字段或参数不被接受(正文读不出来、有未知字段、缺必填、取值越界)。见 Unprocessable |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
201 响应正文(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
tenant | string | ||
id | string | 是 | |
orderId | string | 是 | |
outRefundNo | string | ||
amountCents | integer | 是 | |
reason | string | ||
status | string | 是 | |
channelRefundId | string | ||
createdBy | string | ||
createdAt | string(date-time) | 是 | |
settledAt | string(date-time) | ||
settleAttempts | integer | ||
lastError | string |
示例:
{
"id": "rf_01HZZ",
"orderId": "po_01HZZ",
"amountCents": 3000,
"reason": "部分退款",
"status": "processing",
"createdAt": "2026-10-31T10:00:00Z"
}approvals
审批:为本应用的对象提交、重新提交、撤回审批,读进度,处理当前人员的待办
GET /approvals
读取一个对象最近的审批
需要范围 app.approvals:read。English: the latest approval of an object of the app, for its requester or someone asked to decide, or for the app itself.
审批是人的:除 GET /approvals/participates、GET /approvals 与 POST /approvals/{id}/withdraw 外只收页面会话,应用自己的令牌是 403 forbidden;应用自己的令牌可以读取本应用任何对象的审批(不含个人的待办)、撤回本应用的任何审批(谁可以由应用判断)。subject 是对象的引用。别人的审批、或没有审批,是 404 not_found。
- 认证:
bearer - 范围:
app.approvals:read - operationId:
getApproval
参数
| 名称 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
subject | query | string | 是 | 对象的引用 |
响应
| 状态 | 说明 |
|---|---|
| 200 | 审批 |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 404 | not_found:对应的记录不存在(客户中心没有这个客户,访客、服务或所指的东西不存在)。见 NotFound |
| 422 | 字段或参数不被接受(正文读不出来、有未知字段、缺必填、取值越界)。见 Unprocessable |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
200 响应正文(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
id | string | 是 | |
kind | string | 是 | |
subject | string | 是 | |
number | string | 是 | |
title | string | 是 | |
status | string | 是 | running、returned、approved、rejected、withdrawn、terminated、error |
requester | string | 是 | |
lines | ApprovalLine[] | 是 | |
lines[].label | string | 是 | |
lines[].text | string | 是 | |
waiting | string[] | 是 | 在等谁,例如“直属上级:鲍勃” |
mine | ApprovalTask[] | 是 | 调用者自己待办的任务 |
mine[].id | string | 是 | |
mine[].node | string | 是 | |
mine[].name | string | 是 | |
mine[].version | integer | 是 | 处理时要带回的版本 |
mine[].actions | string[] | 是 | 能做的动作 |
mine[].needComment | string[] | 必须写意见的动作 | |
steps | ApprovalStep[] | 是 | |
steps[].kind | string | 是 | |
steps[].node | string | ||
steps[].actor | string | ||
steps[].name | string | ||
steps[].comment | string | ||
steps[].at | string(date-time) | 是 | |
canWithdraw | boolean | 是 | |
link | string | 是 | 审批应用里这条审批的页面 |
settle | string | 把结果告诉第三方应用的进展:pending、done、failed;没有要告诉的则省略 | |
settleNote | string |
示例:
{
"id": "ap_01J",
"kind": "hr.leave",
"subject": "k3://hr/leave/l_17",
"number": "QJ-2026-0042",
"title": "王芳请假 2 天",
"status": "running",
"requester": "u_1001",
"lines": [
{
"label": "日期",
"text": "11-03 至 11-04"
}
],
"waiting": [
"直属上级:鲍勃"
],
"mine": [],
"steps": [],
"canWithdraw": true,
"link": "/instances/ap_01J"
}POST /approvals
为本应用的一个对象提交审批
需要范围 app.approvals:write。English: asks for the approval of one object of the app, as the person using it.
审批是人的:除 GET /approvals/participates、GET /approvals 与 POST /approvals/{id}/withdraw 外只收页面会话,应用自己的令牌是 403 forbidden;应用自己的令牌可以读取本应用任何对象的审批(不含个人的待办)、撤回本应用的任何审批(谁可以由应用判断)。kind 是本应用在清单 approvals 里声明的审批种类,subject 是对象的引用。事实和摘要不由人的令牌给:平台向应用发签名的 PREPARE 调用,由应用的回答决定;结果以签名的 DECIDED 事件送回应用。同一对象已有没结束的审批是 409 conflict;应用拒绝(对象不存在、状态不对)是 409 或 422,话是给人看的。返回 201 和审批的引用。
- 认证:
bearer - 范围:
app.approvals:write - operationId:
submitApproval
参数
| 名称 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
Idempotency-Key | header | string | 每个 POST 都收。SDK 未传入时会生成 uuid v4。24 小时内同键同正文重放第一次的回答 最短 1,最长 255 |
请求正文(必填)(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
kind | string | 是 | 本应用在清单 approvals 里声明的审批种类 |
subject | string | 是 | 对象的引用,在这个种类声明的前缀之下 |
示例:
{
"kind": "hr.leave",
"subject": "k3://hr/leave/l_17"
}响应
| 状态 | 说明 |
|---|---|
| 201 | 审批的引用 |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 404 | not_found:对应的记录不存在(客户中心没有这个客户,访客、服务或所指的东西不存在)。见 NotFound |
| 409 | 见 Conflict |
| 413 | payload_too_large:正文太大。见 PayloadTooLarge |
| 422 | 字段或参数不被接受(正文读不出来、有未知字段、缺必填、取值越界)。见 Unprocessable |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
201 响应正文(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
id | string | 是 | |
number | string | 是 | 审批单号 |
status | string | 是 | running、returned、approved、rejected、withdrawn、terminated、error |
示例:
{
"id": "ap_01J",
"number": "QJ-2026-0042",
"status": "running"
}POST /approvals/{id}/resubmit
重新提交一个被退回的审批
需要范围 app.approvals:write。English: submits a returned approval again.
审批是人的:除 GET /approvals/participates、GET /approvals 与 POST /approvals/{id}/withdraw 外只收页面会话,应用自己的令牌是 403 forbidden;应用自己的令牌可以读取本应用任何对象的审批(不含个人的待办)、撤回本应用的任何审批(谁可以由应用判断)。正文同提交。返回审批的引用。
- 认证:
bearer - 范围:
app.approvals:write - operationId:
resubmitApproval
参数
| 名称 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
id | path | string | 是 | 审批 id |
Idempotency-Key | header | string | 每个 POST 都收。SDK 未传入时会生成 uuid v4。24 小时内同键同正文重放第一次的回答 最短 1,最长 255 |
请求正文(必填)(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
kind | string | 是 | 本应用在清单 approvals 里声明的审批种类 |
subject | string | 是 | 对象的引用,在这个种类声明的前缀之下 |
示例:
{
"kind": "hr.leave",
"subject": "k3://hr/leave/l_17"
}响应
| 状态 | 说明 |
|---|---|
| 200 | 审批的引用 |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 404 | not_found:对应的记录不存在(客户中心没有这个客户,访客、服务或所指的东西不存在)。见 NotFound |
| 409 | 见 Conflict |
| 413 | payload_too_large:正文太大。见 PayloadTooLarge |
| 422 | 字段或参数不被接受(正文读不出来、有未知字段、缺必填、取值越界)。见 Unprocessable |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
200 响应正文(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
id | string | 是 | |
number | string | 是 | 审批单号 |
status | string | 是 | running、returned、approved、rejected、withdrawn、terminated、error |
示例:
{
"id": "ap_01J",
"number": "QJ-2026-0042",
"status": "running"
}POST /approvals/{id}/withdraw
撤回自己提交的审批
需要范围 app.approvals:write。English: withdraws the person's own approval, or (the app's own token) any approval of the app's objects.
审批是人的:除 GET /approvals/participates、GET /approvals 与 POST /approvals/{id}/withdraw 外只收页面会话,应用自己的令牌是 403 forbidden;应用自己的令牌可以读取本应用任何对象的审批(不含个人的待办)、撤回本应用的任何审批(谁可以由应用判断)。reason 是撤回的原因,可省略。返回审批的引用。
- 认证:
bearer - 范围:
app.approvals:write - operationId:
withdrawApproval
参数
| 名称 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
id | path | string | 是 | 审批 id |
Idempotency-Key | header | string | 每个 POST 都收。SDK 未传入时会生成 uuid v4。24 小时内同键同正文重放第一次的回答 最短 1,最长 255 |
请求正文(必填)(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
reason | string | 撤回的原因 |
示例:
{
"reason": "日期填错了"
}响应
| 状态 | 说明 |
|---|---|
| 200 | 审批的引用 |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 404 | not_found:对应的记录不存在(客户中心没有这个客户,访客、服务或所指的东西不存在)。见 NotFound |
| 409 | 见 Conflict |
| 413 | payload_too_large:正文太大。见 PayloadTooLarge |
| 422 | 字段或参数不被接受(正文读不出来、有未知字段、缺必填、取值越界)。见 Unprocessable |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
200 响应正文(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
id | string | 是 | |
number | string | 是 | 审批单号 |
status | string | 是 | running、returned、approved、rejected、withdrawn、terminated、error |
示例:
{
"id": "ap_01J",
"number": "QJ-2026-0042",
"status": "running"
}GET /approvals/waiting
列出当前人员本应用的审批待办
需要范围 app.approvals:read。English: the tasks waiting for the person in the app's approvals.
审批是人的:除 GET /approvals/participates、GET /approvals 与 POST /approvals/{id}/withdraw 外只收页面会话,应用自己的令牌是 403 forbidden;应用自己的令牌可以读取本应用任何对象的审批(不含个人的待办)、撤回本应用的任何审批(谁可以由应用判断)。kind 只要这一种审批的待办。最多 100 条。返回 {items}。
- 认证:
bearer - 范围:
app.approvals:read - operationId:
listWaitingApprovals
参数
| 名称 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
kind | query | string | 审批种类,例如 hr.leave |
响应
| 状态 | 说明 |
|---|---|
| 200 | 待办 |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 422 | 字段或参数不被接受(正文读不出来、有未知字段、缺必填、取值越界)。见 Unprocessable |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
200 响应正文(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
items | ApprovalWaiting[] | 是 | |
items[].approval | string | 是 | 审批 id |
items[].task | ApprovalTask | 是 | 一条待办,以及能对它做什么 |
items[].task.id | string | 是 | |
items[].task.node | string | 是 | |
items[].task.name | string | 是 | |
items[].task.version | integer | 是 | 处理时要带回的版本 |
items[].task.actions | string[] | 是 | 能做的动作 |
items[].task.needComment | string[] | 必须写意见的动作 | |
items[].subject | string | 是 | |
items[].title | string | 是 | |
items[].lines | ApprovalLine[] | 是 | |
items[].lines[].label | string | 是 | |
items[].lines[].text | string | 是 | |
items[].since | string(date-time) | 是 |
POST /approvals/tasks/{task}/actions
处理一条审批待办
需要范围 app.approvals:write。English: decides a task of the person's.
审批是人的:除 GET /approvals/participates、GET /approvals 与 POST /approvals/{id}/withdraw 外只收页面会话,应用自己的令牌是 403 forbidden;应用自己的令牌可以读取本应用任何对象的审批(不含个人的待办)、撤回本应用的任何审批(谁可以由应用判断)。action 是 approve、reject、return、transfer、presign、aftersign、cosign 之一;version 是人看到的待办版本,过期是 409 conflict;转交和加签用 target 或 users。返回处理后的审批。
- 认证:
bearer - 范围:
app.approvals:write - operationId:
actOnApprovalTask
参数
| 名称 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
task | path | string | 是 | 待办 id |
Idempotency-Key | header | string | 每个 POST 都收。SDK 未传入时会生成 uuid v4。24 小时内同键同正文重放第一次的回答 最短 1,最长 255 |
请求正文(必填)(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
action | string | 是 | 可选值:approve、reject、return、transfer、presign、aftersign、cosign |
version | integer | 是 | 人看到的待办版本 |
comment | string | ||
target | string | 退回到哪个节点,或转交给谁 | |
users | string[] | 加签的人 |
示例:
{
"action": "approve",
"version": 3,
"comment": "同意"
}响应
| 状态 | 说明 |
|---|---|
| 200 | 处理后的审批 |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 404 | not_found:对应的记录不存在(客户中心没有这个客户,访客、服务或所指的东西不存在)。见 NotFound |
| 409 | 见 Conflict |
| 413 | payload_too_large:正文太大。见 PayloadTooLarge |
| 422 | 字段或参数不被接受(正文读不出来、有未知字段、缺必填、取值越界)。见 Unprocessable |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
200 响应正文(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
id | string | 是 | |
kind | string | 是 | |
subject | string | 是 | |
number | string | 是 | |
title | string | 是 | |
status | string | 是 | running、returned、approved、rejected、withdrawn、terminated、error |
requester | string | 是 | |
lines | ApprovalLine[] | 是 | |
lines[].label | string | 是 | |
lines[].text | string | 是 | |
waiting | string[] | 是 | 在等谁,例如“直属上级:鲍勃” |
mine | ApprovalTask[] | 是 | 调用者自己待办的任务 |
mine[].id | string | 是 | |
mine[].node | string | 是 | |
mine[].name | string | 是 | |
mine[].version | integer | 是 | 处理时要带回的版本 |
mine[].actions | string[] | 是 | 能做的动作 |
mine[].needComment | string[] | 必须写意见的动作 | |
steps | ApprovalStep[] | 是 | |
steps[].kind | string | 是 | |
steps[].node | string | ||
steps[].actor | string | ||
steps[].name | string | ||
steps[].comment | string | ||
steps[].at | string(date-time) | 是 | |
canWithdraw | boolean | 是 | |
link | string | 是 | 审批应用里这条审批的页面 |
settle | string | 把结果告诉第三方应用的进展:pending、done、failed;没有要告诉的则省略 | |
settleNote | string |
示例:
{
"id": "ap_01J",
"kind": "hr.leave",
"subject": "k3://hr/leave/l_17",
"number": "QJ-2026-0042",
"title": "王芳请假 2 天",
"status": "running",
"requester": "u_1001",
"lines": [
{
"label": "日期",
"text": "11-03 至 11-04"
}
],
"waiting": [
"直属上级:鲍勃"
],
"mine": [],
"steps": [],
"canWithdraw": true,
"link": "/instances/ap_01J"
}GET /approvals/participates
问某人是否参与一个对象的审批
需要范围 app.approvals:read。English: whether user takes part in the approval of subject (what lets the app show the object to them).
这一个操作应用自己的令牌也能调。返回 {participates}。
- 认证:
bearer - 范围:
app.approvals:read - operationId:
approvalParticipates
参数
| 名称 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
subject | query | string | 是 | 对象的引用 |
user | query | string | 是 | 用户 id |
响应
| 状态 | 说明 |
|---|---|
| 200 | 是否参与 |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 422 | 字段或参数不被接受(正文读不出来、有未知字段、缺必填、取值越界)。见 Unprocessable |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
200 响应正文(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
participates | boolean | 是 |
示例:
{
"participates": true
}calendar
日历:把本应用的日程(课节、面试、预订)放到相关人员的日历上
POST /calendar/projections
把本应用的一条日程放到相关人员的日历上,或取消它
需要范围 app.calendar:write。English: puts one fact of the app (a session, an interview, a booked room) on the people's calendars as a projection, or cancels it.
每个应用的每个 ref 只有一条投影。item 是投影;省略或为 null 表示取消。version 是这次推送的版本,必须是正数,用来排序:比已应用的更旧的推送回答 stale,什么也不改。回答 result 是日历条目的 id,或 stale。
- 认证:
bearer - 范围:
app.calendar:write - operationId:
pushCalendarProjection
参数
| 名称 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
Idempotency-Key | header | string | 每个 POST 都收。SDK 未传入时会生成 uuid v4。24 小时内同键同正文重放第一次的回答 最短 1,最长 255 |
请求正文(必填)(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
ref | string | 是 | 事实的 k3:// 引用 |
version | integer | 是 | 这次推送的版本,正数。比已应用的旧就是 stale 最小 1 |
item | CalendarProjection | 本应用的一条日程在日历上的样子 | |
item.ref | string | 是 | 事实的 k3:// 引用,k3://{应用}/{类型}/{id} |
item.route | string | 在本应用里打开它的路由 | |
item.owner | string | 是 | 这条日程属于的人(用户 id) |
item.attendees | string[] | 其他参与的人 | |
item.start | string(date-time) | 是 | |
item.end | string(date-time) | 是 | |
item.tz | string | 时区 | |
item.allDay | boolean | ||
item.title | string | 是 | 中文标题 |
item.titleEn | string | 英文标题 | |
item.place | string | ||
item.detail | string | 只有这条日程自己的人能读的内容 | |
item.privacy | string | 隐私等级。省略是 normal 可选值: normal、private、health | |
item.state | string | 应用自己的状态词,显示在条目旁 |
示例:
{
"ref": "k3://rehab/session/s_7",
"version": 1,
"item": {
"ref": "k3://rehab/session/s_7",
"route": "/sessions/s_7",
"owner": "u_2001",
"attendees": [
"u_3002"
],
"start": "2026-11-03T02:00:00Z",
"end": "2026-11-03T03:00:00Z",
"tz": "Asia/Shanghai",
"title": "康复课 · 术后康复",
"titleEn": "Rehab session · Post-op",
"place": "3 号诊室",
"privacy": "health",
"state": "booked"
}
}响应
| 状态 | 说明 |
|---|---|
| 200 | 推送的结果 |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 413 | payload_too_large:正文太大。见 PayloadTooLarge |
| 422 | 字段或参数不被接受(正文读不出来、有未知字段、缺必填、取值越界)。见 Unprocessable |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
200 响应正文(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
result | string | 是 | 日历条目的 id,或 stale(已应用过更新的推送) |
示例:
{
"result": "cal_01K"
}imports
历史导入:登记本应用导入的批次,并记下每条记录的来源
POST /imports/{batch}/items
登记本应用导入的一段历史数据(批次、每一行的结果、记录的来源)
需要范围 app.imports:write。English: records one chunk of a history import the app ran in its own process: the batch, what became of each row, and the provenance of each record a row wrote.
应用用自己的命令、在自己的数据库里按业务时刻写入旧系统的历史(ADR-0081),每写完一段就把结果报到这里。平台把批次与行记在跨应用的批次列表里(管理后台的「导入批次」),给每条写成的记录记一条来源(via 为 import,记录的「来源」与 GET /provenance 读到),每段写一条审计。平台不收行的数据:digest 是应用对这一行原文的摘要,同一批里同一个外部键再报一次,摘要必须一样。
只收页面会话,且必须是企业管理员(tenant.admin)本人:应用自己的令牌是 403 person_required,其他人是 403。batch 只能用字母、数字和 . _ : -,最多 80 个字符。一次 1 到 500 行,外部键在一次提交里不能重复;ok 的行要有 recordId,ref 必须是本应用的记录(k3://{本应用 id}/…),failed 的行要有 error、不能有记录;不合规是 422,整段不收。已经记为 ok 的外部键再报成另一行(摘要不同,或报成 failed)是 409 conflict,整段不收。正文最多 1 MiB。回答是批次现在的样子。平台没有数据库时是 503。
- 认证:
bearer - 范围:
app.imports:write - operationId:
reportImportItems
参数
| 名称 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
Idempotency-Key | header | string | 每个 POST 都收。SDK 未传入时会生成 uuid v4。24 小时内同键同正文重放第一次的回答 最短 1,最长 255 | |
batch | path | string | 是 | 批号,导入方自定,在本应用内唯一 |
请求正文(必填)(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
label | string | 批次说明,最多 200 字;省略时保留原来的 | |
items | ImportReportItem[] | 是 | 最多 500 项 |
items[].key | string | 是 | 旧系统里这一行的键,批内唯一,最多 120 字符 |
items[].kind | string | 是 | 这一行是什么(应用自己的种类) |
items[].status | string | 是 | 写成了,或失败了 可选值: ok、failed |
items[].recordId | string | ok:这一行写成的主记录 id | |
items[].ref | string | ok:主记录的 k3:// 引用(本应用的);有它就记一条来源 | |
items[].businessAt | string(date-time) | 是 | 业务时刻:这件事发生的时间 |
items[].digest | string | 是 | 应用对这一行原文的摘要(同一行再报时必须一样),最多 128 字符 |
items[].error | string | failed:原因,导入的人读的,最多 500 字 |
示例:
{
"label": "旧系统会员 2019–2025",
"items": [
{
"key": "m-1001",
"kind": "member",
"status": "ok",
"recordId": "mem_01K",
"ref": "k3://membership/member/mem_01K",
"businessAt": "2019-04-02T08:00:00Z",
"digest": "9f2c…"
},
{
"key": "m-1002",
"kind": "member",
"status": "failed",
"businessAt": "2019-04-03T08:00:00Z",
"digest": "1a7e…",
"error": "手机号不对"
}
]
}响应
| 状态 | 说明 |
|---|---|
| 200 | 批次现在的样子 |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 409 | 见 Conflict |
| 413 | payload_too_large:正文太大。见 PayloadTooLarge |
| 422 | 字段或参数不被接受(正文读不出来、有未知字段、缺必填、取值越界)。见 Unprocessable |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
200 响应正文(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
app | string | 是 | |
id | string | 是 | |
label | string | 是 | |
createdBy | string | 是 | 建这个批次的人 |
createdName | string | 是 | |
createdAt | string(date-time) | 是 | |
updatedAt | string(date-time) | 是 | |
rowsOk | integer | 是 | |
rowsFailed | integer | 是 | |
firstAt | string(date-time) | 写成的行里最早的业务时刻 | |
lastAt | string(date-time) | 写成的行里最晚的业务时刻 |
peers
其他应用的服务经平台去问:核销台、收银台、资源占用(治疗室与设备)、推广码;平台按已安装并开启的清单选提供者,本应用不指名也碰不到它
GET /peers/desk
其他应用的核销台:有没有,以及当前人员能做什么
需要范围 app.desk:use。English: whether an installed app serves the redemption desk, and what the caller may do there.
另一个应用的核销台,经平台去问:平台按这个组织已安装并开启的应用的清单选出提供它的应用,请求的应用不指名也碰不到它。available 说明有没有应用提供核销台;redeem、void 是当前人员能不能核销、作废。应用自己的调用(没有人在背后)这两项永远是 false。
- 认证:
bearer - 范围:
app.desk:use - operationId:
getPeerDesk
响应
| 状态 | 说明 |
|---|---|
| 200 | 核销台的情况 |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
200 响应正文(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
available | boolean | 是 | 有应用提供核销台 |
redeem | boolean | 是 | 当前人员能核销;应用自己的调用永远是 false |
void | boolean | 是 | 当前人员能作废;应用自己的调用永远是 false |
POST /peers/desk/http
把本应用页面的一个请求交给其他应用的核销台,以当前人员的身份
需要范围 app.desk:use。English: hands a request of the app's page (its /api/desk/… path, GET or POST, JSON body) to the redemption desk, as the page session's person.
另一个应用的核销台,经平台去问(平台按已安装并开启的清单选提供者,请求的应用不指名也碰不到它)。method 是 GET 或 POST,path 必须以 /api/desk/ 开头,query 是查询串,body 是 JSON。只有页面会话(页面上的人)可以;应用自己的调用是 403 person_required。没有应用提供核销台是 404 no_provider。回答是提供者的回答原样:status、contentType、body(字节,JSON 里是 base64);提供者回的错误在 status 里,这个接口本身仍是 200。正文最多 1 MiB。
- 认证:
bearer - 范围:
app.desk:use - operationId:
peerDeskHttp
参数
| 名称 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
Idempotency-Key | header | string | 每个 POST 都收。SDK 未传入时会生成 uuid v4。24 小时内同键同正文重放第一次的回答 最短 1,最长 255 |
请求正文(必填)(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
method | string | 是 | GET 或 POST 可选值: GET、POST |
path | string | 是 | 提供者自己的路径:核销台以 /api/desk/ 开头,收银台以 /api/till/ 开头;不能含 ..、?、#、反斜杠 |
query | string | 查询串(不含 ?) | |
body | any | JSON 正文,可省略 |
响应
| 状态 | 说明 |
|---|---|
| 200 | 提供者的回答 |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 404 | not_found:对应的记录不存在(客户中心没有这个客户,访客、服务或所指的东西不存在)。见 NotFound |
| 413 | payload_too_large:正文太大。见 PayloadTooLarge |
| 422 | 字段或参数不被接受(正文读不出来、有未知字段、缺必填、取值越界)。见 Unprocessable |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
200 响应正文(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
status | integer | 是 | 提供者回答的 HTTP 状态 |
contentType | string | 提供者回答的 Content-Type | |
body | string(byte) | 提供者回答的字节(base64) |
GET /peers/till
其他应用的收银台:有没有,以及当前人员能不能收银
需要范围 app.till:use。English: whether an installed app serves the till, and whether the caller may sell there.
另一个应用的收银台,经平台去问:平台按这个组织已安装并开启的应用的清单选出提供它的应用,请求的应用不指名也碰不到它。available 说明有没有应用提供收银台;sell 是当前人员能不能在那里收银。应用自己的调用(没有人在背后)sell 永远是 false。
- 认证:
bearer - 范围:
app.till:use - operationId:
getPeerTill
响应
| 状态 | 说明 |
|---|---|
| 200 | 收银台的情况 |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
200 响应正文(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
available | boolean | 是 | 有应用提供收银台 |
sell | boolean | 是 | 当前人员能收银;应用自己的调用永远是 false |
POST /peers/till/http
把本应用页面的一个请求交给其他应用的收银台,以当前人员的身份
需要范围 app.till:use。English: hands a request of the app's page (its /api/till/… path, GET or POST, JSON body) to the till, as the page session's person.
另一个应用的收银台,经平台去问(平台按已安装并开启的清单选提供者,请求的应用不指名也碰不到它)。method 是 GET 或 POST,path 必须以 /api/till/ 开头,query 是查询串,body 是 JSON。只有页面会话(页面上的人)可以;应用自己的调用是 403 person_required。没有应用提供收银台是 404 no_provider。回答是提供者的回答原样:status、contentType、body(字节,JSON 里是 base64);提供者回的错误在 status 里,这个接口本身仍是 200。正文最多 1 MiB。
- 认证:
bearer - 范围:
app.till:use - operationId:
peerTillHttp
参数
| 名称 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
Idempotency-Key | header | string | 每个 POST 都收。SDK 未传入时会生成 uuid v4。24 小时内同键同正文重放第一次的回答 最短 1,最长 255 |
请求正文(必填)(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
method | string | 是 | GET 或 POST 可选值: GET、POST |
path | string | 是 | 提供者自己的路径:核销台以 /api/desk/ 开头,收银台以 /api/till/ 开头;不能含 ..、?、#、反斜杠 |
query | string | 查询串(不含 ?) | |
body | any | JSON 正文,可省略 |
响应
| 状态 | 说明 |
|---|---|
| 200 | 提供者的回答 |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 404 | not_found:对应的记录不存在(客户中心没有这个客户,访客、服务或所指的东西不存在)。见 NotFound |
| 413 | payload_too_large:正文太大。见 PayloadTooLarge |
| 422 | 字段或参数不被接受(正文读不出来、有未知字段、缺必填、取值越界)。见 Unprocessable |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
200 响应正文(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
status | integer | 是 | 提供者回答的 HTTP 状态 |
contentType | string | 提供者回答的 Content-Type | |
body | string(byte) | 提供者回答的字节(base64) |
GET /peers/holds
其他应用有没有提供资源占用(治疗室、设备)
需要范围 app.holds:read。English: whether an installed app offers resource holds.
另一个应用的资源占用,经平台去问:平台按这个组织已安装并开启的应用的清单选出提供者,请求的应用不指名也碰不到它。available 为 false 时,其余占用接口都是 404 no_provider,调用方可以不占资源直接预约。
- 认证:
bearer - 范围:
app.holds:read - operationId:
getPeerHolds
响应
| 状态 | 说明 |
|---|---|
| 200 | 有没有 |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
200 响应正文(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
available | boolean | 是 | 有应用提供 |
GET /peers/holds/holdable
可占用的治疗室和设备
需要范围 app.holds:read。English: the items another app may hold, as the caller sees them.
另一个应用的资源占用,经平台去问(提供者由平台按清单选,请求的应用不指名也碰不到它)。没有应用提供资源占用是 404 no_provider。
- 认证:
bearer - 范围:
app.holds:read - operationId:
listPeerHoldable
响应
| 状态 | 说明 |
|---|---|
| 200 | 可占用的项目 |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 404 | not_found:对应的记录不存在(客户中心没有这个客户,访客、服务或所指的东西不存在)。见 NotFound |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
200 响应正文(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
items | PeerHoldableItem[] | 是 | |
items[].id | string | 是 | 项目 id |
items[].name | string | 是 | 名称 |
items[].kind | string | 是 | 类别的种类词:room、device … |
items[].category | string | 是 | 类别名称 |
items[].location | string | 位置 |
POST /peers/holds/free
查一段时间里这些项目空不空
需要范围 app.holds:read。English: says, per item, whether it is free in [from, to), not counting the holds of except.
另一个应用的资源占用,经平台去问(提供者由平台按清单选,请求的应用不指名也碰不到它)。except 是正在改期的来源,它自己的占用不算。没有应用提供资源占用是 404 no_provider。这是读操作,什么也不占。
- 认证:
bearer - 范围:
app.holds:read - operationId:
checkPeerHoldsFree
参数
| 名称 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
Idempotency-Key | header | string | 每个 POST 都收。SDK 未传入时会生成 uuid v4。24 小时内同键同正文重放第一次的回答 最短 1,最长 255 |
请求正文(必填)(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
items | string[] | 是 | 要查的项目 id |
from | string(date-time) | 是 | 开始 |
to | string(date-time) | 是 | 结束(不含) |
except | string | 正在改期的来源(k3:// 引用),它自己的占用不算 |
响应
| 状态 | 说明 |
|---|---|
| 200 | 每个项目的空闲情况 |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 404 | not_found:对应的记录不存在(客户中心没有这个客户,访客、服务或所指的东西不存在)。见 NotFound |
| 422 | 字段或参数不被接受(正文读不出来、有未知字段、缺必填、取值越界)。见 Unprocessable |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
200 响应正文(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
items | PeerFreeItem[] | 是 | |
items[].item | string | 是 | 项目 id |
items[].name | string | 是 | 名称 |
items[].free | boolean | 是 | 这段时间是否空闲 |
items[].conflict | string | 被什么占着(可读的标题) |
POST /peers/holds/hold
为本应用的一个对象占用这些项目
需要范围 app.holds:write。English: holds every free item for one object of the calling app; a taken item comes back with conflict and no hold.
另一个应用的资源占用,经平台去问(提供者由平台按清单选,请求的应用不指名也碰不到它)。source 必须是本应用自己的 k3:// 引用(k3://{应用}/…),否则 422;资源应用在收回占用时据此告诉本应用。被占着的项目在回答里带 conflict,没有 holdId。没有应用提供资源占用是 404 no_provider。
- 认证:
bearer - 范围:
app.holds:write - operationId:
createPeerHold
参数
| 名称 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
Idempotency-Key | header | string | 每个 POST 都收。SDK 未传入时会生成 uuid v4。24 小时内同键同正文重放第一次的回答 最短 1,最长 255 |
请求正文(必填)(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
source | string | 是 | 本应用自己的 k3:// 引用(k3://{应用}/…),否则 422 |
title | string | 占用的标题(别的人看到占用时读到的) | |
items | string[] | 是 | 要占用的项目 id |
from | string(date-time) | 是 | 开始 |
to | string(date-time) | 是 | 结束(不含) |
响应
| 状态 | 说明 |
|---|---|
| 200 | 每个项目的占用结果 |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 404 | not_found:对应的记录不存在(客户中心没有这个客户,访客、服务或所指的东西不存在)。见 NotFound |
| 422 | 字段或参数不被接受(正文读不出来、有未知字段、缺必填、取值越界)。见 Unprocessable |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
200 响应正文(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
items | PeerHoldResult[] | 是 | |
items[].item | string | 是 | 项目 id |
items[].holdId | string | 占用的 id;被占着的项目没有 | |
items[].conflict | string | 被什么占着(可读的标题);有它就没有 holdId |
POST /peers/holds/move
改一个占用的时间
需要范围 app.holds:write。English: moves a hold to [from, to).
另一个应用的资源占用,经平台去问(提供者由平台按清单选,请求的应用不指名也碰不到它)。holdId 必填。新的时间里项目已被占是 409 hold_conflict;没有应用提供资源占用是 404 no_provider。
- 认证:
bearer - 范围:
app.holds:write - operationId:
movePeerHold
参数
| 名称 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
Idempotency-Key | header | string | 每个 POST 都收。SDK 未传入时会生成 uuid v4。24 小时内同键同正文重放第一次的回答 最短 1,最长 255 |
请求正文(必填)(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
holdId | string | 是 | 占用的 id |
from | string(date-time) | 是 | 新的开始 |
to | string(date-time) | 是 | 新的结束(不含) |
响应
| 状态 | 说明 |
|---|---|
| 204 | 已改。没有正文 |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 404 | not_found:对应的记录不存在(客户中心没有这个客户,访客、服务或所指的东西不存在)。见 NotFound |
| 409 | 见 Conflict |
| 422 | 字段或参数不被接受(正文读不出来、有未知字段、缺必填、取值越界)。见 Unprocessable |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
POST /peers/holds/release
放掉一个占用
需要范围 app.holds:write。English: gives a hold back.
另一个应用的资源占用,经平台去问(提供者由平台按清单选,请求的应用不指名也碰不到它)。holdId 必填,reason 是放掉的原因。没有应用提供资源占用是 404 no_provider。
- 认证:
bearer - 范围:
app.holds:write - operationId:
releasePeerHold
参数
| 名称 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
Idempotency-Key | header | string | 每个 POST 都收。SDK 未传入时会生成 uuid v4。24 小时内同键同正文重放第一次的回答 最短 1,最长 255 |
请求正文(必填)(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
holdId | string | 是 | 占用的 id |
reason | string | 放掉的原因 |
响应
| 状态 | 说明 |
|---|---|
| 204 | 已放掉。没有正文 |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 404 | not_found:对应的记录不存在(客户中心没有这个客户,访客、服务或所指的东西不存在)。见 NotFound |
| 422 | 字段或参数不被接受(正文读不出来、有未知字段、缺必填、取值越界)。见 Unprocessable |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
GET /peers/referral-codes
其他应用有没有提供推广码
需要范围 app.referrals:read。English: whether an installed app offers promotion codes.
另一个应用的推广码,经平台去问:平台按这个组织已安装并开启的应用的清单选出提供者,请求的应用不指名也碰不到它。available 为 false 时,其余推广码接口都是 404 no_provider。
- 认证:
bearer - 范围:
app.referrals:read - operationId:
getPeerReferralCodes
响应
| 状态 | 说明 |
|---|---|
| 200 | 有没有 |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
200 响应正文(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
available | boolean | 是 | 有应用提供 |
POST /peers/referral-codes/code
一位推广人的推广码、链接和海报
需要范围 app.referrals:read。English: the promoter's code, link and posters.
另一个应用的推广码,经平台去问(提供者由平台按清单选,请求的应用不指名也碰不到它)。promoter 必须写 customer 或 user 之一,否则 422;origin(https://host)是链接指向的企业站点。对方说不是推广人时是 404 not_found;没有应用提供推广码是 404 no_provider。这是读操作。
- 认证:
bearer - 范围:
app.referrals:read - operationId:
getPeerReferralCode
参数
| 名称 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
Idempotency-Key | header | string | 每个 POST 都收。SDK 未传入时会生成 uuid v4。24 小时内同键同正文重放第一次的回答 最短 1,最长 255 |
请求正文(必填)(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
promoter | PeerPromoter | 是 | 推广人:客户或成员,二者写一个 |
promoter.customer | string | 客户 id(cu_…) | |
promoter.user | string | 成员 id | |
origin | string | 链接指向的企业站点(https://host) |
响应
| 状态 | 说明 |
|---|---|
| 200 | 推广码 |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 404 | not_found:对应的记录不存在(客户中心没有这个客户,访客、服务或所指的东西不存在)。见 NotFound |
| 422 | 字段或参数不被接受(正文读不出来、有未知字段、缺必填、取值越界)。见 Unprocessable |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
200 响应正文(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
code | string | 是 | 推广码 |
status | string | 是 | 状态 |
link | string | 是 | 推广链接 |
posters | PeerReferralPoster[] | 是 | |
posters[].id | string | 是 | |
posters[].name | string | 是 | |
posters[].headline | string | 是 | |
posters[].subline | string | 是 | |
posters[].theme | string | 是 | |
posters[].cta | string | 是 | |
posters[].link | string | 是 |
POST /peers/referral-codes/promoter
一个推广码属于哪位推广人
需要范围 app.referrals:read。English: who owns a code that is in use.
另一个应用的推广码,经平台去问(提供者由平台按清单选,请求的应用不指名也碰不到它)。code 必填。码不存在或现在不带来任何人是 404 not_found;没有应用提供推广码是 404 no_provider。这是读操作。
- 认证:
bearer - 范围:
app.referrals:read - operationId:
getPeerReferralPromoter
参数
| 名称 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
Idempotency-Key | header | string | 每个 POST 都收。SDK 未传入时会生成 uuid v4。24 小时内同键同正文重放第一次的回答 最短 1,最长 255 |
请求正文(必填)(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
code | string | 是 | 推广码 |
响应
| 状态 | 说明 |
|---|---|
| 200 | 推广人 |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 404 | not_found:对应的记录不存在(客户中心没有这个客户,访客、服务或所指的东西不存在)。见 NotFound |
| 422 | 字段或参数不被接受(正文读不出来、有未知字段、缺必填、取值越界)。见 Unprocessable |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
200 响应正文(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
customer | string | 客户 id(cu_…) | |
user | string | 成员 id |
deals
成交事件:本应用的成交、退款与作废交给平台,由平台投递给订阅者
POST /deals
把本应用的一笔成交、退款或作废告诉平台,由平台投递给订阅者
需要范围 app.deals:write。English: hands one deal event of the calling app (a sale, a refund, a void) to the platform, which queues it for the deal subscribers exactly as in process.
source.app 必须是调用的应用,否则 422。key 省略时按 来源应用:来源引用:种类 补上,写了就必须等于它;同一个事件(同一个 key)再来一次不会再排队。事件只带内部引用和标签,不带手机号、openid、邮箱、证件号等个人信息(看得出来的会被拒绝,422)。回答的 queued 是排给了几个订阅者(0 表示这个组织现在没有订阅者)。事件不是账:钱归经营记账。English: queued is how many subscribers the event was queued for.
- 认证:
bearer - 范围:
app.deals:write - operationId:
emitDeal
参数
| 名称 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
Idempotency-Key | header | string | 每个 POST 都收。SDK 未传入时会生成 uuid v4。24 小时内同键同正文重放第一次的回答 最短 1,最长 255 |
请求正文(必填)(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
key | string | 是 | 幂等键 |
kind | string | 是 | sale、refund 或 void |
source | DealSource | 是 | 成交从哪个应用来 |
source.app | string | 是 | 应用 id |
source.ref | string | 是 | k3:// 引用,退款指退款本身 |
customer | string | 客户 id;匿名为空 | |
amount_cents | integer | 是 | 折后实付;退款为退回的金额 |
currency | string | 空为租户的币种 | |
lines | DealLine[] | ||
lines[].sku | string | 是 | 商品 id(对平台不透明) |
lines[].name | string | 是 | 名称 |
lines[].qty | integer | 是 | 数量 |
lines[].amount_cents | integer | 是 | 金额 |
attribution | DealAttribution | 是 | 成交从哪里来(只有内部引用和标签,没有个人信息) |
attribution.channel | string | 渠道 | |
attribution.campaign | string | k3://campaign/<id> | |
attribution.site | string | 站点 | |
attribution.referrer | string | 分销者的客户 id | |
attribution.utm | map[string, string] | UTM | |
attribution.voucher | string | 用了哪张券 | |
reverses | string | 退款或作废所冲销的销售的 key | |
at | string(date-time) | 是 | 成交发生的业务时间 |
响应
| 状态 | 说明 |
|---|---|
| 200 | 事件的键,以及排给了几个订阅者 |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 422 | 字段或参数不被接受(正文读不出来、有未知字段、缺必填、取值越界)。见 Unprocessable |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
200 响应正文(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
key | string | 是 | 事件的键 |
queued | integer | 是 | 排给了几个订阅者;0 表示这个组织现在没有订阅者 |
org
GET /org/units
企业的部门
需要范围 app.directory:read。English: the tenant's departments, for an app's own pickers and sharing rules. 没有部门时 items 是 []。
- 认证:
bearer - 范围:
app.directory:read - operationId:
listOrgUnits
响应
| 状态 | 说明 |
|---|---|
| 200 | 企业的部门 |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
200 响应正文(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
items | OrgUnit[] | 是 | |
items[].id | string | 是 | |
items[].parentId | string | 上级部门;根部门省略 | |
items[].name | string | 是 | |
items[].path | string | 是 | 从根到它的名字路径 |
GET /org/roles
企业自己的角色
需要范围 app.directory:read。English: the tenant's own roles. 没有角色时 items 是 []。
- 认证:
bearer - 范围:
app.directory:read - operationId:
listOrgRoles
响应
| 状态 | 说明 |
|---|---|
| 200 | 企业自己的角色 |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
200 响应正文(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
items | OrgRole[] | 是 | |
items[].id | string | 是 | |
items[].name | string | 是 |
GET /org/placement
一个人所在的部门和被指派的角色
需要范围 app.directory:read。English: the department chain of a person and the ids of the tenant roles assigned to them.
units 先是这个人自己的部门,再是逐级向上的父部门,直到根;然后是他被任命的各部门及其上级。没有部门或角色时是 []。缺 user 是 422。
- 认证:
bearer - 范围:
app.directory:read - operationId:
getOrgPlacement
参数
| 名称 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
user | query | string | 是 | 人的 subject(成员的 userId) |
响应
| 状态 | 说明 |
|---|---|
| 200 | 部门链和角色 |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 422 | 字段或参数不被接受(正文读不出来、有未知字段、缺必填、取值越界)。见 Unprocessable |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
200 响应正文(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
units | string[] | 是 | 部门 id:先是自己的部门,再逐级向上;然后是任命的部门及其上级 |
roles | string[] | 是 | 被指派的角色 id |
GET /org/members
调用者数据范围内的成员及其部门与角色(分页)
需要范围 app.org:read。按 id 排序分页列出本企业的在职成员(不含机器账号、未激活和已停用的成员):id(账号 id)、name(显示名)、units(本人所属的部门和被任命的部门,不含上级)、roles(企业角色 id)。
人员按调用者的数据范围裁剪:point 必填,必须是本应用的权限点(以 app.{本应用 id}. 开头),否则 403 forbidden。平台按调用者在这个权限点上的数据范围回答:全部 → 本企业的全部成员;部门 → 所属或被任命的部门在范围内的成员;本人 → 调用者自己;调用者没有这个权限是 403 forbidden。组织没有启用权限模型(基础模式)时,企业管理员(tenant.admin)看到全部成员,其他人只看到自己。应用自己的调用(令牌背后没有人员)没有数据范围,拿不到成员列表:启用权限模型时是 403 forbidden,基础模式下是空列表(比 app.directory:read 的 /members 更严,有意如此)。next 是下一页的 cursor,最后一页是空字符串。limit 超出 1 到 500 是 422。平台没有接上权限求值、成员目录或组织架构时是 501 capability_off。English: the active members of the tenant (no machine accounts, no inactive or invited members), sorted by id and paged, cut to the caller's data scope on point, which must be one of this app's permissions (app.{app id}. prefix; another is 403 forbidden): all → every member; departments → members whose own or appointed department is in scope; self → the caller; no access → 403 forbidden. Basic mode (no permission model): a tenant administrator sees every member, anyone else only themselves. Each item has only id, name, units (own and appointed departments, no parents) and roles (tenant role ids). A limit outside 1 to 500 is 422; 501 capability_off when access, the directory or the organisation is not wired. The app's own call (no person behind the token) has no data scope and gets no member list: 403 forbidden with the permission model on, an empty list in basic mode (stricter than /members under app.directory:read, on purpose).
隐私规则:谁在哪个部门、担任什么角色是员工的个人数据,所以成员列表有自己的范围 app.org:read,与 app.directory:read 分开声明、分开审核;只回答令牌所属企业(租户)的数据,只含本企业的成员;按调用者的数据范围裁剪;分页;字段只有 id、显示名、部门和角色,从不包含联系方式(邮箱、手机号)或头像。English: privacy rules: who sits in which department with which role is personal data of the staff, so the member list has a scope of its own (app.org:read, declared and reviewed apart from app.directory:read), answers only the token's tenant and its own members, is cut to the caller's data scope and paged, and carries only ids, display names, departments and roles, never contact details (e-mail, phone) or a picture.
- 认证:
bearer - 范围:
app.org:read - operationId:
listOrgMembers
参数
| 名称 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
point | query | string | 是 | 本应用的权限点(以 app.{本应用 id}. 开头);按调用者在它上面的数据范围裁剪成员 |
cursor | query | string | 上一页的 next(不透明,原样传回);省略为第一页 | |
limit | query | integer | 每页条数,1 到 500,默认 100 默认 100最小 1,最大 500 |
响应
| 状态 | 说明 |
|---|---|
| 200 | 一页成员 |
| 401 | 见 Unauthorized |
| 403 | 见 Forbidden |
| 422 | 字段或参数不被接受(正文读不出来、有未知字段、缺必填、取值越界)。见 Unprocessable |
| 429 | 见 RateLimited |
| 500 | 见 Internal |
| 501 | capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。见 CapabilityOff |
| 503 | unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。见 Unavailable |
200 响应正文(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
items | OrgMember[] | 是 | |
items[].id | string | 是 | 账号 id |
items[].name | string | 是 | 显示名 |
items[].units | string[] | 是 | 所属的部门和被任命的部门(不含上级) |
items[].roles | string[] | 是 | 企业角色 id |
next | string | 是 | 下一页的 cursor;空字符串是到头了 |
事件(Webhooks)
平台向你登记的 https 地址推送的事件。每个事件是一个 POST 请求。
event:deal
平台把一笔成交(销售、退款、作废)送给声明了 event:deal 服务的应用
触发器 event:{kind},由平台的服务运行时投递到应用在清单 services 里声明的端点,至少一次。正文是 {input, idempotencyKey, runId, trigger, attempt};idempotencyKey 也在请求头 Idempotency-Key,处理程序按它去重。请求头 K3-Assertion 是平台签的短时断言,处理前要验证。回答的状态含义:2xx 完成;423 加 Retry-After 表示还没到时候;其他 4xx(408、429 除外)拒绝、不再重试;其余重试。
input 是 {caller, event}:caller 是代表租户的调用者(字段名是 Go 的大写形式 Tenant、User、Name、Roles、Agent、Via),event 是成交事件。幂等键是 deal: 加事件的 key。退款或作废先于它所冲销的销售到达时,回 423 加 Retry-After(销售还没到)。
- operationId:
receiveDealEvent
参数
| 名称 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
K3-Assertion | header | string | 是 | 平台签发的短时断言(JWT),处理前要验证。同时带 Idempotency-Key(运行的键)、X-K3-Run(运行 id)、X-K3-Attempt(第几次) |
Idempotency-Key | header | string | 每个 POST 都收。SDK 未传入时会生成 uuid v4。24 小时内同键同正文重放第一次的回答 最短 1,最长 255 |
请求正文(必填)(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
input | DealDeliveryInput | 是 | event:deal 的输入 |
input.caller | DealCaller | 是 | 代表租户的调用者(Go 结构没有 json 标签,字段名是大写形式) |
input.caller.Tenant | string | 是 | 租户 |
input.caller.User | string | 用户 | |
input.caller.Name | string | 姓名 | |
input.caller.Roles | string[] | 角色 | |
input.caller.Agent | string | 平台代理 | |
input.caller.Via | string | 怎么发起的 | |
input.event | DealEvent | 是 | 一笔成交 |
input.event.key | string | 是 | 幂等键 |
input.event.kind | string | 是 | sale、refund 或 void |
input.event.source | DealSource | 是 | 成交从哪个应用来 |
input.event.source.app | string | 是 | 应用 id |
input.event.source.ref | string | 是 | k3:// 引用,退款指退款本身 |
input.event.customer | string | 客户 id;匿名为空 | |
input.event.amount_cents | integer | 是 | 折后实付;退款为退回的金额 |
input.event.currency | string | 空为租户的币种 | |
input.event.lines | DealLine[] | ||
input.event.lines[].sku | string | 是 | 商品 id(对平台不透明) |
input.event.lines[].name | string | 是 | 名称 |
input.event.lines[].qty | integer | 是 | 数量 |
input.event.lines[].amount_cents | integer | 是 | 金额 |
input.event.attribution | DealAttribution | 是 | 成交从哪里来(只有内部引用和标签,没有个人信息) |
input.event.attribution.channel | string | 渠道 | |
input.event.attribution.campaign | string | k3://campaign/<id> | |
input.event.attribution.site | string | 站点 | |
input.event.attribution.referrer | string | 分销者的客户 id | |
input.event.attribution.utm | map[string, string] | UTM | |
input.event.attribution.voucher | string | 用了哪张券 | |
input.event.reverses | string | 退款或作废所冲销的销售的 key | |
input.event.at | string(date-time) | 是 | 成交发生的业务时间 |
idempotencyKey | string | 是 | 这次运行的键;同键是同一次运行 |
runId | string | 是 | 运行 id |
trigger | string | 是 | 触发器,例如 "event:deal" |
attempt | integer | 是 | 第几次投递 |
响应
| 状态 | 说明 |
|---|---|
| 200 | 已处理。任何 2xx 都表示这次运行完成 |
| 422 | 其他 4xx(408、429 除外):拒绝,这次运行不再重试,在管理员的运行列表里可见 |
| 423 | 还没到时候:平台过一会儿再送(头 Retry-After 的秒数,5 秒到 1 小时,默认 5 分钟),不用掉一次尝试,也不算服务失败;等满 24 小时仍是 423 则这次运行失败 |
| 500 | 5xx、408、429,或没有回答:按退避重试,最多 5 次 |
event:payment
平台把一笔收款或退款结果送给声明了 event:payment 服务的应用
触发器 event:{kind},由平台的服务运行时投递到应用在清单 services 里声明的端点,至少一次。正文是 {input, idempotencyKey, runId, trigger, attempt};idempotencyKey 也在请求头 Idempotency-Key,处理程序按它去重。请求头 K3-Assertion 是平台签的短时断言,处理前要验证。回答的状态含义:2xx 完成;423 加 Retry-After 表示还没到时候;其他 4xx(408、429 除外)拒绝、不再重试;其余重试。
input 是 {kind, order, refund}:kind 为 paid 或 refunded,refund 只在退款时有。幂等键是 paid: 加订单 id,退款是 refund: 加退款 id。
- operationId:
receivePaymentEvent
参数
| 名称 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
K3-Assertion | header | string | 是 | 平台签发的短时断言(JWT),处理前要验证。同时带 Idempotency-Key(运行的键)、X-K3-Run(运行 id)、X-K3-Attempt(第几次) |
Idempotency-Key | header | string | 每个 POST 都收。SDK 未传入时会生成 uuid v4。24 小时内同键同正文重放第一次的回答 最短 1,最长 255 |
请求正文(必填)(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
input | PaymentDeliveryInput | 是 | event:payment 的输入 |
input.kind | string | 是 | paid 或 refunded 可选值: paid、refunded |
input.order | PaymentOrder | 是 | 一张支付订单 |
input.order.tenant | string | 是 | 租户 |
input.order.id | string | 是 | 订单 id |
input.order.channel | string | 是 | 渠道 |
input.order.product | string | 是 | 产品 |
input.order.outTradeNo | string | 是 | 商户单号 |
input.order.amountCents | integer | 是 | 金额 |
input.order.currency | string | 是 | 币种 |
input.order.subject | string | 是 | 标题 |
input.order.status | string | 是 | 状态 |
input.order.sourceApp | string | 来源应用 | |
input.order.sourceRef | string | 来源引用 | |
input.order.payToken | string | 是 | 付款令牌 |
input.order.codeUrl | string | 二维码地址 | |
input.order.payUrl | string | 支付地址 | |
input.order.appId | string | JSAPI 所用的 appid | |
input.order.channelTradeNo | string | 渠道单号 | |
input.order.refundedCents | integer | 是 | 已退 |
input.order.createdBy | string | 创建者 | |
input.order.settleAttempts | integer | 是 | 结算尝试次数 |
input.order.expiresAt | string(date-time) | 是 | 过期时间 |
input.order.paidAt | string(date-time) | 支付时间 | |
input.order.closedAt | string(date-time) | 关闭时间 | |
input.order.createdAt | string(date-time) | 是 | 创建时间 |
input.order.settledAt | string(date-time) | 结算时间 | |
input.refund | PaymentRefund | 一笔退款 | |
input.refund.tenant | string | 是 | 租户 |
input.refund.id | string | 是 | 退款 id |
input.refund.orderId | string | 是 | 订单 id |
input.refund.outRefundNo | string | 是 | 商户退款单号 |
input.refund.amountCents | integer | 是 | 金额 |
input.refund.reason | string | 原因 | |
input.refund.status | string | 是 | 状态 |
input.refund.channelRefundId | string | 渠道退款号 | |
input.refund.createdBy | string | 创建者 | |
input.refund.settleAttempts | integer | 是 | 结算尝试次数 |
input.refund.lastError | string | 最近的错误 | |
input.refund.createdAt | string(date-time) | 是 | 创建时间 |
input.refund.settledAt | string(date-time) | 结算时间 | |
idempotencyKey | string | 是 | 这次运行的键;同键是同一次运行 |
runId | string | 是 | 运行 id |
trigger | string | 是 | 触发器,例如 "event:deal" |
attempt | integer | 是 | 第几次投递 |
响应
| 状态 | 说明 |
|---|---|
| 200 | 已处理。任何 2xx 都表示这次运行完成 |
| 422 | 其他 4xx(408、429 除外):拒绝,这次运行不再重试,在管理员的运行列表里可见 |
| 423 | 还没到时候:平台过一会儿再送(头 Retry-After 的秒数,5 秒到 1 小时,默认 5 分钟),不用掉一次尝试,也不算服务失败;等满 24 小时仍是 423 则这次运行失败 |
| 500 | 5xx、408、429,或没有回答:按退避重试,最多 5 次 |
event:app.installed
租户里的应用有变化(安装、升级、开关、卸载)
触发器 event:{kind},由平台的服务运行时投递到应用在清单 services 里声明的端点,至少一次。正文是 {input, idempotencyKey, runId, trigger, attempt};idempotencyKey 也在请求头 Idempotency-Key,处理程序按它去重。请求头 K3-Assertion 是平台签的短时断言,处理前要验证。回答的状态含义:2xx 完成;423 加 Retry-After 表示还没到时候;其他 4xx(408、429 除外)拒绝、不再重试;其余重试。
input 是 {id, type, tenant, createdAt},type 为 app.installed;幂等键是 id。它只说“变了”,要看现状请重新读取。
- operationId:
receiveAppInstalledChange
参数
| 名称 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
K3-Assertion | header | string | 是 | 平台签发的短时断言(JWT),处理前要验证。同时带 Idempotency-Key(运行的键)、X-K3-Run(运行 id)、X-K3-Attempt(第几次) |
Idempotency-Key | header | string | 每个 POST 都收。SDK 未传入时会生成 uuid v4。24 小时内同键同正文重放第一次的回答 最短 1,最长 255 |
请求正文(必填)(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
input | TenantChangeInput | 是 | 租户变化事件的输入 |
input.id | string | 是 | 事件 id,也是运行的键 |
input.type | string | 是 | app.installed 或 permissions.changed |
input.tenant | string | 是 | 租户 |
input.createdAt | string(date-time) | 是 | 发出时间 |
idempotencyKey | string | 是 | 这次运行的键;同键是同一次运行 |
runId | string | 是 | 运行 id |
trigger | string | 是 | 触发器,例如 "event:deal" |
attempt | integer | 是 | 第几次投递 |
响应
| 状态 | 说明 |
|---|---|
| 200 | 已处理。任何 2xx 都表示这次运行完成 |
| 422 | 其他 4xx(408、429 除外):拒绝,这次运行不再重试,在管理员的运行列表里可见 |
| 423 | 还没到时候:平台过一会儿再送(头 Retry-After 的秒数,5 秒到 1 小时,默认 5 分钟),不用掉一次尝试,也不算服务失败;等满 24 小时仍是 423 则这次运行失败 |
| 500 | 5xx、408、429,或没有回答:按退避重试,最多 5 次 |
event:permissions.changed
租户的部门、角色或分配有变化
触发器 event:{kind},由平台的服务运行时投递到应用在清单 services 里声明的端点,至少一次。正文是 {input, idempotencyKey, runId, trigger, attempt};idempotencyKey 也在请求头 Idempotency-Key,处理程序按它去重。请求头 K3-Assertion 是平台签的短时断言,处理前要验证。回答的状态含义:2xx 完成;423 加 Retry-After 表示还没到时候;其他 4xx(408、429 除外)拒绝、不再重试;其余重试。
input 同 event:app.installed,type 为 permissions.changed;幂等键是 id。它只说“变了”,要看现状请重新读取。
- operationId:
receivePermissionsChanged
参数
| 名称 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
K3-Assertion | header | string | 是 | 平台签发的短时断言(JWT),处理前要验证。同时带 Idempotency-Key(运行的键)、X-K3-Run(运行 id)、X-K3-Attempt(第几次) |
Idempotency-Key | header | string | 每个 POST 都收。SDK 未传入时会生成 uuid v4。24 小时内同键同正文重放第一次的回答 最短 1,最长 255 |
请求正文(必填)(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
input | TenantChangeInput | 是 | 租户变化事件的输入 |
input.id | string | 是 | 事件 id,也是运行的键 |
input.type | string | 是 | app.installed 或 permissions.changed |
input.tenant | string | 是 | 租户 |
input.createdAt | string(date-time) | 是 | 发出时间 |
idempotencyKey | string | 是 | 这次运行的键;同键是同一次运行 |
runId | string | 是 | 运行 id |
trigger | string | 是 | 触发器,例如 "event:deal" |
attempt | integer | 是 | 第几次投递 |
响应
| 状态 | 说明 |
|---|---|
| 200 | 已处理。任何 2xx 都表示这次运行完成 |
| 422 | 其他 4xx(408、429 除外):拒绝,这次运行不再重试,在管理员的运行列表里可见 |
| 423 | 还没到时候:平台过一会儿再送(头 Retry-After 的秒数,5 秒到 1 小时,默认 5 分钟),不用掉一次尝试,也不算服务失败;等满 24 小时仍是 423 则这次运行失败 |
| 500 | 5xx、408、429,或没有回答:按退避重试,最多 5 次 |
event:realtime.doc.projected
本应用的一份实时文档投影完成了
触发器 event:{kind},由平台的服务运行时投递到应用在清单 services 里声明的端点(应用不声明就收不到),至少一次。正文是 {input, idempotencyKey, runId, trigger, attempt};idempotencyKey 也在请求头 Idempotency-Key,处理程序按它去重。请求头 K3-Assertion 是平台签的短时断言,处理前要验证。回答的状态含义同其他服务事件。
input 是 {id, type, tenant, data},type 为 realtime.doc.projected,data 是 {doc, kind, seq, actors}:哪份文档、什么种类、投影在哪个序号、上次投影以来谁写过。要内容请再调用 GET /realtime/docs/{id}/projection(读的是现在的投影,可能比事件的序号新;按序号去重,旧的事件不要覆盖新的投影)。
- operationId:
receiveRealtimeDocProjected
参数
| 名称 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
K3-Assertion | header | string | 是 | 平台签发的短时断言(JWT),处理前要验证。同时带 Idempotency-Key(运行的键)、X-K3-Run(运行 id)、X-K3-Attempt(第几次) |
Idempotency-Key | header | string | 每个 POST 都收。SDK 未传入时会生成 uuid v4。24 小时内同键同正文重放第一次的回答 最短 1,最长 255 |
请求正文(必填)(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
input | RealtimeProjectedInput | 是 | 事件 realtime.doc.projected 的输入 |
input.id | string | 是 | 事件 id,也是运行的键 |
input.type | string | 是 | realtime.doc.projected |
input.tenant | string | 是 | |
input.data | object | 是 | |
input.data.doc | string | 是 | 文档 id |
input.data.kind | string | 是 | 文档种类 |
input.data.seq | integer(int64) | 是 | 投影所在的序号 |
input.data.actors | string[] | 上次投影以来写过的人(日志里连接的身份,最后一个是最后写的人;服务器自己的编辑是 system) | |
idempotencyKey | string | 是 | 这次运行的键;同键是同一次运行 |
runId | string | 是 | 运行 id |
trigger | string | 是 | 触发器,例如 "event:deal" |
attempt | integer | 是 | 第几次投递 |
响应
| 状态 | 说明 |
|---|---|
| 200 | 已处理。任何 2xx 都表示这次运行完成 |
| 422 | 其他 4xx(408、429 除外):拒绝,这次运行不再重试,在管理员的运行列表里可见 |
| 423 | 还没到时候:平台过一会儿再送(头 Retry-After 的秒数,5 秒到 1 小时,默认 5 分钟),不用掉一次尝试,也不算服务失败;等满 24 小时仍是 423 则这次运行失败 |
| 500 | 5xx、408、429,或没有回答:按退避重试,最多 5 次 |
event:access.changed
本应用的一个资源的访问名单变了
触发器 event:{kind},由平台的服务运行时投递到应用在清单 services 里声明的端点(应用不声明就收不到),至少一次。正文是 {input, idempotencyKey, runId, trigger, attempt};idempotencyKey 也在请求头 Idempotency-Key,处理程序按它去重。请求头 K3-Assertion 是平台签的短时断言,处理前要验证。回答的状态含义同其他服务事件。
input 是 {id, type, tenant, data},type 为 access.changed,data 是 {type, id}:哪个资源。登记、删除、分享、撤销、通用访问、开关、转让、批准申请之后都会发。它只说“变了”;维护可见性镜像的应用据此用 GET /access/{type}/visible 刷新,最终一致。
- operationId:
receiveAccessChanged
参数
| 名称 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
K3-Assertion | header | string | 是 | 平台签发的短时断言(JWT),处理前要验证。同时带 Idempotency-Key(运行的键)、X-K3-Run(运行 id)、X-K3-Attempt(第几次) |
Idempotency-Key | header | string | 每个 POST 都收。SDK 未传入时会生成 uuid v4。24 小时内同键同正文重放第一次的回答 最短 1,最长 255 |
请求正文(必填)(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
input | AccessChangedInput | 是 | 事件 access.changed 的输入 |
input.id | string | 是 | 事件 id,也是运行的键 |
input.type | string | 是 | access.changed |
input.tenant | string | 是 | |
input.data | object | 是 | |
input.data.type | string | 是 | 资源类型 |
input.data.id | string | 是 | 资源 id |
idempotencyKey | string | 是 | 这次运行的键;同键是同一次运行 |
runId | string | 是 | 运行 id |
trigger | string | 是 | 触发器,例如 "event:deal" |
attempt | integer | 是 | 第几次投递 |
响应
| 状态 | 说明 |
|---|---|
| 200 | 已处理。任何 2xx 都表示这次运行完成 |
| 422 | 其他 4xx(408、429 除外):拒绝,这次运行不再重试,在管理员的运行列表里可见 |
| 423 | 还没到时候:平台过一会儿再送(头 Retry-After 的秒数,5 秒到 1 小时,默认 5 分钟),不用掉一次尝试,也不算服务失败;等满 24 小时仍是 423 则这次运行失败 |
| 500 | 5xx、408、429,或没有回答:按退避重试,最多 5 次 |
event:{app}.{what}
另一个应用发出的事件(它在清单 events.emits 里声明、经 POST /events/emit 发出)
触发器 event:{app}.{what}:订阅方在清单 services[] 里写 trigger: ["event:campaign.coupon.claimed"] 这样的触发器,平台在发布方每次发出这个类型的事件时,对同一租户里装了并开着订阅方的服务启动一次运行,由服务运行时投递到声明的端点,至少一次。正文、断言、回答的含义同其他服务事件({input, idempotencyKey, runId, trigger, attempt},请求头 K3-Assertion、Idempotency-Key;2xx 完成,423 稍后再送,其他 4xx 拒绝,5xx / 408 / 429 / 没有回答按退避重试,最多 5 次)。
input 是 {id, type, app, tenant, customer, data, createdAt}:app 是发布方,id 也是幂等键(appevt:{发布方}:{发布方的键}),customer 是客户中心的 id。只有在清单 events.emits 里声明了这个类型的应用(类型以它的 id 开头)能发布它;发布方的新版本不再声明时,事件不再送出。这个触发器随订阅方的版本审核。
- operationId:
receiveAppEvent
参数
| 名称 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
K3-Assertion | header | string | 是 | 平台签发的短时断言(JWT),处理前要验证。同时带 Idempotency-Key(运行的键)、X-K3-Run(运行 id)、X-K3-Attempt(第几次) |
Idempotency-Key | header | string | 每个 POST 都收。SDK 未传入时会生成 uuid v4。24 小时内同键同正文重放第一次的回答 最短 1,最长 255 |
请求正文(必填)(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
input | AppEventInput | 是 | 另一个应用发出的事件,作为订阅服务一次运行的输入 |
input.id | string | 是 | 事件 id,也是运行的幂等键:appevt:{发布方}:{发布方的键} |
input.type | string | 是 | 事件类型,{发布方 id}.{what} |
input.app | string | 是 | 发布方应用 id |
input.tenant | string | 是 | 租户 |
input.customer | string | 事件涉及的客户(客户中心的 id),可为空 | |
input.data | object | 发布方给的事件内容(最多 16 KiB) | |
input.createdAt | string(date-time) | 是 | 平台收到事件的时间 |
idempotencyKey | string | 是 | 这次运行的键;同键是同一次运行 |
runId | string | 是 | 运行 id |
trigger | string | 是 | 触发器,例如 "event:deal" |
attempt | integer | 是 | 第几次投递 |
响应
| 状态 | 说明 |
|---|---|
| 200 | 已处理。任何 2xx 都表示这次运行完成 |
| 422 | 其他 4xx(408、429 除外):拒绝,这次运行不再重试,在管理员的运行列表里可见 |
| 423 | 还没到时候:平台过一会儿再送(头 Retry-After 的秒数,5 秒到 1 小时,默认 5 分钟),不用掉一次尝试,也不算服务失败;等满 24 小时仍是 423 则这次运行失败 |
| 500 | 5xx、408、429,或没有回答:按退避重试,最多 5 次 |
event:customer.consent.changed
本企业的一位客户撤回或给出了同意(退订、撤回、员工改动、客户被抹除)
触发器 event:customer.consent.changed:只投给清单 uses 里有 app.customers:consent_events 的应用(客户的选择是个人信息),且要在 services[] 里声明这个触发器。由服务运行时投递到声明的端点,至少一次;正文、断言、回答的含义同其他服务事件。
input 是 {id, type, tenant, customer, channel, purpose, state, at}:customer 是客户中心的 id,channel 为 sms、wechat_template、wecom 或 any,purpose 为 service 或 marketing,state 为 granted 或 withdrawn。没有手机号、姓名或同意的来源。幂等键是 id。
撤回同意时,平台在写入撤回的同一个事务里先取消这位客户在这个渠道、这个用途下排队未发的消息,再把变化写进发件箱;应用收到时,这些消息已经不会发出。客户被抹除时,每一项仍然有效的同意都各发一次撤回。
- operationId:
receiveConsentChanged
参数
| 名称 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
K3-Assertion | header | string | 是 | 平台签发的短时断言(JWT),处理前要验证。同时带 Idempotency-Key(运行的键)、X-K3-Run(运行 id)、X-K3-Attempt(第几次) |
Idempotency-Key | header | string | 每个 POST 都收。SDK 未传入时会生成 uuid v4。24 小时内同键同正文重放第一次的回答 最短 1,最长 255 |
请求正文(必填)(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
input | ConsentChangeInput | 是 | 一位客户的同意变化,作为订阅服务一次运行的输入(只有客户 id、渠道、用途与状态) |
input.id | string | 是 | 变化的 id,也是运行的幂等键 |
input.type | string | 是 | customer.consent.changed |
input.tenant | string | 是 | 租户 |
input.customer | string | 是 | 客户中心的客户 id |
input.channel | string | 是 | 渠道:sms、wechat_template、wecom,或 any(所有渠道) |
input.purpose | string | 是 | 用途:service 或 marketing |
input.state | string | 是 | 新的状态:granted 或 withdrawn |
input.at | string(date-time) | 是 | 变化写入的时间 |
idempotencyKey | string | 是 | 这次运行的键;同键是同一次运行 |
runId | string | 是 | 运行 id |
trigger | string | 是 | 触发器,例如 "event:deal" |
attempt | integer | 是 | 第几次投递 |
响应
| 状态 | 说明 |
|---|---|
| 200 | 已处理。任何 2xx 都表示这次运行完成 |
| 422 | 其他 4xx(408、429 除外):拒绝,这次运行不再重试,在管理员的运行列表里可见 |
| 423 | 还没到时候:平台过一会儿再送(头 Retry-After 的秒数,5 秒到 1 小时,默认 5 分钟),不用掉一次尝试,也不算服务失败;等满 24 小时仍是 423 则这次运行失败 |
| 500 | 5xx、408、429,或没有回答:按退避重试,最多 5 次 |
data:{kind}
平台的数据事件(租户删除、站点删除、客户合并、本应用被卸载)送给在清单 events.receives 里声明了它的应用
数据事件不经服务运行时:应用在清单 events.receives 里写要收的种类(tenant.deleted、site.deleted、customer.merged、app.uninstalled),平台在同一个事务里为每个声明了它、且(除 tenant.deleted 外)装在这个租户里的应用记一行,再投递到 POST /k3/events/{kind},直到应用回 2xx,至少一次,失败后按退避(30 秒起翻倍,最长 6 小时)一直重试,不放弃。同一个事件可能来不止一次,处理程序第二次发现没什么可做就直接回 204。进程内的应用与独立进程的应用走同一条路、收到同样的调用。
请求头 K3-Assertion 是平台签的短时断言(via 为 event,租户与正文的 tenant 相同),处理前要验证;raise-go 的 appkit.Serve 已经做了,并只把清单声明了的种类交给 DataEventHandler,没声明的回 404。
subject 随种类而定:tenant.deleted 是租户 id;site.deleted 是站点 id;customer.merged 是 <被合并的客户 id>><保留的客户 id>(appkit.ParseMergedSubject),应用把指向前者的记录挪到后者;app.uninstalled 是本应用自己的 id,只发给被卸载的这个应用,卸载不删数据(ADR-0028),留不留由应用决定,租户可能再装回来。随租户一起删除的安装只发 tenant.deleted。
- operationId:
receiveDataEvent
参数
| 名称 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
kind | path | string | 是 | 可选值:tenant.deleted、site.deleted、customer.merged、app.uninstalled |
K3-Assertion | header | string | 是 | 平台签发的短时断言(JWT),处理前要验证。同时带 Idempotency-Key(运行的键)、X-K3-Run(运行 id)、X-K3-Attempt(第几次) |
请求正文(必填)(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
tenant | string | 是 | 租户 id,与断言里的租户相同 |
subject | string | 是 | 事件说的是什么:租户 id、站点 id、<被合并>><保留> 的客户 id,或本应用的 id(app.uninstalled) |
test | boolean | true:开发者在测试企业里用 k3 trigger 发的测试投递,平台什么都没删、没合并、没卸载;真实事件不带这个字段 |
响应
| 状态 | 说明 |
|---|---|
| 204 | 已处理。任何 2xx 都表示完成 |
| 404 | 应用没有声明这个种类;平台不会为它记行 |
| 500 | 没处理好:按退避重试,不放弃 |
schedule
平台的时钟按清单里声明的 cron 启动一次服务运行(触发器 schedule)
触发器 schedule:服务在清单 services[] 里声明 trigger: ["schedule"] 和 schedule: {cron, timezone, missed}。平台每 30 秒看一次到点的时间,对每个装了并开着本应用的租户各启动一次运行,由服务运行时投递到声明的端点,至少一次;平台多副本时每个时间只启动一次。正文、断言、回答的含义同其他服务事件({input, idempotencyKey, runId, trigger, attempt},请求头 K3-Assertion、Idempotency-Key;2xx 完成,423 稍后再送,其他 4xx 拒绝,5xx / 408 / 429 / 没有回答按退避重试,最多 5 次)。
cron 是五段(分 时 日 月 星期;数字、*、a-b、/n、逗号列表;星期 0 和 7 都是周日;日和星期都限定时满足其一即可),按 timezone(IANA 名称,默认 Asia/Shanghai)读。幂等键是 schedule: 加这个时间(UTC 的 RFC 3339)。input 是 {scheduledAt, missed}。
错过的时间(平台重启、故障、服务暂停):missed: "skip"(默认)时晚了超过 5 分钟的时间不再启动,只记数;missed: "once" 时只把其中最近的一个补跑一次,input.missed 说折进了几个。服务暂停期间到点的时间不启动运行,服务页上看得到原因。新装、升级、卸载最迟 5 分钟后生效。每次投递都记进开发者的请求日志(方向 out),失败的也是一条脱敏错误。
- operationId:
receiveScheduledRun
参数
| 名称 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
K3-Assertion | header | string | 是 | 平台签发的短时断言(JWT),处理前要验证。同时带 Idempotency-Key(运行的键)、X-K3-Run(运行 id)、X-K3-Attempt(第几次) |
Idempotency-Key | header | string | 每个 POST 都收。SDK 未传入时会生成 uuid v4。24 小时内同键同正文重放第一次的回答 最短 1,最长 255 |
请求正文(必填)(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
input | ScheduleDeliveryInput | 是 | 按清单的 schedule 启动的一次运行的输入 |
input.scheduledAt | string(date-time) | 是 | 这次运行对应的时间(UTC);幂等键是 schedule: 加它 |
input.missed | integer | 之前没有启动的时间有几个(missed: once 时折进本次;skip 时已丢弃) | |
idempotencyKey | string | 是 | 这次运行的键;同键是同一次运行 |
runId | string | 是 | 运行 id |
trigger | string | 是 | 触发器,例如 "event:deal" |
attempt | integer | 是 | 第几次投递 |
响应
| 状态 | 说明 |
|---|---|
| 200 | 已处理。任何 2xx 都表示这次运行完成 |
| 422 | 其他 4xx(408、429 除外):拒绝,这次运行不再重试,在管理员的运行列表里可见 |
| 423 | 还没到时候:平台过一会儿再送(头 Retry-After 的秒数,5 秒到 1 小时,默认 5 分钟),不用掉一次尝试,也不算服务失败;等满 24 小时仍是 423 则这次运行失败 |
| 500 | 5xx、408、429,或没有回答:按退避重试,最多 5 次 |
通用响应
多个接口共用的响应。
CapabilityOff
501 capability_off:这个部署(或这个宿主)不提供这项能力,正文的 capability 是它的范围。不会好转,不要重试:应用照常运行,服务端回自己的调用方 503 capability_off,界面隐藏相应的入口(Raise 宿主规范 §5,ADR-0146)。SDK 把它读成 ErrCapabilityOff。English:this deployment (or host) does not provide the capability; capability names its scope. Do not retry.
正文(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
error | string | 给人看的说明 | |
code | string | 是 | 可选值:capability_off |
capability | string | 是 | 这项能力的范围,例如 app.customers:read |
Conflict
409。conflict:和当前状态冲突。idempotency_conflict:同一 Idempotency-Key 不同正文。idempotency_in_progress:第一次还在处理,稍后再读或换新键。
正文(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
error | ErrorBody | 是 | |
error.code | string | 是 | 稳定错误码。用它分支,不要解析 message。invalid 是这个接口面上的处理程序对 422 回答的码。可选值: invalid_request、invalid_grant、consent_required、consent_revoked、person_gone、unauthorized、forbidden、not_found、method_not_allowed、conflict、payload_too_large、validation_failed、rate_limited、internal、not_implemented、capability_off、unavailable、token_required、invalid_token、invalid_credential、invalid_client、unsupported_grant_type、tenant_required、wrong_environment、credential_ended、address_not_allowed、not_installed、no_scope、scope_required、customer_token_required、assertion_stale、invalid_phone、ambiguous_customer、too_many_attempts、idempotency_conflict、idempotency_in_progress、condition_failed、invalid |
error.message | string | 是 | 给人看的说明 |
error.requestId | string | 与 X-Request-Id 相同 | |
error.docUrl | string | 这条错误的文档,形如 https://dev.{domain}/docs/errors#scope_required | |
error.details | object | 没有内容时是 {} |
DraftRefused
草稿服务的拒绝,状态由它定(400、403、404、409、422 等)。正文是 {"error": "给人看的话", …},外加这次拒绝带的字段(item、missing、confirm 等),不是通用的错误信封。应用自己的令牌打只收页面会话的草稿接口是 403。
正文(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
error | string | 是 |
Forbidden
403。scope_required:缺了操作描述里写的范围;范围必须在应用清单的 uses 里声明。forbidden:客户令牌不能调用这里;只收应用自己的令牌的操作遇到页面会话;或操作描述里写的归属检查没过(不是本应用的权限点、动作或事件类型,sourceApp 不是本应用)。wrong_environment:测试密钥打了正式组织,或正式密钥打了测试企业。not_installed:应用没装、关掉,或组织停用。no_scope:一把范围都没授。address_not_allowed:来源 IP 不在凭证允许名单。
正文(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
error | ErrorBody | 是 | |
error.code | string | 是 | 稳定错误码。用它分支,不要解析 message。invalid 是这个接口面上的处理程序对 422 回答的码。可选值: invalid_request、invalid_grant、consent_required、consent_revoked、person_gone、unauthorized、forbidden、not_found、method_not_allowed、conflict、payload_too_large、validation_failed、rate_limited、internal、not_implemented、capability_off、unavailable、token_required、invalid_token、invalid_credential、invalid_client、unsupported_grant_type、tenant_required、wrong_environment、credential_ended、address_not_allowed、not_installed、no_scope、scope_required、customer_token_required、assertion_stale、invalid_phone、ambiguous_customer、too_many_attempts、idempotency_conflict、idempotency_in_progress、condition_failed、invalid |
error.message | string | 是 | 给人看的说明 |
error.requestId | string | 与 X-Request-Id 相同 | |
error.docUrl | string | 这条错误的文档,形如 https://dev.{domain}/docs/errors#scope_required | |
error.details | object | 没有内容时是 {} |
Internal
500。平台出错,或依赖出了没有名字的错。带上 X-Request-Id 报给我们。
正文(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
error | ErrorBody | 是 | |
error.code | string | 是 | 稳定错误码。用它分支,不要解析 message。invalid 是这个接口面上的处理程序对 422 回答的码。可选值: invalid_request、invalid_grant、consent_required、consent_revoked、person_gone、unauthorized、forbidden、not_found、method_not_allowed、conflict、payload_too_large、validation_failed、rate_limited、internal、not_implemented、capability_off、unavailable、token_required、invalid_token、invalid_credential、invalid_client、unsupported_grant_type、tenant_required、wrong_environment、credential_ended、address_not_allowed、not_installed、no_scope、scope_required、customer_token_required、assertion_stale、invalid_phone、ambiguous_customer、too_many_attempts、idempotency_conflict、idempotency_in_progress、condition_failed、invalid |
error.message | string | 是 | 给人看的说明 |
error.requestId | string | 与 X-Request-Id 相同 | |
error.docUrl | string | 这条错误的文档,形如 https://dev.{domain}/docs/errors#scope_required | |
error.details | object | 没有内容时是 {} |
LengthRequired
411:没带 Content-Length。上传对象必须说明长度。正文是 {"error": "…"}。
正文(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
error | string |
NotFound
404 not_found:对应的记录不存在(客户中心没有这个客户,访客、服务或所指的东西不存在)。
正文(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
error | ErrorBody | 是 | |
error.code | string | 是 | 稳定错误码。用它分支,不要解析 message。invalid 是这个接口面上的处理程序对 422 回答的码。可选值: invalid_request、invalid_grant、consent_required、consent_revoked、person_gone、unauthorized、forbidden、not_found、method_not_allowed、conflict、payload_too_large、validation_failed、rate_limited、internal、not_implemented、capability_off、unavailable、token_required、invalid_token、invalid_credential、invalid_client、unsupported_grant_type、tenant_required、wrong_environment、credential_ended、address_not_allowed、not_installed、no_scope、scope_required、customer_token_required、assertion_stale、invalid_phone、ambiguous_customer、too_many_attempts、idempotency_conflict、idempotency_in_progress、condition_failed、invalid |
error.message | string | 是 | 给人看的说明 |
error.requestId | string | 与 X-Request-Id 相同 | |
error.docUrl | string | 这条错误的文档,形如 https://dev.{domain}/docs/errors#scope_required | |
error.details | object | 没有内容时是 {} |
PayloadTooLarge
413 payload_too_large:正文太大。
正文(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
error | ErrorBody | 是 | |
error.code | string | 是 | 稳定错误码。用它分支,不要解析 message。invalid 是这个接口面上的处理程序对 422 回答的码。可选值: invalid_request、invalid_grant、consent_required、consent_revoked、person_gone、unauthorized、forbidden、not_found、method_not_allowed、conflict、payload_too_large、validation_failed、rate_limited、internal、not_implemented、capability_off、unavailable、token_required、invalid_token、invalid_credential、invalid_client、unsupported_grant_type、tenant_required、wrong_environment、credential_ended、address_not_allowed、not_installed、no_scope、scope_required、customer_token_required、assertion_stale、invalid_phone、ambiguous_customer、too_many_attempts、idempotency_conflict、idempotency_in_progress、condition_failed、invalid |
error.message | string | 是 | 给人看的说明 |
error.requestId | string | 与 X-Request-Id 相同 | |
error.docUrl | string | 这条错误的文档,形如 https://dev.{domain}/docs/errors#scope_required | |
error.details | object | 没有内容时是 {} |
RateLimited
429。rate_limited:这把凭证的调用预算用完,看 Retry-After 和 X-RateLimit-*。
正文(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
error | ErrorBody | 是 | |
error.code | string | 是 | 稳定错误码。用它分支,不要解析 message。invalid 是这个接口面上的处理程序对 422 回答的码。可选值: invalid_request、invalid_grant、consent_required、consent_revoked、person_gone、unauthorized、forbidden、not_found、method_not_allowed、conflict、payload_too_large、validation_failed、rate_limited、internal、not_implemented、capability_off、unavailable、token_required、invalid_token、invalid_credential、invalid_client、unsupported_grant_type、tenant_required、wrong_environment、credential_ended、address_not_allowed、not_installed、no_scope、scope_required、customer_token_required、assertion_stale、invalid_phone、ambiguous_customer、too_many_attempts、idempotency_conflict、idempotency_in_progress、condition_failed、invalid |
error.message | string | 是 | 给人看的说明 |
error.requestId | string | 与 X-Request-Id 相同 | |
error.docUrl | string | 这条错误的文档,形如 https://dev.{domain}/docs/errors#scope_required | |
error.details | object | 没有内容时是 {} |
Refused
422:服务拒绝,或字段不被接受。权益服务的拒绝是给人看的话(例如剩余 0 次不能核销):error.code 是 invalid,error.message 是原话,error.details.refused 为 true;有多项权益时 error.details.items 逐项说明(grant、name、reason)。
正文(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
error | ErrorBody | 是 | |
error.code | string | 是 | 稳定错误码。用它分支,不要解析 message。invalid 是这个接口面上的处理程序对 422 回答的码。可选值: invalid_request、invalid_grant、consent_required、consent_revoked、person_gone、unauthorized、forbidden、not_found、method_not_allowed、conflict、payload_too_large、validation_failed、rate_limited、internal、not_implemented、capability_off、unavailable、token_required、invalid_token、invalid_credential、invalid_client、unsupported_grant_type、tenant_required、wrong_environment、credential_ended、address_not_allowed、not_installed、no_scope、scope_required、customer_token_required、assertion_stale、invalid_phone、ambiguous_customer、too_many_attempts、idempotency_conflict、idempotency_in_progress、condition_failed、invalid |
error.message | string | 是 | 给人看的说明 |
error.requestId | string | 与 X-Request-Id 相同 | |
error.docUrl | string | 这条错误的文档,形如 https://dev.{domain}/docs/errors#scope_required | |
error.details | object | 没有内容时是 {} |
Unauthorized
401。token_required:没带 Bearer,先 POST /open/v1/oauth/token。invalid_token:令牌无效或过期,重新换(SDK 会自动换一次再重试)。credential_ended:凭证吊销、过期,或应用关掉、范围被收光。
正文(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
error | ErrorBody | 是 | |
error.code | string | 是 | 稳定错误码。用它分支,不要解析 message。invalid 是这个接口面上的处理程序对 422 回答的码。可选值: invalid_request、invalid_grant、consent_required、consent_revoked、person_gone、unauthorized、forbidden、not_found、method_not_allowed、conflict、payload_too_large、validation_failed、rate_limited、internal、not_implemented、capability_off、unavailable、token_required、invalid_token、invalid_credential、invalid_client、unsupported_grant_type、tenant_required、wrong_environment、credential_ended、address_not_allowed、not_installed、no_scope、scope_required、customer_token_required、assertion_stale、invalid_phone、ambiguous_customer、too_many_attempts、idempotency_conflict、idempotency_in_progress、condition_failed、invalid |
error.message | string | 是 | 给人看的说明 |
error.requestId | string | 与 X-Request-Id 相同 | |
error.docUrl | string | 这条错误的文档,形如 https://dev.{domain}/docs/errors#scope_required | |
error.details | object | 没有内容时是 {} |
Unavailable
503 unavailable:暂时不可用(这个部署不提供的能力是 501 capability_off)。按 Retry-After 重试;没有该头时 SDK 用指数退避。
正文(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
error | ErrorBody | 是 | |
error.code | string | 是 | 稳定错误码。用它分支,不要解析 message。invalid 是这个接口面上的处理程序对 422 回答的码。可选值: invalid_request、invalid_grant、consent_required、consent_revoked、person_gone、unauthorized、forbidden、not_found、method_not_allowed、conflict、payload_too_large、validation_failed、rate_limited、internal、not_implemented、capability_off、unavailable、token_required、invalid_token、invalid_credential、invalid_client、unsupported_grant_type、tenant_required、wrong_environment、credential_ended、address_not_allowed、not_installed、no_scope、scope_required、customer_token_required、assertion_stale、invalid_phone、ambiguous_customer、too_many_attempts、idempotency_conflict、idempotency_in_progress、condition_failed、invalid |
error.message | string | 是 | 给人看的说明 |
error.requestId | string | 与 X-Request-Id 相同 | |
error.docUrl | string | 这条错误的文档,形如 https://dev.{domain}/docs/errors#scope_required | |
error.details | object | 没有内容时是 {} |
Unprocessable
422:字段或参数不被接受(正文读不出来、有未知字段、缺必填、取值越界)。这个接口面上的处理程序回答的 code 是 invalid。
正文(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
error | ErrorBody | 是 | |
error.code | string | 是 | 稳定错误码。用它分支,不要解析 message。invalid 是这个接口面上的处理程序对 422 回答的码。可选值: invalid_request、invalid_grant、consent_required、consent_revoked、person_gone、unauthorized、forbidden、not_found、method_not_allowed、conflict、payload_too_large、validation_failed、rate_limited、internal、not_implemented、capability_off、unavailable、token_required、invalid_token、invalid_credential、invalid_client、unsupported_grant_type、tenant_required、wrong_environment、credential_ended、address_not_allowed、not_installed、no_scope、scope_required、customer_token_required、assertion_stale、invalid_phone、ambiguous_customer、too_many_attempts、idempotency_conflict、idempotency_in_progress、condition_failed、invalid |
error.message | string | 是 | 给人看的说明 |
error.requestId | string | 与 X-Request-Id 相同 | |
error.docUrl | string | 这条错误的文档,形如 https://dev.{domain}/docs/errors#scope_required | |
error.details | object | 没有内容时是 {} |