ko
예약고객을 대신하여 예약 확정

고객을 대신하여 예약 확정

비즈니스 화면에서 고객 액터의 `confirm_booking` 액션을 실행합니다(business_on_behalf로 감사 기록됨). 두 가지 용도: (1) 라이브 — 전화로 예약한 고객을 위해 스태프가 슬롯을 확정; (2) 샌드박스 — 고객 매직 토큰 화면은 라이브 전용이므로(샌드박스 작업의 링크는 실제 고객에게 도달할 수 없음) 샌드박스 테스트 작업을 예약 이후 단계로 진행시키는 유일한 방법입니다(book → quote → confirm → assign → complete). 본문에는 고객이 선택한 scheduled_at(비즈니스 로컬 naive datetime)이 담깁니다. 결정 표 — 이 엔드포인트가 반환하는 모든 409와 올바른 다음 단계(HTTP 상태가 아니라 error_code로 분기하세요): • JOB_REQUEST_STAGE_CONFLICT — 읽은 이후 작업이 바뀜(참고: 실패한 confirm 시도도 설계상 status_version을 증가시킵니다). 다음: 작업을 다시 GET하고, 최신 status_version으로 재시도하세요. • JOB_REQUEST_ACTION_NOT_PENDING — 작업이 더 이상 confirm 단계가 아님(보통 이미 확정됨). 다음: 다시 GET하여 현재 상태를 표시; 재시도하지 마세요. • JOB_REQUEST_NO_TECHNICIAN_AVAILABLE — 그 시각이 모두에게 불가능함(근무 시간/고객 창을 벗어났거나, 자격을 갖춘 사람이 없음). 다음: booking-windows / time-segments로 다른 시각을 선택하세요. 긴급 상황이 아닙니다 — 밀어내기는 없는 여유를 만들어내지 못합니다. • JOB_REQUEST_TECH_INFEASIBLE — 강제 지정된 기사가 그때는 절대 작업을 맡을 수 없음; `data.reason`이 이유를 알려줍니다: cannot_arrive_in_time(통근/근무 시작 — `data.earliest_feasible_at`(RFC3339 UTC)가 그들이 현장에 있을 수 있는 같은 날의 가장 이른 시각 → 제안하세요) | missing_required_skills | not_available_today | not_lead_tier. 다음: 기사를 유지하고 earliest_feasible_at 이후로 재조정하거나, 시각을 유지하고 technician_id를 빼세요(자동 선택) / time-segments에서 다른 기사를 선택하세요. 긴급 상황이 아닙니다. • JOB_REQUEST_P0_REQUIRES_DISPLACEMENT — 긴급 플로우로 라우팅되는 유일한 코드: 작업이 P0이고 기사는 자격이 있지만 레인이 실제로 점유됨. 다음: POST emergency/candidates → preview → commit(커밋이 자동 확정함). 주의: 점유 중인 작업들이 스스로 P0라면 미리보기가 EMERGENCY_RESCHEDULE_SLOT_OCCUPIED로 거부됩니다(P0는 절대 P0를 밀어내지 않음) — 그러면 다른 기사/시각을 선택하세요.

인수

idstringpath필수
작업 요청 ID
Idempotency-Keystringheader선택
Unique key making retries safe: a repeat send with the same key replays the original response (header Idempotent-Replayed: true) instead of re-running the operation. Reusing a key with a different body returns 422 IDEMPOTENCY_KEY_REUSE.
arrival_window_minutesintegerbody선택
ArrivalWindowMinutes = 고객이 슬롯 선택기에서 누른 도착 창의 폭(분) (즉 time_slot_step_minutes, 기본값 30). 확정 후 상세 화면이 올바른 창을 다시 렌더링하도록 저장합니다. 선택 사항이며, 범위([5, 240], 슬롯 선택기 스텝과 일치)는 유스케이스에서 검증되어 단일 권한 하에 하나의 오류 코드(JOB_REQUEST_INVALID_INPUT)를 반환합니다.
scheduled_atstringbody선택
Chosen start time — business-local naive datetime, no offset (the business_time.datetime value from the time-segments picker). The server converts to UTC using the job's business timezone.
status_versionintegerbody선택
Optimistic-lock fence: the status_version from your last read. Omitted/0 = fence on the row's current version (no race protection).
technician_idstringbody선택
TechnicianID(비즈니스 confirm 전용 — 고객 화면에서는 무시됨): 순위 기반 자동 선택 대신 이 기사에게 작업을 강제 배정합니다. 순위는 우회되지만 실현 가능성(근무 시간/휴가/지리/스킬), TierLead 규칙, 이중 예약 방지는 그대로 적용됩니다 — 실현 불가능한 강제 기사는 confirm을 거부합니다(P0는 밀어내기 힌트를 받음).
POST/v1/job-requests/{id}/confirm
curl -X POST "https://api.crisphive.com/v1/job-requests/9b2f6c3e-1a4d-4f0a-8f2e-7c5d1b3a9e01/confirm" \
  -H "Authorization: Bearer chsk_test_4eC8xQ9mZ2pL7Ka0rT" \
  -H "Content-Type: application/json" \
  -d '{
  "arrival_window_minutes": 1,
  "scheduled_at": "2030-06-14T09:00:00",
  "status_version": 2,
  "technician_id": "9b2f6c3e-1a4d-4f0a-8f2e-7c5d1b3a9e01"
}'
요청 본문
{
"arrival_window_minutes": ,
"scheduled_at": ,
"status_version": ,
"technician_id":
}

응답