使用与付费订阅绑定的 API 密钥对接生产环境的排班提交 API。租户排班默认值可通过 PATCH /v1/schedule-defaults 保存;员工周次班次愿望可通过 GET/PUT /v1/staff/{staffId}/weekly-shift-wish 读取或整体替换。计费遵循订阅与合同(不按 API 调用从量计费)。本页说明付费权益、校验规则与错误码 — 可用侧栏搜索跳转到各字段。
本页说明面向外部集成的产品 REST API(API Gateway 的 {stage}/v1/*,使用 x-api-key 认证)。
排班结果完成 Webhook 是在 API 管理中注册的出站 HTTPS 通知(不是 REST CRUD)。载荷与签名见本页「完成通知 Webhook」。
站点内浏览器路由(如支付回调、统计路径)不能替代本产品 API。外部系统请使用本页的 /v1/* 与完成通知 Webhook。
本 HTTP API 属于付费产品:需有生效的商业协议,并在入驻后向贵组织发放密钥。
费用按订阅与合同收取;付费产品通常按登记员工人数(席)按月计费(见定价页)。
沙盒/免费档限制不适用于付费 API 密钥。日程跨度、人数、是否启用 15 分钟粒度等由付费权益决定。详见本页的限额与默认值。
以 JSON 提交排班条件。这是付费集成面;开通 API 访问后,将按环境提供具体基址 URL。
请使用 API 访问开通时或运维联系人提供的基址 URL。
将 **BASE_URL** 替换为开通访问时提供的 API 基址 URL(路径前缀)。
在 **x-api-key** 请求头中发送 API 密钥。贵组织(租户)通过密钥自动识别——无需在查询字符串中单独传递租户 ID。
付费功能(紧急班次、劳务详情、部分排班默认值等)需要有效的付费订阅。若租户未完成计费配置,可能收到 **503**(例如代码 **STRIPE_NOT_CONFIGURED**)。公司信息、审计日志与用户(账户)、公司信息与审计日志由 Web 应用负责,不包含在公开 API 中。
Windows PowerShell:行尾的 `\` **不是**续行。请写一行,或用行末 **反引号(`)**续行。
curl -sS -D - \ -H "x-api-key: YOUR_API_KEY" \ "BASE_URL/v1/schedule-results?limit=10" curl -sS -D - \ -H "x-api-key: YOUR_API_KEY" \ "BASE_URL/v1/staff"
与 POST /v1/schedule 使用相同的基础 URL 与 API 密钥。可选查询参数:limit(1〜100,默认 50)、cursor(将上一次响应中的 nextCursor 原样传入的不透明令牌)。
列出 SCHEDULE_RESULT 父行:conditionId、status、candidateCount、createdAt/updatedAt 等。DynamoDB 父行分页。
排班结果历史搜索(与浏览器历史查看相同)。可选 from / to(ISO 8601,默认服务开始至现在)、keyword、eventName(逗号分隔 INSERT,MODIFY,REMOVE)、limit、cursor。自动合并近期与归档,仅返回 items / nextCursor。
按 conditionId 获取一条 SCHEDULE_RESULT 父行(JSON 属性;省略 PK/SK)。
已解析的优化输出:status、candidates、如有则含 confirmedAssignments。若 status 为 completed 且尚未确认,此 GET 可能自动确认 rank-1(副作用)。手动确认请使用 POST …/confirm-assignments。
手动确认用审查载荷(候选项、requiredByCellKey、员工 allowedCellKeys 等)。
紧急班次上下文(日历日、员工、时段列表)。需付费订阅;条件不存在时为 null。
列出 SCHEDULE_CONDITION 父行(conditionId、日期、可选 publicApiCancelledAt)。
条件父行及 reqDays、staffSnapshots(不含 PK/SK)。
租户排班默认值行(SCHEDULE_DEFAULTS),未保存则为 null。
实绩班次 SCHEDULE_ACTUAL 行,无则为 null。
员工周次希望行,无则为 null。
列出租户在册人员(按显示名排序)。
按 staffId 获取一名人员,含 laborLawCompliance、laborFlsaExempt、个人上限、laborConstraintMask 等劳务详情(软删除返回 404)。
| 方法 | 路径 | 说明 |
|---|---|---|
| GET | {baseUrl}/v1/schedule-results | 列出 SCHEDULE_RESULT 父行:conditionId、status、candidateCount、createdAt/updatedAt 等。DynamoDB 父行分页。 |
| GET | {baseUrl}/v1/schedule-results/history | 排班结果历史搜索(与浏览器历史查看相同)。可选 from / to(ISO 8601,默认服务开始至现在)、keyword、eventName(逗号分隔 INSERT,MODIFY,REMOVE)、limit、cursor。自动合并近期与归档,仅返回 items / nextCursor。 |
| GET | {baseUrl}/v1/schedule-results/{conditionId} | 按 conditionId 获取一条 SCHEDULE_RESULT 父行(JSON 属性;省略 PK/SK)。 |
| GET | {baseUrl}/v1/schedule-results/{conditionId}/resolution | 已解析的优化输出:status、candidates、如有则含 confirmedAssignments。若 status 为 completed 且尚未确认,此 GET 可能自动确认 rank-1(副作用)。手动确认请使用 POST …/confirm-assignments。 |
| GET | {baseUrl}/v1/schedule-results/{conditionId}/review | 手动确认用审查载荷(候选项、requiredByCellKey、员工 allowedCellKeys 等)。 |
| GET | {baseUrl}/v1/schedule-results/{conditionId}/emergency-shift-context | 紧急班次上下文(日历日、员工、时段列表)。需付费订阅;条件不存在时为 null。 |
| GET | {baseUrl}/v1/schedule-conditions | 列出 SCHEDULE_CONDITION 父行(conditionId、日期、可选 publicApiCancelledAt)。 |
| GET | {baseUrl}/v1/schedule-conditions/{conditionId} | 条件父行及 reqDays、staffSnapshots(不含 PK/SK)。 |
| GET | {baseUrl}/v1/schedule-defaults | 租户排班默认值行(SCHEDULE_DEFAULTS),未保存则为 null。 |
| GET | {baseUrl}/v1/schedule-actual/{conditionId} | 实绩班次 SCHEDULE_ACTUAL 行,无则为 null。 |
| GET | {baseUrl}/v1/staff/{staffId}/weekly-shift-wish | 员工周次希望行,无则为 null。 |
| GET | {baseUrl}/v1/staff | 列出租户在册人员(按显示名排序)。 |
| GET | {baseUrl}/v1/staff/{staffId} | 按 staffId 获取一名人员,含 laborLawCompliance、laborFlsaExempt、个人上限、laborConstraintMask 等劳务详情(软删除返回 404)。 |
使用同一 API 密钥发送 JSON 请求体。PATCH /v1/schedule-defaults 保存租户级排班默认值(requirementsByCellKey、计划周期等);付费项按订阅权益生效。PUT /v1/staff/{staffId}/weekly-shift-wish 会整体替换该员工的周次愿望网格(见下方验证说明)。POST /v1/staff 在名册超出合同上限时返回 409 STAFF_LIMIT。用户(账户)、公司信息与审计日志由 Web 应用负责,不包含在公开 API 中。
POST /v1/staff 仅需 JSON { "displayName": "..." }。PATCH /v1/staff/{staffId} 可发送 displayName、laborLawCompliance、laborFlsaExempt、personalMaxWeeklyMinutes / personalMaxMonthlyMinutes / personalMaxThreeMonthMinutes(整数或 null 清除)、laborConstraintMask(对象或 null,仅 laborLawCompliance 为 true 时)的任意组合(劳务字段需付费订阅)。POST /v1/schedule-results/{conditionId}/emergency-shift:absentStaffIds、absentDatesYmd 和/或 absentSlots(需付费且参照班次已完成)。POST …/confirm-assignments:assignments 数组及可选 relaxAvailability。PATCH /v1/schedule-defaults 见 PUBLIC_API_SCHEDULE_REQUEST_BODY.md §12。PUT /v1/staff/{staffId}/weekly-shift-wish:scheduleStartDate、scheduleEndDate、timeRangeStart、timeRangeEnd、wishByCellKey。
保存租户排班默认值(请求体与 schedule-defaults-actions 的 saveSchema 一致)。付费项按订阅权益生效。
创建人员(displayName)。返回 201 及 staff JSON。
复制已完成参照班次并应用缺勤,创建新 condition(201 与 conditionId)。需付费订阅。
校验并保存手动编辑的分配(200 与 { ok: true })。
更新显示名及劳务详情(laborLawCompliance、laborFlsaExempt、个人上限、laborConstraintMask)。
软删除人员(设置 deletedAt)。
将条件标记为已取消(publicApiCancelledAt);不删除子行。
保存实绩分配 JSON { "assignments": [ ... ] }(对照条件网格校验)。
全量替换周次希望:完整网格(1–7 日),每格 wishByCellKey(NONE|LOW|HIGH);粒度遵循租户默认值。
| 方法 | 路径 | 说明 |
|---|---|---|
| PATCH | {baseUrl}/v1/schedule-defaults | 保存租户排班默认值(请求体与 schedule-defaults-actions 的 saveSchema 一致)。付费项按订阅权益生效。 |
| POST | {baseUrl}/v1/staff | 创建人员(displayName)。返回 201 及 staff JSON。 |
| POST | {baseUrl}/v1/schedule-results/{conditionId}/emergency-shift | 复制已完成参照班次并应用缺勤,创建新 condition(201 与 conditionId)。需付费订阅。 |
| POST | {baseUrl}/v1/schedule-results/{conditionId}/confirm-assignments | 校验并保存手动编辑的分配(200 与 { ok: true })。 |
| PATCH | {baseUrl}/v1/staff/{staffId} | 更新显示名及劳务详情(laborLawCompliance、laborFlsaExempt、个人上限、laborConstraintMask)。 |
| DELETE | {baseUrl}/v1/staff/{staffId} | 软删除人员(设置 deletedAt)。 |
| DELETE | {baseUrl}/v1/schedule-conditions/{conditionId} | 将条件标记为已取消(publicApiCancelledAt);不删除子行。 |
| PUT | {baseUrl}/v1/schedule-actual/{conditionId} | 保存实绩分配 JSON { "assignments": [ ... ] }(对照条件网格校验)。 |
| PUT | {baseUrl}/v1/staff/{staffId}/weekly-shift-wish | 全量替换周次希望:完整网格(1–7 日),每格 wishByCellKey(NONE|LOW|HIGH);粒度遵循租户默认值。 |
When a schedule result reaches a terminal status, we POST a signed JSON notification to your HTTPS URL. The body does not include the full result; fetch details with GET /v1/schedule-results/{conditionId}.
Playground results are not delivered. If the webhook is disabled or no URL is saved, nothing is sent.
Event type and when it is sent.
schedule.result.terminal
Schedule result status becomes completed, no_solution, failed, error, or canceled
| type | 时机 |
|---|---|
| schedule.result.terminal | Schedule result status becomes completed, no_solution, failed, error, or canceled |
status is terminal only. customerId is omitted from the body.
{
"type": "schedule.result.terminal",
"conditionId": "019ee481-e855-7000-abd8-977cbfd64ffc",
"status": "completed",
"occurredAt": "2026-07-16T13:00:54.694Z",
"links": {
"result": "{baseUrl}/v1/schedule-results/019ee481-e855-7000-abd8-977cbfd64ffc"
}
}Content-Type
application/json
User-Agent
AutoScheduler-Webhook/1.0
X-AutoScheduler-Timestamp
Unix seconds as a string
X-AutoScheduler-Signature
v1=<hex> (see verification below)
| Header | Description |
|---|---|
| Content-Type | application/json |
| User-Agent | AutoScheduler-Webhook/1.0 |
| X-AutoScheduler-Timestamp | Unix seconds as a string |
| X-AutoScheduler-Signature | v1=<hex> (see verification below) |
Compute a digest from the raw body (before JSON parse) and the Timestamp, then compare to Signature. Reject requests when |now − timestamp| exceeds 300 seconds (5 minutes) unless you intentionally allow wider clock skew.
HMAC-SHA256(signingSecret, `${timestamp}.${rawBody}`) → hex; header value is v1=<hex>On 5xx or timeout we retry automatically. Persistent failures go to a dead-letter queue. Browser push notifications use a separate path.
注册与启用: API 管理
x-api-key
与付费订阅绑定的 API 密钥(识别租户与计划限额)。
Content-Type
application/json
| 头 | 说明 |
|---|---|
| x-api-key | 与付费订阅绑定的 API 密钥(识别租户与计划限额)。 |
| Content-Type | application/json |
部分响应头(如请求 ID)为追踪用元数据,并非您的 API 密钥。含公司或用户数据的 JSON **响应体**请按机密处理。
贵合同下的典型校验上限(15 分钟粒度、排班跨度、登记员工数及相关上限)。
计费模式
Stripe 订阅;产品费用通常按登记员工人数(席)与定价页一致(不按 API 调用从量计费)。
maxScheduleDays
标准付费两周详细规划下,每次提交最多 14 个自然日(仅合同允许时可更长)。
maxStaffPerSchedule
POST /v1/schedule 的 staff 数组最多 500 行(PUBLIC_SCHEDULE_MAX_STAFF;正文内联 staffId)。
maxRosterStaff
POST /v1/staff 名册登记最多 30 人(STAFF_ROSTER_MAX_PAID);超出返回 409 STAFF_LIMIT。
allowedGranularities
[60, 15] — 15 分钟槽为付费能力;也支持 60 分钟。
maxPayloadBytes
524288(512 KiB)UTF-8,除非授予更高上限。
strictUnknownRootKeys
true — 拒绝未知的顶层或 staff 内键
| 设置 | 付费 API(典型) |
|---|---|
| 计费模式 | Stripe 订阅;产品费用通常按登记员工人数(席)与定价页一致(不按 API 调用从量计费)。 |
| maxScheduleDays | 标准付费两周详细规划下,每次提交最多 14 个自然日(仅合同允许时可更长)。 |
| maxStaffPerSchedule | POST /v1/schedule 的 staff 数组最多 500 行(PUBLIC_SCHEDULE_MAX_STAFF;正文内联 staffId)。 |
| maxRosterStaff | POST /v1/staff 名册登记最多 30 人(STAFF_ROSTER_MAX_PAID);超出返回 409 STAFF_LIMIT。 |
| allowedGranularities | [60, 15] — 15 分钟槽为付费能力;也支持 60 分钟。 |
| maxPayloadBytes | 524288(512 KiB)UTF-8,除非授予更高上限。 |
| strictUnknownRootKeys | true — 拒绝未知的顶层或 staff 内键 |
每格所需人数仍为 0–15 的整数。超出请求频率上限时可能返回错误响应。
开启严格模式时,仅接受以下顶层键。其他任何键返回 UNKNOWN_FIELD。
载荷遵循付费公开排班请求模型:日历日期、时区、槽网格(付费 API 上为 60 或 15 分钟)、每格需求与人员可用性。劳动法管辖、付费优化标志与员工级劳动字段不属于 JSON — 持久化时由服务器写入父行 SCHEDULE_CONDITION 的默认值(见「劳动法与付费选项」)。请勿在正文中包含 DynamoDB 键或内部实体类型。
timeZone
用于解释日期与槽的 IANA 时区。
scheduleStartDate / scheduleEndDate
含端点的日历范围;开始 ≤ 结束。
timeRangeStart / timeRangeEnd
定义槽列的挂钟范围;须至少生成一个槽。
slotGranularityMinutes
付费 API:60(按小时)或 15(15 分钟)。须在 allowedGranularities 中。
requirementsByCell
键 = 计算网格中的 cellKey;值 = 0–15 的整数。
staff
非空;最大规模见限额;每项:staffId、displayName、可选 availableCells。
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| timeZone | string | 是 | 用于解释日期与槽的 IANA 时区。 |
| scheduleStartDate / scheduleEndDate | string (YYYY-MM-DD) | 是 | 含端点的日历范围;开始 ≤ 结束。 |
| timeRangeStart / timeRangeEnd | string (HH:mm) | 是 | 定义槽列的挂钟范围;须至少生成一个槽。 |
| slotGranularityMinutes | 60 | 15 | 是 | 付费 API:60(按小时)或 15(15 分钟)。须在 allowedGranularities 中。 |
| requirementsByCell | object | 是 | 键 = 计算网格中的 cellKey;值 = 0–15 的整数。 |
| staff | array | 是 | 非空;最大规模见限额;每项:staffId、displayName、可选 availableCells。 |
以下各节与 `app/lib/public-schedule-api/validate.ts` 的校验及 `sanitize.ts` 的处理一致,除非传入选项,否则使用 `PUBLIC_SCHEDULE_SUBMIT_DEFAULTS` 的付费默认。JSON 数字请用真实数字类型发送(不要用字符串)。校验通过后,`build-schedule-transact-items.ts` 会添加父行字段(付费优化副本、劳动法管辖、模型版本),这些不是请求键 — 见「劳动法与付费选项」。
string | 省略 · 必填: 否 — 可选
允许值
行为
常见错误
TYPE_ERROR不支持的 apiVersion 值。string · 必填: 是
允许值
行为
常见错误
INVALID_TIME_ZONE缺失、空或无效 IANA 时区。string, string · 必填: 是 — 两者
允许值
行为
常见错误
INVALID_DATE_RANGE格式错误、无效日期或空范围。SCHEDULE_SPAN_TOO_LONG超过 maxScheduleDays 的天数。string, string · 必填: 是 — 两者
允许值
行为
常见错误
INVALID_TIME_RANGE缺失或该范围下槽数为 0。number(JSON 数字) · 必填: 是
允许值
行为
常见错误
INVALID_GRANULARITY非 60/15 或方案不允许。Record<string, number> · 必填: 是
允许值
行为
常见错误
INVALID_REQUIREMENTS不是对象或某键数值无效。UNKNOWN_CELL_KEY键不在计算的日期×槽网格内。array · 必填: 是 — 非空数组
允许值
行为
常见错误
INVALID_STAFF空数组、过多行、对象无效或清理失败。UNKNOWN_FIELD严格模式下 staff 对象出现额外键。DUPLICATE_STAFF_ID重复的 staffId。string[] | 省略 · 必填: 否 — 可选
允许值
SHORTFALL 检查
常见错误
INVALID_AVAILABLE_CELL未知 cellKey 或空项。SHORTFALL_CELLS相对需求人数不足。不适用 — 服务端持久化 · 是否在请求中: 否 — 切勿发送这些键
API 在父行上存储的内容
文档
若发送不允许的键
UNKNOWN_FIELD严格模式拒绝未知的根或 staff 属性。在 `sanitize.ts` 中于校验前后应用。可解释 INVALID_STAFF 等拒绝原因。
staffId
displayName
单元格键(requirements / availableCells)
202 Accepted
请求体通过校验并已写入条件;优化可能异步继续。处理程序可返回含 conditionId 等的 JSON。
校验错误返回带稳定 `code` 的结构化信息。解析先于校验(INVALID_JSON、PAYLOAD_TOO_LARGE)。持久化失败可能表现为 DYNAMODB_ERROR。PATCH /v1/schedule-defaults 失败时可能返回 HTTP 400 与 SCHEDULE_DEFAULTS_SAVE_FAILED(详见 details)。
INVALID_JSON
正文不是有效 JSON。
PAYLOAD_TOO_LARGE
UTF-8 字节长度超过 maxPayloadBytes(默认 512 KiB)。
TYPE_ERROR
JSON 类型错误或 apiVersion 字符串不支持。
UNKNOWN_FIELD
严格模式:根或 staff 对象上不允许的属性。
INVALID_TIME_ZONE
timeZone 缺失或不是有效 IANA 名称。
INVALID_DATE_RANGE
日期非 YYYY-MM-DD、范围无效或枚举为空。
SCHEDULE_SPAN_TOO_LONG
起止之间天数过多(见 maxScheduleDays)。
INVALID_TIME_RANGE
时间范围缺失或槽数为 0。
INVALID_GRANULARITY
slotGranularityMinutes 非 60/15 或方案不允许。
INVALID_REQUIREMENTS
requirementsByCell 不是对象或计数非 0–15 整数。
UNKNOWN_CELL_KEY
键不在计算的排班网格中。
INVALID_STAFF
staff 为空、过大、行无效或清理失败。
DUPLICATE_STAFF_ID
staffId 重复。
INVALID_AVAILABLE_CELL
availableCells 中有空项或未知项。
SHORTFALL_CELLS
可用人数相对需求不足。
DYNAMODB_ERROR
校验后的瞬时或持久化错误(取决于处理程序)。
SCHEDULE_DEFAULTS_SAVE_FAILED
PATCH /v1/schedule-defaults:校验或业务规则失败(见 error.details)。
LABOR_COMPLIANCE_REQUIRED
PATCH /v1/staff/{staffId}:laborLawCompliance 为 false 时发送了 laborConstraintMask。
| 代码 | 含义 |
|---|---|
| INVALID_JSON | 正文不是有效 JSON。 |
| PAYLOAD_TOO_LARGE | UTF-8 字节长度超过 maxPayloadBytes(默认 512 KiB)。 |
| TYPE_ERROR | JSON 类型错误或 apiVersion 字符串不支持。 |
| UNKNOWN_FIELD | 严格模式:根或 staff 对象上不允许的属性。 |
| INVALID_TIME_ZONE | timeZone 缺失或不是有效 IANA 名称。 |
| INVALID_DATE_RANGE | 日期非 YYYY-MM-DD、范围无效或枚举为空。 |
| SCHEDULE_SPAN_TOO_LONG | 起止之间天数过多(见 maxScheduleDays)。 |
| INVALID_TIME_RANGE | 时间范围缺失或槽数为 0。 |
| INVALID_GRANULARITY | slotGranularityMinutes 非 60/15 或方案不允许。 |
| INVALID_REQUIREMENTS | requirementsByCell 不是对象或计数非 0–15 整数。 |
| UNKNOWN_CELL_KEY | 键不在计算的排班网格中。 |
| INVALID_STAFF | staff 为空、过大、行无效或清理失败。 |
| DUPLICATE_STAFF_ID | staffId 重复。 |
| INVALID_AVAILABLE_CELL | availableCells 中有空项或未知项。 |
| SHORTFALL_CELLS | 可用人数相对需求不足。 |
| DYNAMODB_ERROR | 校验后的瞬时或持久化错误(取决于处理程序)。 |
| SCHEDULE_DEFAULTS_SAVE_FAILED | PATCH /v1/schedule-defaults:校验或业务规则失败(见 error.details)。 |
| LABOR_COMPLIANCE_REQUIRED | PATCH /v1/staff/{staffId}:laborLawCompliance 为 false 时发送了 laborConstraintMask。 |
{
"apiVersion": "2026-04-01",
"timeZone": "Asia/Tokyo",
"scheduleStartDate": "2026-04-07",
"scheduleEndDate": "2026-04-13",
"timeRangeStart": "08:00",
"timeRangeEnd": "20:00",
"slotGranularityMinutes": 60,
"requirementsByCell": {
"2026-04-07__slot-0": 2
},
"staff": [
{
"staffId": "550e8400-e29b-41d4-a716-446655440000",
"displayName": "Example",
"availableCells": ["2026-04-07__slot-0"]
}
]
}延伸阅读. 产品方案与付费功能:docs/architecture/NURSE_SCHEDULING_SERVICE_SPECIFICATION.md。POST /v1/schedule 请求体:docs/data-and-api/PUBLIC_API_SCHEDULE_REQUEST_BODY.md §1–§11。租户默认值 PATCH 请求体:同一文档 §12。代码:app/lib/public-schedule-api/、app/features/schedule-settings/schedule-defaults-actions.ts、app/lib/public-api-write/weekly-shift-wish-tenant.ts。部署:docs/aws/CDK_DEPLOY.md。