{"openapi":"3.1.0","info":{"title":"Tour Server API","description":"부산 여행 일정 서버 API 문서입니다. 코드에서 생성되므로 배포된 서버의 실제 계약과 항상 일치합니다.\n\n일정 생성·조회는 FastAPI에 위임되며, 위임이 꺼져 있으면 503 EXTERNAL_PROVIDER_UNAVAILABLE을 반환합니다.\n일정 생성 예제의 placeId는 해당 환경에 실제로 적재된 장소로 채워집니다.","version":"v1"},"servers":[{"url":"http://api.busantour.site","description":"Generated server url"}],"tags":[{"name":"출발지·도착지","description":"Kakao Local 기반 위치 검색"},{"name":"장소","description":"내부 DB 장소 검색과 상세 조회"},{"name":"일정 공유","description":"읽기 전용 공유 링크 생성과 폐기"},{"name":"주변 편의시설","description":"장소 주변 편의시설 실시간 검색"},{"name":"일정 미리보기","description":"Planner 실행 전 일정 조건 계산과 확인"},{"name":"여행 질문","description":"일정 생성에 사용하는 질문과 답변 ID"},{"name":"일정","description":"일정 생성, 조회, 수정과 지도 데이터"},{"name":"공유 일정","description":"공유 토큰으로 읽기 전용 일정과 지도 조회"}],"paths":{"/api/v1/schedules":{"get":{"tags":["일정"],"summary":"일정 목록 조회","description":"목록 카드에 필요한 축약 정보만 반환한다. 방문지·경로·평가는 단건 조회를 사용한다.","operationId":"getAll","responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ScheduleSummaryListResponse"}}}},"503":{"description":"일정 생성·조회를 담당하는 FastAPI가 응답하지 않는다. 가능한 code: EXTERNAL_PROVIDER_UNAVAILABLE","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"서버가 처리하지 못한 예외. 응답에 내부 메시지를 담지 않으며 원인은 같은 traceId로 서버 로그에 남는다. 가능한 code: INTERNAL_ERROR","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"post":{"tags":["일정"],"summary":"일정 생성","description":"POST /api/v1/schedule-previews 로 만든 Preview 를 소비해 일정을 만든다. Preview 하나로 일정 하나만 만들 수 있고, 이미 소비된 Preview 는 409 로 응답한다. 같은 Idempotency-Key 로 다시 요청하면 새 일정을 만들지 않는다.","operationId":"createFromPreview","parameters":[{"name":"Idempotency-Key","in":"header","description":"재요청 시 중복 생성을 막는 키. 화면에서 생성 버튼을 누를 때 UUID 를 만들어 재시도까지 같은 값을 쓴다. 최대 128자.","required":true,"schema":{"type":"string"},"example":"3f1b9c2e-6a4d-4f77-9b2a-1c8d5e0f4a31"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SchedulePreviewScheduleRequest"},"examples":{"fromPreview":{"summary":"Preview 응답의 previewId 를 그대로 전달","description":"fromPreview","value":{"previewId":"6afa151a-3fb2-4f3d-821f-53228b88d1c0"}}}}},"required":true},"responses":{"201":{"description":"Created","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ScheduleResponse"}}}},"400":{"description":"요청 값이 올바르지 않다. 가능한 code: INVALID_SCHEDULE_CONDITION, INVALID_SCHEDULE_PREVIEW_REQUEST, FIXED_BASE_LOCATION_REQUIRED, PER_NIGHT_LOCATION_MISSING, MUST_VISIT_PLACE_LIMIT_EXCEEDED, INVALID_EXTERNAL_PLACE, INVALID_PLACE_SEARCH_REQUEST, MALFORMED_REQUEST, IDEMPOTENCY_KEY_REQUIRED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"같은 멱등성 키 재사용, 이미 소비된 Preview, 또는 같은 요청의 생성이 진행 중이다. 가능한 code: IDEMPOTENCY_KEY_REUSED, PREVIEW_ALREADY_CONSUMED, SCHEDULE_CREATION_IN_PROGRESS","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"410":{"description":"Preview가 만료됐다. 가능한 code: PREVIEW_EXPIRED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"일정 생성·조회를 담당하는 FastAPI가 응답하지 않는다. 가능한 code: EXTERNAL_PROVIDER_UNAVAILABLE","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"서버가 처리하지 못한 예외. 응답에 내부 메시지를 담지 않으며 원인은 같은 traceId로 서버 로그에 남는다. 가능한 code: INTERNAL_ERROR","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/schedules/{scheduleId}/shares":{"post":{"tags":["일정 공유"],"summary":"공유 링크 생성","description":"토큰은 응답에서 한 번만 내려주며 서버에는 해시만 저장한다. 폐기된 링크와 없는 링크는 모두 404 SHARE_LINK_NOT_FOUND 로 응답한다.","operationId":"create","parameters":[{"name":"scheduleId","in":"path","description":"일정 ID","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ShareLinkCreateRequest"},"examples":{"expiresInWeek":{"summary":"7일 뒤 만료","description":"expiresInWeek","value":{"expiresInDays":7}},"neverExpires":{"summary":"만료 없음","description":"neverExpires","value":{"expiresInDays":null}}}}},"required":true},"responses":{"201":{"description":"Created","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ShareLinkResponse"}}}},"400":{"description":"요청 값이 올바르지 않다. 가능한 code: INVALID_SCHEDULE_CONDITION, INVALID_SCHEDULE_PREVIEW_REQUEST, FIXED_BASE_LOCATION_REQUIRED, PER_NIGHT_LOCATION_MISSING, MUST_VISIT_PLACE_LIMIT_EXCEEDED, INVALID_EXTERNAL_PLACE, INVALID_PLACE_SEARCH_REQUEST, MALFORMED_REQUEST, IDEMPOTENCY_KEY_REQUIRED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"대상을 찾을 수 없다. 가능한 code: RESOURCE_NOT_FOUND, SCHEDULE_PREVIEW_NOT_FOUND, SCHEDULE_NOT_FOUND, PLACE_NOT_FOUND, SHARE_LINK_NOT_FOUND","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"서버가 처리하지 못한 예외. 응답에 내부 메시지를 담지 않으며 원인은 같은 traceId로 서버 로그에 남는다. 가능한 code: INTERNAL_ERROR","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/schedule-previews":{"post":{"tags":["일정 미리보기"],"summary":"일정 미리보기 생성","description":"입력을 정규화하고 일차별 가용시간을 계산해 Preview를 만든다. 수정 가능한 충돌은 201 응답의 conflicts[]로 반환하고, 형식 오류만 400으로 반환한다. 유효시간은 30분이며 Preview 하나로 일정 하나만 생성할 수 있다.","operationId":"create_1","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SchedulePreviewCreateRequest"},"examples":{"frontendBasic":{"summary":"기본 생성 화면이 실제로 보내는 요청 (숙소 미정 1박 2일)","description":"frontendBasic","value":{"startDate":"2026-09-20","endDate":"2026-09-21","startLocation":{"name":"부산역","longitude":129.0403,"latitude":35.1151},"lodgingPlan":{"mode":"UNDECIDED"},"selectedAnswers":[{"questionId":"COMPANION","answerIds":["COMPANION_FRIENDS"]},{"questionId":"MOBILITY","answerIds":["MOBILITY_NORMAL"]},{"questionId":"PACE","answerIds":["PACE_RELAXED"]},{"questionId":"TRANSIT","answerIds":["TRANSIT_SIMPLE"]},{"questionId":"THEME","answerIds":["THEME_NATURE","THEME_FOOD"]}],"mustVisitPlaceIds":[],"fixedEvents":[],"dayOverrides":[]}},"fullOptions":{"summary":"API 전체 입력. 고정 숙소·종료 제약·자유 요청 포함 (프론트 1차 Deferred)","description":"fullOptions","value":{"startDate":"2026-09-20","endDate":"2026-09-22","startLocation":{"name":"부산역","longitude":129.0403,"latitude":35.1151},"startTime":"10:00","lodgingPlan":{"mode":"FIXED","baseLocation":{"name":"해운대 숙소","longitude":129.1604,"latitude":35.1587}},"endConstraint":{"type":"FLIGHT_DEPARTURE","location":{"name":"김해국제공항","longitude":128.9485,"latitude":35.1732},"targetAt":"2026-09-22T20:00:00+09:00"},"selectedAnswers":[{"questionId":"COMPANION","answerIds":["COMPANION_COUPLE"]},{"questionId":"MOBILITY","answerIds":["MOBILITY_LOW_WALK"]},{"questionId":"PACE","answerIds":["PACE_RELAXED"]},{"questionId":"TRANSIT","answerIds":["TRANSIT_SIMPLE"]},{"questionId":"THEME","answerIds":["THEME_NATURE"]}],"mustVisitPlaceIds":[],"fixedEvents":[],"dayOverrides":[{"date":"2026-09-21","startTime":"09:00","endTime":"21:00"}],"customPrompt":"바다를 많이 보고 걷는 구간은 적었으면 좋겠어요","timeZone":"Asia/Seoul"}}}}},"required":true},"responses":{"201":{"description":"Created","content":{"*/*":{"schema":{"$ref":"#/components/schemas/SchedulePreviewResponse"}}}},"400":{"description":"요청 값이 올바르지 않다. 가능한 code: INVALID_SCHEDULE_CONDITION, INVALID_SCHEDULE_PREVIEW_REQUEST, FIXED_BASE_LOCATION_REQUIRED, PER_NIGHT_LOCATION_MISSING, MUST_VISIT_PLACE_LIMIT_EXCEEDED, INVALID_EXTERNAL_PLACE, INVALID_PLACE_SEARCH_REQUEST, MALFORMED_REQUEST, IDEMPOTENCY_KEY_REQUIRED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"같은 멱등성 키 재사용, 이미 소비된 Preview, 또는 같은 요청의 생성이 진행 중이다. 가능한 code: IDEMPOTENCY_KEY_REUSED, PREVIEW_ALREADY_CONSUMED, SCHEDULE_CREATION_IN_PROGRESS","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"410":{"description":"Preview가 만료됐다. 가능한 code: PREVIEW_EXPIRED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"일정 생성·조회를 담당하는 FastAPI가 응답하지 않는다. 가능한 code: EXTERNAL_PROVIDER_UNAVAILABLE","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"서버가 처리하지 못한 예외. 응답에 내부 메시지를 담지 않으며 원인은 같은 traceId로 서버 로그에 남는다. 가능한 code: INTERNAL_ERROR","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/places/resolve":{"post":{"tags":["장소"],"summary":"외부 장소 확정","description":"사용자가 선택한 외부 검색 결과만 내부 장소로 저장한다. 같은 (source, externalId)는 upsert 되며, 좌표 100m 이내이고 공백·기호를 제거한 이름이 완전히 같은 기존 장소가 있으면 그 장소의 placeId를 반환한다. 이때 응답 source는 기존 장소의 출처이며 적재해 둔 값은 덮어쓰지 않는다.","operationId":"resolve","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PlaceResolveRequest"},"examples":{"naver":{"summary":"네이버 지역검색 결과","description":"naver","value":{"source":"NAVER_LOCAL","externalId":"1291598546-351585232","name":"해운대 해수욕장","category":"여행,명소>관광,명소>해수욕장","address":"부산 해운대구 우동","longitude":129.1598546,"latitude":35.1585232,"placeUrl":"https://map.naver.com/p/entry/place/1234567"}},"kakao":{"summary":"카카오 로컬 결과","description":"kakao","value":{"source":"KAKAO_LOCAL","externalId":"26338954","name":"구남로 카페","category":"음식점 > 카페","address":"부산 해운대구 구남로 1","longitude":129.1615,"latitude":35.162,"placeUrl":"https://place.map.kakao.com/26338954"}}}}},"required":true},"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/PlaceResolveResponse"}}}},"400":{"description":"요청 값이 올바르지 않다. 가능한 code: INVALID_SCHEDULE_CONDITION, INVALID_SCHEDULE_PREVIEW_REQUEST, FIXED_BASE_LOCATION_REQUIRED, PER_NIGHT_LOCATION_MISSING, MUST_VISIT_PLACE_LIMIT_EXCEEDED, INVALID_EXTERNAL_PLACE, INVALID_PLACE_SEARCH_REQUEST, MALFORMED_REQUEST, IDEMPOTENCY_KEY_REQUIRED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"서버가 처리하지 못한 예외. 응답에 내부 메시지를 담지 않으며 원인은 같은 traceId로 서버 로그에 남는다. 가능한 code: INTERNAL_ERROR","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/schedules/{scheduleId}":{"get":{"tags":["일정"],"summary":"일정 단건 조회","description":"방문지·경로·planningAssumptions 를 포함한 전체 일정을 반환한다. 생성 시점에만 계산하는 evaluation 은 포함하지 않는다.","operationId":"get","parameters":[{"name":"scheduleId","in":"path","description":"일정 생성 응답의 id","required":true,"schema":{"type":"string","format":"uuid"},"example":"f2536c52-69d1-4e6c-8ab6-2ede45dba2cd"}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ScheduleResponse"}}}},"400":{"description":"요청 값이 올바르지 않다. 가능한 code: INVALID_SCHEDULE_CONDITION, INVALID_SCHEDULE_PREVIEW_REQUEST, FIXED_BASE_LOCATION_REQUIRED, PER_NIGHT_LOCATION_MISSING, MUST_VISIT_PLACE_LIMIT_EXCEEDED, INVALID_EXTERNAL_PLACE, INVALID_PLACE_SEARCH_REQUEST, MALFORMED_REQUEST, IDEMPOTENCY_KEY_REQUIRED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"대상을 찾을 수 없다. 가능한 code: RESOURCE_NOT_FOUND, SCHEDULE_PREVIEW_NOT_FOUND, SCHEDULE_NOT_FOUND, PLACE_NOT_FOUND, SHARE_LINK_NOT_FOUND","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"일정 생성·조회를 담당하는 FastAPI가 응답하지 않는다. 가능한 code: EXTERNAL_PROVIDER_UNAVAILABLE","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"서버가 처리하지 못한 예외. 응답에 내부 메시지를 담지 않으며 원인은 같은 traceId로 서버 로그에 남는다. 가능한 code: INTERNAL_ERROR","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"patch":{"tags":["일정"],"summary":"일정 수정","description":"stopId는 생성 응답 값으로, 새 장소를 추가할 때는 placeId로 교체해야 합니다.","operationId":"update","parameters":[{"name":"scheduleId","in":"path","description":"일정 생성 응답의 id","required":true,"schema":{"type":"string","format":"uuid"},"example":"f2536c52-69d1-4e6c-8ab6-2ede45dba2cd"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScheduleUpdateRequest"},"examples":{"reorderAndAddPlace":{"summary":"기존 방문지 유지와 새 장소 추가","description":"reorderAndAddPlace","value":{"stops":[{"stopId":"00000000-0000-0000-0000-000000000001","placeId":null,"dayNo":1,"order":1,"stayMinutes":90},{"stopId":null,"placeId":1,"dayNo":1,"order":2,"stayMinutes":60}]}}}}},"required":true},"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ScheduleResponse"}}}},"400":{"description":"요청 값이 올바르지 않다. 가능한 code: INVALID_SCHEDULE_CONDITION, INVALID_SCHEDULE_PREVIEW_REQUEST, FIXED_BASE_LOCATION_REQUIRED, PER_NIGHT_LOCATION_MISSING, MUST_VISIT_PLACE_LIMIT_EXCEEDED, INVALID_EXTERNAL_PLACE, INVALID_PLACE_SEARCH_REQUEST, MALFORMED_REQUEST, IDEMPOTENCY_KEY_REQUIRED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"대상을 찾을 수 없다. 가능한 code: RESOURCE_NOT_FOUND, SCHEDULE_PREVIEW_NOT_FOUND, SCHEDULE_NOT_FOUND, PLACE_NOT_FOUND, SHARE_LINK_NOT_FOUND","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"일정 생성·조회를 담당하는 FastAPI가 응답하지 않는다. 가능한 code: EXTERNAL_PROVIDER_UNAVAILABLE","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"서버가 처리하지 못한 예외. 응답에 내부 메시지를 담지 않으며 원인은 같은 traceId로 서버 로그에 남는다. 가능한 code: INTERNAL_ERROR","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/trip-questions":{"get":{"tags":["여행 질문"],"summary":"여행 질문 조회","operationId":"gettripQuestionsResponse","responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/TripQuestionsResponse"}}}},"500":{"description":"서버가 처리하지 못한 예외. 응답에 내부 메시지를 담지 않으며 원인은 같은 traceId로 서버 로그에 남는다. 가능한 code: INTERNAL_ERROR","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/shared-schedules/{token}":{"get":{"tags":["공유 일정"],"summary":"공유 일정 조회","operationId":"get_1","parameters":[{"name":"token","in":"path","description":"공유 링크 생성 응답의 token","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/SharedScheduleResponse"}}}},"400":{"description":"요청 값이 올바르지 않다. 가능한 code: INVALID_SCHEDULE_CONDITION, INVALID_SCHEDULE_PREVIEW_REQUEST, FIXED_BASE_LOCATION_REQUIRED, PER_NIGHT_LOCATION_MISSING, MUST_VISIT_PLACE_LIMIT_EXCEEDED, INVALID_EXTERNAL_PLACE, INVALID_PLACE_SEARCH_REQUEST, MALFORMED_REQUEST, IDEMPOTENCY_KEY_REQUIRED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"대상을 찾을 수 없다. 가능한 code: RESOURCE_NOT_FOUND, SCHEDULE_PREVIEW_NOT_FOUND, SCHEDULE_NOT_FOUND, PLACE_NOT_FOUND, SHARE_LINK_NOT_FOUND","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"일정 생성·조회를 담당하는 FastAPI가 응답하지 않는다. 가능한 code: EXTERNAL_PROVIDER_UNAVAILABLE","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"서버가 처리하지 못한 예외. 응답에 내부 메시지를 담지 않으며 원인은 같은 traceId로 서버 로그에 남는다. 가능한 code: INTERNAL_ERROR","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/shared-schedules/{token}/map":{"get":{"tags":["공유 일정"],"summary":"공유 일정 지도 조회","operationId":"getMap","parameters":[{"name":"token","in":"path","description":"공유 링크 생성 응답의 token","required":true,"schema":{"type":"string"}},{"name":"dayNo","in":"query","description":"조회할 일차","required":false,"schema":{"type":"integer","format":"int32"},"example":1}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ScheduleMapResponse"}}}},"400":{"description":"요청 값이 올바르지 않다. 가능한 code: INVALID_SCHEDULE_CONDITION, INVALID_SCHEDULE_PREVIEW_REQUEST, FIXED_BASE_LOCATION_REQUIRED, PER_NIGHT_LOCATION_MISSING, MUST_VISIT_PLACE_LIMIT_EXCEEDED, INVALID_EXTERNAL_PLACE, INVALID_PLACE_SEARCH_REQUEST, MALFORMED_REQUEST, IDEMPOTENCY_KEY_REQUIRED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"대상을 찾을 수 없다. 가능한 code: RESOURCE_NOT_FOUND, SCHEDULE_PREVIEW_NOT_FOUND, SCHEDULE_NOT_FOUND, PLACE_NOT_FOUND, SHARE_LINK_NOT_FOUND","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"일정 생성·조회를 담당하는 FastAPI가 응답하지 않는다. 가능한 code: EXTERNAL_PROVIDER_UNAVAILABLE","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"서버가 처리하지 못한 예외. 응답에 내부 메시지를 담지 않으며 원인은 같은 traceId로 서버 로그에 남는다. 가능한 code: INTERNAL_ERROR","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/schedules/{scheduleId}/map":{"get":{"tags":["일정"],"summary":"일정 지도 조회","operationId":"getMap_1","parameters":[{"name":"scheduleId","in":"path","description":"일정 생성 응답의 id","required":true,"schema":{"type":"string","format":"uuid"},"example":"f2536c52-69d1-4e6c-8ab6-2ede45dba2cd"},{"name":"dayNo","in":"query","description":"조회할 일차. 생략하면 전체 일차의 마커와 경로선을 함께 반환한다.","required":false,"schema":{"type":"integer","format":"int32"},"example":1}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ScheduleMapResponse"}}}},"400":{"description":"요청 값이 올바르지 않다. 가능한 code: INVALID_SCHEDULE_CONDITION, INVALID_SCHEDULE_PREVIEW_REQUEST, FIXED_BASE_LOCATION_REQUIRED, PER_NIGHT_LOCATION_MISSING, MUST_VISIT_PLACE_LIMIT_EXCEEDED, INVALID_EXTERNAL_PLACE, INVALID_PLACE_SEARCH_REQUEST, MALFORMED_REQUEST, IDEMPOTENCY_KEY_REQUIRED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"대상을 찾을 수 없다. 가능한 code: RESOURCE_NOT_FOUND, SCHEDULE_PREVIEW_NOT_FOUND, SCHEDULE_NOT_FOUND, PLACE_NOT_FOUND, SHARE_LINK_NOT_FOUND","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"일정 생성·조회를 담당하는 FastAPI가 응답하지 않는다. 가능한 code: EXTERNAL_PROVIDER_UNAVAILABLE","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"서버가 처리하지 못한 예외. 응답에 내부 메시지를 담지 않으며 원인은 같은 traceId로 서버 로그에 남는다. 가능한 code: INTERNAL_ERROR","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/schedule-previews/{previewId}":{"get":{"tags":["일정 미리보기"],"summary":"일정 미리보기 조회","description":"새로고침 복원용이다. 만료된 Preview 는 410 PREVIEW_EXPIRED 로 응답한다.","operationId":"get_2","parameters":[{"name":"previewId","in":"path","description":"Preview 생성 응답의 previewId","required":true,"schema":{"type":"string","format":"uuid"},"example":"6afa151a-3fb2-4f3d-821f-53228b88d1c0"}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/SchedulePreviewResponse"}}}},"400":{"description":"요청 값이 올바르지 않다. 가능한 code: INVALID_SCHEDULE_CONDITION, INVALID_SCHEDULE_PREVIEW_REQUEST, FIXED_BASE_LOCATION_REQUIRED, PER_NIGHT_LOCATION_MISSING, MUST_VISIT_PLACE_LIMIT_EXCEEDED, INVALID_EXTERNAL_PLACE, INVALID_PLACE_SEARCH_REQUEST, MALFORMED_REQUEST, IDEMPOTENCY_KEY_REQUIRED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"대상을 찾을 수 없다. 가능한 code: RESOURCE_NOT_FOUND, SCHEDULE_PREVIEW_NOT_FOUND, SCHEDULE_NOT_FOUND, PLACE_NOT_FOUND, SHARE_LINK_NOT_FOUND","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"같은 멱등성 키 재사용, 이미 소비된 Preview, 또는 같은 요청의 생성이 진행 중이다. 가능한 code: IDEMPOTENCY_KEY_REUSED, PREVIEW_ALREADY_CONSUMED, SCHEDULE_CREATION_IN_PROGRESS","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"410":{"description":"Preview가 만료됐다. 가능한 code: PREVIEW_EXPIRED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"일정 생성·조회를 담당하는 FastAPI가 응답하지 않는다. 가능한 code: EXTERNAL_PROVIDER_UNAVAILABLE","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"서버가 처리하지 못한 예외. 응답에 내부 메시지를 담지 않으며 원인은 같은 traceId로 서버 로그에 남는다. 가능한 code: INTERNAL_ERROR","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/places":{"get":{"tags":["장소"],"summary":"장소 검색","operationId":"search","parameters":[{"name":"keyword","in":"query","required":false,"schema":{"type":"string"},"example":"광안리"},{"name":"longitude","in":"query","required":false,"schema":{"type":"number"},"example":129.0403},{"name":"latitude","in":"query","required":false,"schema":{"type":"number"},"example":35.1151},{"name":"radius","in":"query","required":false,"schema":{"type":"integer","format":"int32","minimum":1},"example":5000},{"name":"scope","in":"query","description":"INTERNAL 은 내부 DB 만, ALL 은 결과가 부족할 때 외부 검색으로 보강한다. 가고싶은 장소 검색 화면은 ALL 을 쓴다.","required":false,"schema":{"type":"string","default":"INTERNAL"},"example":"ALL"},{"name":"size","in":"query","description":"최대 결과 수. 1 이상 50 이하","required":false,"schema":{"type":"integer","format":"int32","default":20},"example":20}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/PlaceSearchResponse"}}}},"400":{"description":"요청 값이 올바르지 않다. 가능한 code: INVALID_SCHEDULE_CONDITION, INVALID_SCHEDULE_PREVIEW_REQUEST, FIXED_BASE_LOCATION_REQUIRED, PER_NIGHT_LOCATION_MISSING, MUST_VISIT_PLACE_LIMIT_EXCEEDED, INVALID_EXTERNAL_PLACE, INVALID_PLACE_SEARCH_REQUEST, MALFORMED_REQUEST, IDEMPOTENCY_KEY_REQUIRED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"서버가 처리하지 못한 예외. 응답에 내부 메시지를 담지 않으며 원인은 같은 traceId로 서버 로그에 남는다. 가능한 code: INTERNAL_ERROR","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/places/{placeId}":{"get":{"tags":["장소"],"summary":"장소 상세 조회","operationId":"getDetail","parameters":[{"name":"placeId","in":"path","description":"장소 검색 응답의 ID","required":true,"schema":{"type":"integer","format":"int64"},"example":1}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/PlaceDetailResponse"}}}},"400":{"description":"요청 값이 올바르지 않다. 가능한 code: INVALID_SCHEDULE_CONDITION, INVALID_SCHEDULE_PREVIEW_REQUEST, FIXED_BASE_LOCATION_REQUIRED, PER_NIGHT_LOCATION_MISSING, MUST_VISIT_PLACE_LIMIT_EXCEEDED, INVALID_EXTERNAL_PLACE, INVALID_PLACE_SEARCH_REQUEST, MALFORMED_REQUEST, IDEMPOTENCY_KEY_REQUIRED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"대상을 찾을 수 없다. 가능한 code: RESOURCE_NOT_FOUND, SCHEDULE_PREVIEW_NOT_FOUND, SCHEDULE_NOT_FOUND, PLACE_NOT_FOUND, SHARE_LINK_NOT_FOUND","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"서버가 처리하지 못한 예외. 응답에 내부 메시지를 담지 않으며 원인은 같은 traceId로 서버 로그에 남는다. 가능한 code: INTERNAL_ERROR","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/places/{placeId}/nearby-facilities":{"get":{"tags":["주변 편의시설"],"summary":"주변 편의시설 검색","operationId":"search_1","parameters":[{"name":"placeId","in":"path","description":"장소 검색 응답의 ID","required":true,"schema":{"type":"integer","format":"int64"},"example":1},{"name":"types","in":"query","description":"현재 지원값: CONVENIENCE_STORE","required":true,"schema":{"type":"string","minLength":1},"example":"CONVENIENCE_STORE"},{"name":"radius","in":"query","required":false,"schema":{"type":"integer","format":"int32","default":1000,"minimum":1},"example":1000}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/NearbyFacilityResponse"}}}},"400":{"description":"요청 값이 올바르지 않다. 가능한 code: INVALID_SCHEDULE_CONDITION, INVALID_SCHEDULE_PREVIEW_REQUEST, FIXED_BASE_LOCATION_REQUIRED, PER_NIGHT_LOCATION_MISSING, MUST_VISIT_PLACE_LIMIT_EXCEEDED, INVALID_EXTERNAL_PLACE, INVALID_PLACE_SEARCH_REQUEST, MALFORMED_REQUEST, IDEMPOTENCY_KEY_REQUIRED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"대상을 찾을 수 없다. 가능한 code: RESOURCE_NOT_FOUND, SCHEDULE_PREVIEW_NOT_FOUND, SCHEDULE_NOT_FOUND, PLACE_NOT_FOUND, SHARE_LINK_NOT_FOUND","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"서버가 처리하지 못한 예외. 응답에 내부 메시지를 담지 않으며 원인은 같은 traceId로 서버 로그에 남는다. 가능한 code: INTERNAL_ERROR","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/locations/search":{"get":{"tags":["출발지·도착지"],"summary":"출발지·도착지 검색","operationId":"search_2","parameters":[{"name":"keyword","in":"query","required":true,"schema":{"type":"string","minLength":1},"example":"부산역"},{"name":"size","in":"query","description":"최대 결과 수. 출발지 검색 화면은 10을 쓴다.","required":false,"schema":{"type":"integer","format":"int32","default":10,"minimum":1},"example":10}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/LocationSearchResponse"}}}},"400":{"description":"요청 값이 올바르지 않다. 가능한 code: INVALID_SCHEDULE_CONDITION, INVALID_SCHEDULE_PREVIEW_REQUEST, FIXED_BASE_LOCATION_REQUIRED, PER_NIGHT_LOCATION_MISSING, MUST_VISIT_PLACE_LIMIT_EXCEEDED, INVALID_EXTERNAL_PLACE, INVALID_PLACE_SEARCH_REQUEST, MALFORMED_REQUEST, IDEMPOTENCY_KEY_REQUIRED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"서버가 처리하지 못한 예외. 응답에 내부 메시지를 담지 않으며 원인은 같은 traceId로 서버 로그에 남는다. 가능한 code: INTERNAL_ERROR","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/schedules/{scheduleId}/shares/{shareId}":{"delete":{"tags":["일정 공유"],"summary":"공유 링크 폐기","operationId":"revoke","parameters":[{"name":"scheduleId","in":"path","description":"일정 ID","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"shareId","in":"path","description":"공유 링크 ID","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"204":{"description":"No Content"},"400":{"description":"요청 값이 올바르지 않다. 가능한 code: INVALID_SCHEDULE_CONDITION, INVALID_SCHEDULE_PREVIEW_REQUEST, FIXED_BASE_LOCATION_REQUIRED, PER_NIGHT_LOCATION_MISSING, MUST_VISIT_PLACE_LIMIT_EXCEEDED, INVALID_EXTERNAL_PLACE, INVALID_PLACE_SEARCH_REQUEST, MALFORMED_REQUEST, IDEMPOTENCY_KEY_REQUIRED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"대상을 찾을 수 없다. 가능한 code: RESOURCE_NOT_FOUND, SCHEDULE_PREVIEW_NOT_FOUND, SCHEDULE_NOT_FOUND, PLACE_NOT_FOUND, SHARE_LINK_NOT_FOUND","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"서버가 처리하지 못한 예외. 응답에 내부 메시지를 담지 않으며 원인은 같은 traceId로 서버 로그에 남는다. 가능한 code: INTERNAL_ERROR","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}}},"components":{"schemas":{"SchedulePreviewScheduleRequest":{"type":"object","properties":{"previewId":{"type":"string","format":"uuid"}},"required":["previewId"]},"Day":{"type":"object","properties":{"dayNo":{"type":"integer","format":"int32"},"date":{"type":"string","format":"date"},"startTime":{"type":"string"},"endTime":{"type":"string"},"startLocation":{"$ref":"#/components/schemas/DayLocation"},"endLocation":{"$ref":"#/components/schemas/DayLocation"},"startLocationSource":{"type":"string"},"endLocationSource":{"type":"string"},"summary":{"type":"string"},"stops":{"type":"array","items":{"$ref":"#/components/schemas/Stop"}},"finalTransit":{"$ref":"#/components/schemas/Transit"}}},"DayLocation":{"type":"object","properties":{"name":{"type":"string"},"longitude":{"type":"number"},"latitude":{"type":"number"}}},"HardGate":{"type":"object","properties":{"passed":{"type":"boolean"},"violations":{"type":"array","items":{"type":"string"}}}},"LongTransitWarning":{"type":"object","properties":{"dayNo":{"type":"integer","format":"int32"},"routeOrder":{"type":"integer","format":"int32"},"originName":{"type":"string"},"destinationName":{"type":"string"},"totalMinutes":{"type":"integer","format":"int32"}}},"Metric":{"type":"object","properties":{"id":{"type":"string"},"label":{"type":"string"},"score":{"type":"integer","format":"int32"},"maxScore":{"type":"integer","format":"int32"},"reason":{"type":"string"},"status":{"type":"string"}}},"OperatingInfo":{"type":"object","properties":{"openingHoursText":{"type":"string"},"closedDaysText":{"type":"string"},"requiresManualCheck":{"type":"boolean"}}},"Operations":{"type":"object","properties":{"generationMillis":{"type":"integer","format":"int64"},"planningMode":{"type":"string"},"aiPlanConfidence":{"type":"integer","format":"int32"},"multiDayPlanCandidateCount":{"type":"integer","format":"int32"},"multiDayPlanRerankedCount":{"type":"integer","format":"int32"},"routeEstimateResolutionCount":{"type":"integer","format":"int32"},"routeEstimateCacheHitCount":{"type":"integer","format":"int32"},"providerEstimateCallCount":{"type":"integer","format":"int32"},"providerEstimateFailureCount":{"type":"integer","format":"int32"},"routeResolutionCount":{"type":"integer","format":"int32"},"routeCacheHitCount":{"type":"integer","format":"int32"},"providerCallCount":{"type":"integer","format":"int32"},"providerFailureCount":{"type":"integer","format":"int32"},"externalHttpCallCount":{"type":"integer","format":"int32"},"externalHttpFailureCount":{"type":"integer","format":"int32"},"odsayPathSearchCount":{"type":"integer","format":"int32"},"odsayLoadLaneCount":{"type":"integer","format":"int32"},"tmapWalkingCount":{"type":"integer","format":"int32"},"routeCount":{"type":"integer","format":"int32"},"fallbackRouteCount":{"type":"integer","format":"int32"},"geometryFallbackLineCount":{"type":"integer","format":"int32"},"totalTransitMinutes":{"type":"integer","format":"int32"},"totalWalkMinutes":{"type":"integer","format":"int32"},"totalTransferCount":{"type":"integer","format":"int32"},"providers":{"type":"array","items":{"type":"string"}}}},"PlanningAssumptions":{"type":"object","properties":{"timeZone":{"type":"string"},"lodgingMode":{"type":"string"},"routeCoverage":{"type":"string"},"warnings":{"type":"array","items":{"type":"string"}}}},"QualityScore":{"type":"object","properties":{"totalScore":{"type":"integer","format":"int32"},"maxScore":{"type":"integer","format":"int32"},"evaluationCoveragePercent":{"type":"integer","format":"int32"},"unusedMinutes":{"type":"integer","format":"int32"},"longTransitWarnings":{"type":"array","items":{"$ref":"#/components/schemas/LongTransitWarning"}},"routeConfidence":{"type":"string"},"metrics":{"type":"array","items":{"$ref":"#/components/schemas/Metric"}}}},"ScheduleEvaluationReport":{"type":"object","properties":{"hardGate":{"$ref":"#/components/schemas/HardGate"},"qualityScore":{"$ref":"#/components/schemas/QualityScore"},"operations":{"$ref":"#/components/schemas/Operations"}}},"ScheduleResponse":{"type":"object","properties":{"id":{"type":"string","format":"uuid","example":"f2536c52-69d1-4e6c-8ab6-2ede45dba2cd"},"status":{"type":"string","enum":["DRAFT","CONFIRMED"],"example":"CONFIRMED"},"startDate":{"type":"string","format":"date","example":"2026-09-20"},"endDate":{"type":"string","format":"date","example":"2026-09-21"},"dailyStartTime":{"type":"string"},"dailyEndTime":{"type":"string"},"styleSummary":{"type":"string","description":"선택한 답변을 요약한 문구","example":"친구와 함께하는 여유로운 자연 중심 일정"},"days":{"type":"array","description":"일차별 방문지와 이동. 목록 조회에서는 반환하지 않는다.","items":{"$ref":"#/components/schemas/Day"}},"evaluation":{"$ref":"#/components/schemas/ScheduleEvaluationReport"},"previewId":{"type":"string","format":"uuid"},"planningAssumptions":{"$ref":"#/components/schemas/PlanningAssumptions"}}},"Segment":{"type":"object","properties":{"order":{"type":"integer","format":"int32"},"mode":{"type":"string"},"lineName":{"type":"string"},"startStationId":{"type":"string"},"startStationName":{"type":"string"},"endStationId":{"type":"string"},"endStationName":{"type":"string"},"instruction":{"type":"string"},"durationMinutes":{"type":"integer","format":"int32"},"distanceMeters":{"type":"integer","format":"int32"},"stationCount":{"type":"integer","format":"int32"},"waitMinutes":{"type":"integer","format":"int32"},"realtimeStatus":{"type":"string"}}},"Stop":{"type":"object","properties":{"stopId":{"type":"string","format":"uuid"},"placeId":{"type":"integer","format":"int64"},"dayNo":{"type":"integer","format":"int32"},"order":{"type":"integer","format":"int32"},"stayMinutes":{"type":"integer","format":"int32","minimum":30},"referenceValid":{"type":"boolean"}}},"Transit":{"type":"object","properties":{"routeType":{"type":"string"},"routeOrder":{"type":"integer","format":"int32"},"originName":{"type":"string"},"destinationName":{"type":"string"},"summary":{"type":"string"},"departAt":{"type":"string"},"arriveAt":{"type":"string"},"totalMinutes":{"type":"integer","format":"int32"},"walkMinutes":{"type":"integer","format":"int32"},"waitMinutes":{"type":"integer","format":"int32"},"transferCount":{"type":"integer","format":"int32"},"fareAmount":{"type":"integer","format":"int32"},"provider":{"type":"string"},"realtimeStatus":{"type":"string"},"fallbackUsed":{"type":"boolean"},"segments":{"type":"array","items":{"$ref":"#/components/schemas/Segment"}},"warnings":{"type":"array","items":{"type":"string"}}}},"ShareLinkCreateRequest":{"type":"object","properties":{"expiresInDays":{"type":"integer","format":"int32","description":"공유 링크 유효기간(일)","example":7,"maximum":365}}},"ShareLinkResponse":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"token":{"type":"string"},"url":{"type":"string"},"expiresAt":{"type":"string","format":"date-time"}}},"DayOverride":{"type":"object","properties":{"date":{"type":"string","format":"date"},"availableFrom":{"type":"string"},"availableUntil":{"type":"string"},"startLocation":{"$ref":"#/components/schemas/Location"},"endLocation":{"$ref":"#/components/schemas/Location"}},"required":["date"]},"EndConstraint":{"type":"object","properties":{"type":{"type":"string","minLength":1},"location":{"$ref":"#/components/schemas/Location"},"targetAt":{"type":"string","minLength":1},"bufferMinutes":{"type":"integer","format":"int32"}},"required":["location","targetAt","type"]},"FixedEvent":{"type":"object","properties":{"clientEventId":{"type":"string","minLength":1},"name":{"type":"string","minLength":1},"placeId":{"type":"integer","format":"int64"},"startsAt":{"type":"string","minLength":1},"endsAt":{"type":"string","minLength":1}},"required":["clientEventId","endsAt","name","placeId","startsAt"]},"Location":{"type":"object","properties":{"name":{"type":"string","description":"장소명","example":"부산역","minLength":1},"address":{"type":"string","description":"주소","example":"부산 동구 중앙대로 206"},"longitude":{"type":"number","description":"경도. WGS84","example":129.0403},"latitude":{"type":"number","description":"위도. WGS84","example":35.1151}},"required":["latitude","longitude","name"]},"LodgingPlan":{"type":"object","properties":{"mode":{"type":"string","minLength":1},"baseLocation":{"$ref":"#/components/schemas/Location"},"nightStays":{"type":"array","items":{"$ref":"#/components/schemas/NightStay"}}},"required":["mode"]},"NightStay":{"type":"object","properties":{"date":{"type":"string","format":"date"},"location":{"$ref":"#/components/schemas/Location"}},"required":["date","location"]},"SchedulePreviewCreateRequest":{"type":"object","properties":{"startDate":{"type":"string","format":"date","description":"여행 시작일","example":"2026-09-20"},"endDate":{"type":"string","format":"date","description":"여행 종료일. 시작일 포함 최대 4일","example":"2026-09-21"},"startLocation":{"$ref":"#/components/schemas/Location"},"startTime":{"type":"string","description":"첫날 출발 시각. 생략하면 기본값을 적용하고 응답의 appliedDefaults로 알린다.","example":"10:00"},"lodgingPlan":{"$ref":"#/components/schemas/LodgingPlan"},"endConstraint":{"$ref":"#/components/schemas/EndConstraint"},"selectedAnswers":{"type":"array","items":{"$ref":"#/components/schemas/SelectedAnswer"},"minItems":1},"mustVisitPlaceIds":{"type":"array","description":"반드시 방문할 장소의 내부 ID. 외부 검색 결과는 먼저 POST /api/v1/places/resolve 로 내부 ID를 받아야 한다.","example":[],"items":{"type":"integer","format":"int64"}},"fixedEvents":{"type":"array","items":{"$ref":"#/components/schemas/FixedEvent"}},"dayOverrides":{"type":"array","items":{"$ref":"#/components/schemas/DayOverride"}},"customPrompt":{"type":"string","description":"자유 요청. 최대 500자","example":"바다를 많이 보고 걷는 구간은 적었으면 좋겠어요","maxLength":500,"minLength":0},"timeZone":{"type":"string","description":"생략하면 Asia/Seoul","example":"Asia/Seoul"}},"required":["endDate","lodgingPlan","selectedAnswers","startDate","startLocation"]},"SelectedAnswer":{"type":"object","properties":{"questionId":{"type":"string","minLength":1},"answerIds":{"type":"array","items":{"type":"string","minLength":1},"minItems":1}},"required":["answerIds","questionId"]},"AppliedDefault":{"type":"object","properties":{"fieldPath":{"type":"string"},"resolvedValue":{},"reasonCode":{"type":"string"}}},"Conflict":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"fieldPath":{"type":"string"},"conflictDate":{"type":"string","format":"date"},"requiredMinutes":{"type":"integer","format":"int32"},"availableMinutes":{"type":"integer","format":"int32"},"adjustableFields":{"type":"array","items":{"type":"string"}}}},"InterpretedPrompt":{"type":"object","properties":{"preferences":{"type":"array","items":{"type":"string"}},"unrecognizedTexts":{"type":"array","items":{"type":"string"}},"source":{"type":"string"},"confidence":{"type":"integer","format":"int32"}}},"ResolvedDay":{"type":"object","properties":{"date":{"type":"string","format":"date"},"availableFrom":{"type":"string"},"availableUntil":{"type":"string"},"startLocation":{"$ref":"#/components/schemas/Location"},"endLocation":{"$ref":"#/components/schemas/Location"},"startLocationSource":{"type":"string"},"endLocationSource":{"type":"string"}}},"ResolvedEndConstraint":{"type":"object","properties":{"type":{"type":"string"},"targetAt":{"type":"string"},"appliedBufferMinutes":{"type":"integer","format":"int32"},"availableUntil":{"type":"string"}}},"SchedulePreviewResponse":{"type":"object","properties":{"previewId":{"type":"string","format":"uuid","description":"일정 생성 요청에 그대로 전달한다.","example":"6afa151a-3fb2-4f3d-821f-53228b88d1c0"},"status":{"type":"string","description":"READY 면 그대로 생성할 수 있고, REQUIRES_ACTION 이면 conflicts 를 해결해야 한다.","enum":["READY","REQUIRES_ACTION","CONSUMED","EXPIRED"],"example":"READY"},"canGenerate":{"type":"boolean","description":"이 Preview 로 바로 일정을 만들 수 있는지","example":true},"expiresAt":{"type":"string","format":"date-time","description":"만료 시각. 생성 후 30분","example":"2026-09-20T01:30:00Z"},"timeZone":{"type":"string","example":"Asia/Seoul"},"lodgingMode":{"type":"string","enum":["UNDECIDED","FIXED","PER_NIGHT"],"example":"UNDECIDED"},"routeCoverage":{"type":"string","description":"실제 경로를 어디까지 계산했는지","example":"ATTRACTION_ROUTES_ONLY"},"resolvedDays":{"type":"array","items":{"$ref":"#/components/schemas/ResolvedDay"}},"resolvedEndConstraint":{"$ref":"#/components/schemas/ResolvedEndConstraint"},"appliedDefaults":{"type":"array","items":{"$ref":"#/components/schemas/AppliedDefault"}},"interpretedPrompt":{"$ref":"#/components/schemas/InterpretedPrompt"},"warnings":{"type":"array","items":{"$ref":"#/components/schemas/Warning"}},"conflicts":{"type":"array","items":{"$ref":"#/components/schemas/Conflict"}},"scheduleId":{"type":"string","format":"uuid"}}},"Warning":{"type":"object","properties":{"code":{"type":"string"},"date":{"type":"string","format":"date"},"message":{"type":"string"}}},"PlaceResolveRequest":{"type":"object","description":"외부 검색으로 고른 장소를 내부 ID로 확정한다. 같은 (source, externalId)는 upsert 된다.","properties":{"source":{"type":"string","description":"외부 제공자","enum":["NAVER_LOCAL","KAKAO_LOCAL"],"example":"NAVER_LOCAL","minLength":1},"externalId":{"type":"string","description":"제공자의 장소 ID. 네이버는 안정적인 ID가 없어 mapx-mapy 합성 키를 쓴다.","example":"1291598546-351585232","minLength":1},"name":{"type":"string","description":"장소명","example":"해운대 해수욕장","minLength":1},"category":{"type":"string","description":"제공자의 카테고리 문자열. TourAPI 콘텐츠 유형 추정에 쓴다.","example":"여행,명소>관광,명소>해수욕장"},"address":{"type":"string","description":"주소","example":"부산 해운대구 우동"},"longitude":{"type":"number","description":"경도. WGS84. 네이버 mapx는 10000000으로 나눈 값을 보낸다.","example":129.1598546},"latitude":{"type":"number","description":"위도. WGS84","example":35.1585232},"placeUrl":{"type":"string","description":"제공자의 장소 페이지 링크. 장소 상세에서 외부 지도로 연결할 때 쓴다.","example":"https://map.naver.com/p/entry/place/1234567"}},"required":["externalId","latitude","longitude","name","source"]},"PlaceResolveResponse":{"type":"object","properties":{"placeId":{"type":"integer","format":"int64"},"source":{"type":"string"},"externalId":{"type":"string"},"name":{"type":"string"},"category":{"type":"string"},"categoryLabel":{"type":"string"},"address":{"type":"string"},"longitude":{"type":"number"},"latitude":{"type":"number"},"primaryImageUrl":{"type":"string"},"placeUrl":{"type":"string"},"resolved":{"type":"boolean"},"operatingInfoAvailable":{"type":"boolean"}}},"ScheduleUpdateRequest":{"type":"object","properties":{"stops":{"type":"array","items":{"$ref":"#/components/schemas/Stop"},"minItems":1}},"required":["stops"]},"AnswerResponse":{"type":"object","properties":{"id":{"type":"string"},"label":{"type":"string"},"displayOrder":{"type":"integer","format":"int32"}}},"QuestionResponse":{"type":"object","properties":{"id":{"type":"string"},"text":{"type":"string"},"type":{"type":"string"},"required":{"type":"boolean"},"minSelections":{"type":"integer","format":"int32"},"maxSelections":{"type":"integer","format":"int32"},"uiStep":{"type":"integer","format":"int32"},"displayOrder":{"type":"integer","format":"int32"},"answers":{"type":"array","items":{"$ref":"#/components/schemas/AnswerResponse"}}}},"TripQuestionsResponse":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/QuestionResponse"}}}},"SharedScheduleResponse":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"status":{"type":"string"},"readOnly":{"type":"boolean"},"startDate":{"type":"string","format":"date"},"endDate":{"type":"string","format":"date"},"dailyStartTime":{"type":"string"},"dailyEndTime":{"type":"string"},"styleSummary":{"type":"string"},"days":{"type":"array","items":{"$ref":"#/components/schemas/Day"}}}},"Marker":{"type":"object","properties":{"name":{"type":"string"},"longitude":{"type":"number"},"latitude":{"type":"number"}}},"RouteLine":{"type":"object","properties":{"dayNo":{"type":"integer","format":"int32"},"routeOrder":{"type":"integer","format":"int32"},"lineOrder":{"type":"integer","format":"int32"},"mode":{"type":"string"},"lineName":{"type":"string"},"startName":{"type":"string"},"endName":{"type":"string"},"durationMinutes":{"type":"integer","format":"int32"},"distanceMeters":{"type":"integer","format":"int32"},"instruction":{"type":"string"},"fallbackUsed":{"type":"boolean"},"coordinates":{"type":"array","items":{"type":"array","items":{"type":"number"}}}}},"ScheduleMapResponse":{"type":"object","properties":{"startMarker":{"$ref":"#/components/schemas/Marker"},"endMarker":{"$ref":"#/components/schemas/Marker"},"markers":{"type":"array","items":{"$ref":"#/components/schemas/StopMarker"}},"routeLines":{"type":"array","items":{"$ref":"#/components/schemas/RouteLine"}}}},"StopMarker":{"type":"object","properties":{"dayNo":{"type":"integer","format":"int32"},"order":{"type":"integer","format":"int32"},"placeId":{"type":"integer","format":"int64"},"name":{"type":"string"},"arriveAt":{"type":"string"},"departAt":{"type":"string"},"subtitle":{"type":"string"},"riskLevel":{"type":"string"},"longitude":{"type":"number"},"latitude":{"type":"number"}}},"ScheduleSummaryListResponse":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/ScheduleSummaryResponse"}}}},"ScheduleSummaryResponse":{"type":"object","properties":{"id":{"type":"string","format":"uuid","example":"f2536c52-69d1-4e6c-8ab6-2ede45dba2cd"},"status":{"type":"string","example":"CONFIRMED"},"startDate":{"type":"string","format":"date","example":"2026-09-20"},"endDate":{"type":"string","format":"date","example":"2026-09-21"},"styleSummary":{"type":"string","example":"친구와 함께하는 여유로운 자연 중심 일정"},"dayCount":{"type":"integer","format":"int32","description":"총 일차 수","example":2},"stopCount":{"type":"integer","format":"int32","description":"전체 방문지 수","example":6},"previewPlaceNames":{"type":"array","description":"카드 미리보기용 장소 이름. 방문 순서대로 최대 3개, 중복 제거","example":["부산역","감천문화마을","자갈치시장"],"items":{"type":"string"}}}},"Item":{"type":"object","properties":{"placeId":{"type":"integer","format":"int64"},"source":{"type":"string"},"externalId":{"type":"string"},"name":{"type":"string"},"category":{"type":"string"},"categoryLabel":{"type":"string"},"address":{"type":"string"},"longitude":{"type":"number"},"latitude":{"type":"number"},"distanceMeters":{"type":"integer","format":"int32"},"primaryImageUrl":{"type":"string"},"placeUrl":{"type":"string"},"resolved":{"type":"boolean"},"id":{"type":"integer","format":"int64"},"externalContentId":{"type":"string"}}},"PlaceSearchResponse":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/Item"}}}},"Image":{"type":"object","properties":{"url":{"type":"string"},"thumbnailUrl":{"type":"string"},"copyrightType":{"type":"string"}}},"PlaceDetailResponse":{"type":"object","properties":{"id":{"type":"integer","format":"int64"},"source":{"type":"string","description":"장소 출처","enum":["TOUR_API","NAVER_LOCAL","KAKAO_LOCAL"],"example":"NAVER_LOCAL"},"externalContentId":{"type":"string"},"contentTypeId":{"type":"string"},"name":{"type":"string"},"category":{"type":"string"},"categoryLabel":{"type":"string","description":"화면 표시용 카테고리 라벨","example":"음식점"},"address":{"type":"string"},"longitude":{"type":"number"},"latitude":{"type":"number"},"placeUrl":{"type":"string","description":"외부 제공자의 장소 페이지 링크. 축약 상세 화면에서 더 보기 대상으로 쓴다.","example":"https://map.naver.com/p/entry/place/1234567"},"primaryImageUrl":{"type":"string"},"overview":{"type":"string"},"operatingInfo":{"$ref":"#/components/schemas/OperatingInfo"},"images":{"type":"array","items":{"$ref":"#/components/schemas/Image"}}}},"NearbyFacilityResponse":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/Item"}}}},"LocationSearchResponse":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/Item"}}}},"ErrorResponse":{"description":"모든 실패 응답이 공통으로 쓰는 형태. 클라이언트는 HTTP 상태가 아니라 code로 분기해도 된다.","properties":{"code":{"type":"string","description":"오류 코드. 상태별 가능한 값은 각 오퍼레이션의 응답 설명에 있다.","example":"INVALID_PLACE_SEARCH_REQUEST"},"message":{"type":"string","description":"사용자에게 보여줄 수 있는 한국어 메시지","example":"장소 검색 조건이 올바르지 않습니다."},"fieldErrors":{"type":"array","description":"원인을 필드 단위로 좁힐 수 있을 때 채운다. 좁힐 수 없으면 빈 배열이다.","items":{"$ref":"#/components/schemas/FieldErrorResponse"}},"traceId":{"type":"string","description":"요청 추적 ID. 응답 헤더 X-Trace-Id와 같은 값이며 서버 로그와 연결된다.","example":"0ebd1950-190c-444a-aa15-bf6b533686e7"},"scheduleId":{"type":"string","format":"uuid"}}},"FieldErrorResponse":{"description":"원인을 필드 단위로 좁힐 수 있을 때 채운다. 좁힐 수 없으면 빈 배열이다.","properties":{"field":{"type":"string","description":"문제가 된 위치. 요청 본문은 JSON 경로, 그 외는 파라미터·헤더 이름","example":"size"},"message":{"type":"string","description":"사유","example":"1 이상 50 이하여야 합니다. 요청 값: 1000"}}}}}}