유료 구독에 연결된 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분 단위 사용 여부 등은 유료 권한으로 결정됩니다. 자세한 내용은 본 페이지의 한도 및 기본값을 참고하세요.
유료 구독으로 발급된 유효한 API 키를 요청에 포함해야 합니다. 로그인 후 계정 영역에서 키를 생성·교체·폐기할 수 있습니다.
키는 x-api-key 헤더로 전송합니다. 키는 조직에 연결되어 테넌트 식별 및 플랜 기반 이용 한도에 사용됩니다.
키 관리: API 관리
일정 조건을 JSON으로 제출합니다. 유료 연동 표면이며, API 액세스가 부여된 뒤 환경별로 기본 URL이 안내됩니다.
API 액세스 개통 시 또는 운영 담당자가 안내한 기본 URL을 사용하세요.
**BASE_URL**에는 액세스 개통 시 안내된 API 기본 URL(경로 접두사)을 넣습니다.
API 키는 **x-api-key** 헤더로 보냅니다. 조직(테넌트)은 키로 식별되므로 쿼리 문자열에 별도 테넌트 ID를 넘길 필요가 없습니다.
유료 기능(긴급 시프트·노무 상세·일부 스케줄 기본값 등)에는 유효한 유료 구독이 필요합니다. 테넌트에 결제가 구성되지 않은 경우 **503**(예: 코드 **STRIPE_NOT_CONFIGURED**)을 받을 수 있습니다. 회사 정보·감사 로그·사용자(계정)·회사 정보·감사 로그는 웹 앱 소관이며 공개 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 부모 행 1건 조회(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로 직원 1명 조회(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 부모 행 1건 조회(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로 직원 1명 조회(laborLawCompliance, laborFlsaExempt, 개인 상한, laborConstraintMask 등 노무 상세 포함. 소프트 삭제 시 404). |
동일한 API 키로 JSON 본문을 보냅니다. PATCH /v1/schedule-defaults는 테넌트 전역 기본값(requirementsByCellKey, 계획 기간 등)을 저장하며, 유료 항목은 구독 권한에 따릅니다. PUT /v1/staff/{staffId}/weekly-shift-wish는 해당 직원의 주간 희망 그리드를 전체 교체합니다(검증 참고). POST /v1/staff는 명단이 계약 상한을 넘으면 409 STAFF_LIMIT를 반환합니다. 사용자(계정)·회사 정보·감사 로그는 웹 앱 소관이며 공개 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
표준 유료 2주 상세 계획에서 제출당 최대 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 | 표준 유료 2주 상세 계획에서 제출당 최대 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
슬롯 열을 정의하는 시계 범위, 최소 1개 슬롯 생성.
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) | 예 | 슬롯 열을 정의하는 시계 범위, 최소 1개 슬롯 생성. |
| 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_LONGmaxScheduleDays 초과.string, string · 필수: 예 — 둘 다
허용 값
동작
대표 오류
INVALID_TIME_RANGE값 누락 또는 범위에 슬롯 0개.number(JSON 숫자) · 필수: 예
허용 값
동작
대표 오류
INVALID_GRANULARITY60/15가 아니거나 플랜에서 불허.Record<string, number> · 필수: 예
허용 값
동작
대표 오류
INVALID_REQUIREMENTS객체가 아니거나 키의 숫자가 잘못됨.UNKNOWN_CELL_KEY계산된 날짜×슬롯 그리드 밖 키.array · 필수: 예 — 비어 있지 않은 배열
허용 값
동작
대표 오류
INVALID_STAFF빈 배열, 초과, 잘못된 객체, 정리 실패 등.UNKNOWN_FIELD엄격 모드에서 staff 객체에 알 수 없는 키.DUPLICATE_STAFF_IDstaffId 중복.string[] | 생략 · 필수: 아니요 — 선택
허용 값
SHORTFALL 검사
대표 오류
INVALID_AVAILABLE_CELL알 수 없는 셀 키 또는 빈 항목.SHORTFALL_CELLS필요 인원 대비 가용 인원 부족.해당 없음 — 서버에 저장 · 요청에 포함: 아니요 — 이 키는 보내지 않음
부모 행에 저장되는 내용
문서
허용되지 않은 키를 보낸 경우
UNKNOWN_FIELD엄격 모드가 알 수 없는 루트 또는 staff 속성을 거부.`sanitize.ts` 구현대로 검증 전후에 적용됩니다. INVALID_STAFF 거부 이유를 설명합니다.
staffId
displayName
셀 키(requirements / availableCells)
202 Accepted
본문이 검증을 통과하고 조건이 기록되었으며, 최적화는 비동기로 계속될 수 있습니다. 핸들러가 conditionId 등이 포함된 JSON을 반환할 수 있습니다.
검증 오류는 안정적인 `code`가 있는 구조화된 정보를 반환합니다. 검증 전에 JSON 파싱(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.