{"openapi":"3.0.1","info":{"title":"멜리사 Server API","description":"멜리사 Spring Server API 명세서","version":"1.3.0"},"servers":[{"url":"/"}],"security":[{"JWT TOKEN":[]}],"tags":[{"name":"UserMemoryAPI","description":"사용자 메모리 관리 API"},{"name":"TermAPI","description":"약관 동의 API"},{"name":"StreakAPI","description":"Streak 관련 API"},{"name":"AuthAPI","description":"Auth 관련 API"},{"name":"Diary API","description":"[v1.3.0] 일기 관리 API"},{"name":"PaymentAdminAPI","description":"결제 관리자 fallback API"},{"name":"PaymentAPI","description":"인앱결제 검증 및 구매 복원 API"},{"name":"Thread&ChatsAPI","description":"Thread&Chats 관리 API"},{"name":"ExpoPushTokenAPI","description":"Expo Push Token 관리 API"},{"name":"UserSettingAPI","description":"유저 셋팅관련 API"},{"name":"AiProfileAPI","description":"AI 프로필 관련 API (전역 공유 리소스)"},{"name":"CalendarAPI","description":"Calendar 관련 API"},{"name":"UserAPI","description":"유저 관련 API"}],"paths":{"/api/v1/user-settings":{"get":{"tags":["UserSettingAPI"],"summary":"유저 설정 조회","description":"현재 로그인한 사용자의 설정 정보를 조회합니다.","operationId":"getUserSetting","responses":{"404":{"description":"AUTH4006: 유저 없음 / SETTING4001: 설정 없음","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseUserSettingResponse"}}}},"200":{"description":"성공","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseUserSettingResponse"}}}},"401":{"description":"인증 실패(토큰 누락/만료/위조)","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseUserSettingResponse"}}}}}},"put":{"tags":["UserSettingAPI"],"summary":"유저 설정 수정","description":"현재 로그인한 사용자의 설정 정보를 수정합니다.","operationId":"updateUserSetting","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserSettingRequest"}}},"required":true},"responses":{"404":{"description":"AUTH4006: 유저 없음 / SETTING4001: 설정 없음","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseUserSettingResponse"}}}},"200":{"description":"성공","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseUserSettingResponse"}}}},"401":{"description":"인증 실패(토큰 누락/만료/위조)","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseUserSettingResponse"}}}},"400":{"description":"SETTING4003: 유효하지 않은 시간 형식","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseUserSettingResponse"}}}}}}},"/api/v1/diaries/{diaryId}":{"put":{"tags":["Diary API"],"summary":"일기 수정","description":"[v1.3.0] 일기를 수정합니다. null이 아닌 필드만 업데이트됩니다.","operationId":"updateDiary","parameters":[{"name":"diaryId","in":"path","description":"일기 ID","required":true,"schema":{"type":"integer","format":"int64"},"example":1}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DiaryUpdateRequest"}}},"required":true},"responses":{"404":{"description":"AUTH4006: 사용자를 찾을 수 없음 / DIARY4001: 일기를 찾을 수 없음","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseDiaryResponse"}}}},"200":{"description":"성공","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseDiaryResponse"}}}},"400":{"description":"DIARY4003: 이미 삭제된 일기","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseDiaryResponse"}}}},"429":{"description":"QUOTA4001: 일일 사용량 초과 (이미지 재생성 시)","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseDiaryResponse"}}}},"403":{"description":"DIARY4002: 일기에 접근할 권한이 없음","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseDiaryResponse"}}}}}},"delete":{"tags":["Diary API"],"summary":"일기 삭제","description":"[v1.3.0] 일기를 삭제합니다. (소프트 삭제 - isActive = false)","operationId":"deleteDiary","parameters":[{"name":"diaryId","in":"path","description":"일기 ID","required":true,"schema":{"type":"integer","format":"int64"},"example":1}],"responses":{"404":{"description":"AUTH4006: 사용자를 찾을 수 없음 / DIARY4001: 일기를 찾을 수 없음","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseDiaryDeleteResponse"}}}},"200":{"description":"성공","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseDiaryDeleteResponse"}}}},"400":{"description":"DIARY4003: 이미 삭제된 일기","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseDiaryDeleteResponse"}}}},"403":{"description":"DIARY4002: 일기에 접근할 권한이 없음","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseDiaryDeleteResponse"}}}}}}},"/api/v2/chats/message":{"post":{"tags":["Thread&ChatsAPI"],"summary":"메모리 기반 SSE 채팅","description":"사용자 메모리를 포함한 AI 채팅입니다.","operationId":"messageToAiV2","parameters":[{"name":"Idempotency-Key","in":"header","required":false,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AiChatRequestV2"}}},"required":true},"responses":{"200":{"description":"OK","content":{"text/event-stream":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ServerSentEventString"}}}}}}}},"/api/v2/chats/message-test":{"post":{"tags":["Thread&ChatsAPI"],"summary":"메모리 기반 테스트 채팅","description":"SSE 없이 일반 HTTP 응답으로 메모리 기반 AI 채팅을 수행합니다.","operationId":"messageToAiTest","parameters":[{"name":"Idempotency-Key","in":"header","required":false,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AiChatRequestV2"}}},"required":true},"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseChatResponse"}}}}}}},"/api/v1/user-settings/register":{"post":{"tags":["UserSettingAPI"],"summary":"유저 설정 기본값 등록(멱등)","description":"현재 로그인한 사용자의 설정 정보를 기본값으로 등록합니다.\n- 이미 설정이 존재하면 아무 동작 없이 성공 응답을 반환합니다(멱등).\n","operationId":"createDefaultUserSetting","responses":{"200":{"description":"성공","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseVoid"}}}},"404":{"description":"AUTH4006: 유저 없음","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseVoid"}}}},"401":{"description":"인증 실패(토큰 누락/만료/위조)","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseVoid"}}}}}}},"/api/v1/terms/agreements":{"post":{"tags":["TermAPI"],"summary":"약관 동의 제출","description":"현재 로그인한 사용자의 약관 동의/거절 결정을 저장합니다.\n- 인증 필요 (Bearer JWT)\n- 필수 약관은 반드시 true로 제출해야 합니다.\n- 선택 약관은 false 제출이 가능하며 이력으로 저장됩니다.\n- `context` 후보: SIGNUP, RECONSENT, OPTIONAL_UPDATE, WITHDRAWAL\n- `termVersionId`는 agreement-status 또는 agreement-screen의 `terms[].currentTermVersionId` 값을 사용합니다.\n- 필수 약관 누락 또는 필수 약관 `agreed=false` 제출 시 400으로 응답합니다.\n","operationId":"submitAgreements","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubmitAgreementsRequest"}}},"required":true},"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseSubmitAgreementsResponse"}}}}}}},"/api/v1/payments/google/verify":{"post":{"tags":["PaymentAPI"],"summary":"Google Play 광고 제거 구매 검증","description":"Google Play Billing에서 받은 비소모성 상품 구매 정보를 서버에서 검증하고 광고 제거 권한을 부여합니다.\n- 인증 필요 (Bearer JWT)\n- userId는 토큰(subject) 기반으로 서버에서 결정\n- 요청 productId는 Google Play 상품 ID인 `premium`\n- 검증 성공 시 응답의 `entitlement.active=true`로 광고 제거 적용 가능\n- 같은 구매를 같은 사용자가 다시 검증하면 `alreadyProcessed=true`로 응답\n","operationId":"verifyGoogle","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GoogleVerifyRequest"}}},"required":true},"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseVerifyResponse"}}}}}}},"/api/v1/payments/google/restore":{"post":{"tags":["PaymentAPI"],"summary":"Google Play 광고 제거 구매 복원","description":"Google Play Billing에서 조회한 보유 구매 목록을 서버에 다시 검증하여 광고 제거 권한을 복원합니다.\n- 인증 필요 (Bearer JWT)\n- userId는 토큰(subject) 기반으로 서버에서 결정\n- 일부 구매 검증 실패가 있어도 API 자체는 성공할 수 있으며 실패 항목은 `failed`에 포함\n- 최종 광고 제거 여부는 `features.adRemoved` 값으로 판단\n","operationId":"restoreGoogle","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GoogleRestoreRequest"}}},"required":true},"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseRestoreResponse"}}}}}}},"/api/v1/payments/apple/verify":{"post":{"tags":["PaymentAPI"],"summary":"Apple App Store 광고 제거 구매 검증","description":"App Store에서 받은 비소모성 상품 transactionId를 서버에서 검증하고 광고 제거 권한을 부여합니다.\n- 인증 필요 (Bearer JWT)\n- userId는 토큰(subject) 기반으로 서버에서 결정\n- 요청 productId는 Apple 상품 ID인 `com.melissa.melissaFE.premium`\n- environment는 테스트 결제 `SANDBOX`, 상용 결제 `PRODUCTION`\n- 검증 성공 시 응답의 `entitlement.active=true`로 광고 제거 적용 가능\n","operationId":"verifyApple","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppleVerifyRequest"}}},"required":true},"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseVerifyResponse"}}}}}}},"/api/v1/payments/apple/restore":{"post":{"tags":["PaymentAPI"],"summary":"Apple App Store 광고 제거 구매 복원","description":"App Store에서 조회한 보유 거래 목록을 서버에 다시 검증하여 광고 제거 권한을 복원합니다.\n- 인증 필요 (Bearer JWT)\n- userId는 토큰(subject) 기반으로 서버에서 결정\n- 일부 거래 검증 실패가 있어도 API 자체는 성공할 수 있으며 실패 항목은 `failed`에 포함\n- 최종 광고 제거 여부는 `features.adRemoved` 값으로 판단\n","operationId":"restoreApple","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppleRestoreRequest"}}},"required":true},"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseRestoreResponse"}}}}}}},"/api/v1/expo-push-tokens":{"get":{"tags":["ExpoPushTokenAPI"],"summary":"내 Expo Push Token 목록 조회","description":"현재 로그인한 사용자에게 연결된 Expo Push Token 목록을 반환합니다.\n- 인증 필요 (Bearer JWT)\n- `platform` 후보: ANDROID, IOS\n- `invalid=true`이면 발송 실패 등으로 무효 처리된 토큰입니다.\n","operationId":"getUserTokens","responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseListTokenResponse"}}}}}},"post":{"tags":["ExpoPushTokenAPI"],"summary":"Expo Push Token 등록/갱신","description":"현재 로그인한 사용자의 Expo Push Token을 등록하거나 기존 토큰 정보를 갱신합니다.\n- 인증 필요 (Bearer JWT)\n- userId는 토큰(subject) 기반으로 서버에서 결정\n- `platform` 후보: ANDROID, IOS\n- `expoPushToken` 형식: ExponentPushToken[...]\n- `Idempotency-Key` 헤더를 전달하면 같은 요청의 중복 처리를 방지합니다.\n","operationId":"registerToken","parameters":[{"name":"Idempotency-Key","in":"header","required":false,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RegisterTokenRequest"}}},"required":true},"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseTokenResponse"}}}}}}},"/api/v1/diaries/manual":{"post":{"tags":["Diary API"],"summary":"수동 일기 작성","description":"[v1.3.0] 사용자가 직접 작성한 일기를 저장합니다. 해시태그는 LLM이 자동 생성하며, 이미지는 DALL-E로 비동기 생성됩니다.","operationId":"createManualDiary","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ManualDiaryCreateRequest"}}},"required":true},"responses":{"500":{"description":"CALENDAR5001: LLM 응답 파싱 실패","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseDiaryResponse"}}}},"200":{"description":"성공","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseDiaryResponse"}}}},"429":{"description":"QUOTA4001: 일일 사용량 초과","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseDiaryResponse"}}}},"400":{"description":"CALENDAR4003: 유효하지 않은 날짜 / DIARY4004: 하루 최대 3개 일기 제한 초과","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseDiaryResponse"}}}},"404":{"description":"AUTH4006: 사용자를 찾을 수 없음 / PROFILE4002: AI 프로필을 찾을 수 없음","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseDiaryResponse"}}}}}}},"/api/v1/diaries/from-chat":{"post":{"tags":["Diary API"],"summary":"채팅 기반 일기 생성","description":"[v1.3.0] Thread의 채팅 로그를 LLM으로 요약하여 일기를 자동 생성합니다. 제목, 내용, 해시태그가 자동 생성됩니다.","operationId":"createChatDiary","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChatDiaryCreateRequest"}}},"required":true},"responses":{"500":{"description":"CALENDAR5001: LLM 응답 파싱 실패","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseDiaryResponse"}}}},"200":{"description":"성공","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseDiaryResponse"}}}},"429":{"description":"QUOTA4001: 일일 사용량 초과","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseDiaryResponse"}}}},"404":{"description":"AUTH4006: 사용자를 찾을 수 없음 / CALENDAR4001: Thread를 찾을 수 없음 / CHAT4001: 채팅 로그 부족 (2개 이하)","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseDiaryResponse"}}}},"400":{"description":"DIARY4004: 하루 최대 3개 일기 제한 초과","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseDiaryResponse"}}}}}}},"/api/v1/chats":{"get":{"tags":["Thread&ChatsAPI"],"summary":"채팅 메시지 조회","description":"해당 날짜 스레드의 채팅 메시지를 조회합니다.","operationId":"getMessages","parameters":[{"name":"aiProfileId","in":"query","description":"AI 프로필 ID","required":true,"schema":{"type":"integer","format":"int64"},"example":1},{"name":"year","in":"query","description":"연도","required":true,"schema":{"type":"integer","format":"int32"},"example":2025},{"name":"month","in":"query","description":"월","required":true,"schema":{"type":"integer","format":"int32"},"example":1},{"name":"day","in":"query","description":"일","required":true,"schema":{"type":"integer","format":"int32"},"example":15}],"responses":{"200":{"description":"성공","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseChatListResponse"}}}},"404":{"description":"AUTH4006: 사용자를 찾을 수 없음 / CALENDAR4001: 스레드를 찾을 수 없음","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseChatListResponse"}}}},"403":{"description":"CALENDAR4002: 스레드에 접근할 권한이 없음","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseChatListResponse"}}}}}},"post":{"tags":["Thread&ChatsAPI"],"summary":"채팅 스레드 생성","description":"해당 날짜의 채팅 스레드를 생성합니다. 기존 스레드가 있으면 같은 threadId를 반환합니다.","operationId":"createThread","parameters":[{"name":"aiProfileId","in":"query","description":"AI 프로필 ID","required":true,"schema":{"type":"integer","format":"int64"},"example":1},{"name":"year","in":"query","description":"연도","required":true,"schema":{"type":"integer","format":"int32"},"example":2025},{"name":"month","in":"query","description":"월","required":true,"schema":{"type":"integer","format":"int32"},"example":1},{"name":"day","in":"query","description":"일","required":true,"schema":{"type":"integer","format":"int32"},"example":15}],"responses":{"200":{"description":"성공","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseThreadResponse"}}}},"404":{"description":"AUTH4006: 사용자를 찾을 수 없음 / PROFILE4002: AI 프로필을 찾을 수 없음","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseThreadResponse"}}}},"400":{"description":"THREAD4001: 해당 날짜의 스레드가 이미 존재","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseThreadResponse"}}}}}},"delete":{"tags":["Thread&ChatsAPI"],"summary":"채팅 스레드 삭제","description":"해당 날짜의 스레드와 연결된 채팅 로그를 삭제합니다.","operationId":"deleteThread","parameters":[{"name":"aiProfileId","in":"query","description":"AI 프로필 ID","required":true,"schema":{"type":"integer","format":"int64"},"example":1},{"name":"year","in":"query","description":"연도","required":true,"schema":{"type":"integer","format":"int32"},"example":2025},{"name":"month","in":"query","description":"월","required":true,"schema":{"type":"integer","format":"int32"},"example":1},{"name":"day","in":"query","description":"일","required":true,"schema":{"type":"integer","format":"int32"},"example":15}],"responses":{"200":{"description":"성공","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseThreadResponse"}}}},"404":{"description":"AUTH4006: 사용자를 찾을 수 없음 / CALENDAR4001: 스레드를 찾을 수 없음","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseThreadResponse"}}}},"403":{"description":"CALENDAR4002: 스레드에 접근할 권한이 없음","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseThreadResponse"}}}}}}},"/api/v1/chats/message":{"post":{"tags":["Thread&ChatsAPI"],"summary":"AI 채팅 메시지 전송 (SSE)","description":"AI에게 채팅 메시지를 전송하고 SSE로 응답을 받습니다.","operationId":"messageToAi","parameters":[{"name":"Idempotency-Key","in":"header","required":false,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AiChatRequest"}}},"required":true},"responses":{"404":{"description":"AUTH4006: 사용자를 찾을 수 없음 / CALENDAR4001: 스레드를 찾을 수 없음 / PROFILE4002: AI 프로필을 찾을 수 없음","content":{"text/event-stream":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ServerSentEventString"}}}}},"200":{"description":"성공","content":{"text/event-stream":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ServerSentEventString"}}}}},"429":{"description":"QUOTA4001: 일일 사용량 초과","content":{"text/event-stream":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ServerSentEventString"}}}}},"403":{"description":"CALENDAR4002: 스레드에 접근할 권한이 없음","content":{"text/event-stream":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ServerSentEventString"}}}}}}}},"/api/v1/auth/refresh":{"post":{"tags":["AuthAPI"],"summary":"토큰 재발급(Refresh)","description":"Authorization 헤더에 Refresh Token(Bearer)을 전달하여 Access/Refresh 토큰을 재발급합니다.\n- 예: Authorization: Bearer {refreshToken}\n","operationId":"refreshToken","responses":{"200":{"description":"성공","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseOAuthLoginResultDTO"}}}},"401":{"description":"AUTH4002/AUTH4003/AUTH4005: 토큰이 유효하지 않음/만료/검증 실패","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseOAuthLoginResultDTO"}}}}}}},"/api/v1/auth/logout":{"post":{"tags":["AuthAPI"],"summary":"로그아웃","description":"현재 로그인 사용자의 서버 저장 Refresh Token을 제거합니다.","operationId":"logout","responses":{"200":{"description":"성공","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseVoid"}}}},"401":{"description":"AUTH4002/AUTH4003/AUTH4005: 토큰이 유효하지 않음/만료/검증 실패","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseVoid"}}}}}}},"/api/v1/auth/kakao":{"post":{"tags":["AuthAPI"],"summary":"카카오 로그인","description":"카카오 accessToken을 검증하고, Access/Refresh 토큰을 발급합니다.","operationId":"kakaoLogin","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/KakaoOAuthDTO"}}},"required":true},"responses":{"200":{"description":"성공","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseOAuthLoginResultDTO"}}}},"401":{"description":"AUTH4001: 소셜 로그인 인증 실패","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseOAuthLoginResultDTO"}}}},"400":{"description":"COMMON400: 잘못된 요청(요청 바디 검증 실패 등)","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseOAuthLoginResultDTO"}}}}}}},"/api/v1/auth/google":{"post":{"tags":["AuthAPI"],"summary":"구글 로그인","description":"구글 idToken을 검증하고, Access/Refresh 토큰을 발급합니다.","operationId":"googleLogin","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GoogleOAuthDTO"}}},"required":true},"responses":{"200":{"description":"성공","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseOAuthLoginResultDTO"}}}},"401":{"description":"AUTH4001: 소셜 로그인 인증 실패","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseOAuthLoginResultDTO"}}}},"400":{"description":"COMMON400: 잘못된 요청(요청 바디 검증 실패 등)","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseOAuthLoginResultDTO"}}}}}}},"/api/v1/auth/apple":{"post":{"tags":["AuthAPI"],"summary":"애플 로그인","description":"애플 idToken을 검증하고, Access/Refresh 토큰을 발급합니다.","operationId":"appleLogin","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppleOAuthDTO"}}},"required":true},"responses":{"200":{"description":"성공","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseOAuthLoginResultDTO"}}}},"401":{"description":"AUTH4001: 소셜 로그인 인증 실패","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseOAuthLoginResultDTO"}}}},"400":{"description":"COMMON400: 잘못된 요청(요청 바디 검증 실패 등)","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseOAuthLoginResultDTO"}}}}}}},"/api/v1/admin/payments/{paymentId}/refund":{"post":{"tags":["PaymentAdminAPI"],"summary":"관리자 수동 환불 반영","description":"스토어 콘솔에서 이미 환불 처리된 결제를 백엔드 DB에 수동 반영하고 광고 제거 권한을 회수합니다.\n- 관리자 인증 필요 (Bearer JWT, ADMIN 계정)\n- Google/Apple 스토어에 환불을 요청하는 API가 아니라 내부 fallback 처리 API\n- paymentId 기준으로 결제 상태를 `REFUNDED`로 변경\n- 해당 결제가 부여한 `REMOVE_ADS` 권한을 비활성화\n- 이미 환불 처리된 결제는 `alreadyProcessed=true`로 멱등 응답\n","operationId":"refundManually","parameters":[{"name":"paymentId","in":"path","required":true,"schema":{"type":"integer","format":"int64"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminManualRefundRequest"}}},"required":true},"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseAdminManualRefundResponse"}}}}}}},"/api/v1/chats/{chatLogId}":{"delete":{"tags":["Thread&ChatsAPI"],"summary":"채팅 메시지 삭제","description":"사용자 또는 AI가 작성한 채팅 메시지를 삭제합니다.","operationId":"deleteChatLog","parameters":[{"name":"chatLogId","in":"path","description":"채팅 로그 ID","required":true,"schema":{"type":"integer","format":"int64"},"example":1}],"responses":{"403":{"description":"CHAT4003: 채팅 메시지에 접근할 권한이 없음","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseChatLogDeleteResponse"}}}},"200":{"description":"성공","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseChatLogDeleteResponse"}}}},"404":{"description":"CHAT4002: 채팅 메시지를 찾을 수 없음","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseChatLogDeleteResponse"}}}}}},"patch":{"tags":["Thread&ChatsAPI"],"summary":"채팅 메시지 수정","description":"사용자 메시지만 수정할 수 있습니다.","operationId":"updateChatLog","parameters":[{"name":"chatLogId","in":"path","description":"채팅 로그 ID","required":true,"schema":{"type":"integer","format":"int64"},"example":1}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChatLogUpdateRequest"}}},"required":true},"responses":{"403":{"description":"CHAT4003: 채팅 메시지에 접근할 권한이 없음","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseChatLogResponse"}}}},"200":{"description":"성공","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseChatLogResponse"}}}},"404":{"description":"CHAT4002: 채팅 메시지를 찾을 수 없음","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseChatLogResponse"}}}},"400":{"description":"CHAT4004: AI 메시지는 수정할 수 없음","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseChatLogResponse"}}}}}}},"/jwt":{"get":{"tags":["health-controller"],"operationId":"checkHealthJWT","responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"type":"string"}}}}}}},"/health":{"get":{"tags":["health-controller"],"operationId":"checkHealth","responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"type":"string"}}}}}}},"/api/v1/user/me":{"get":{"tags":["UserAPI"],"summary":"내 유저 정보 조회","description":"현재 로그인한 사용자의 기본 정보(이메일/닉네임/OAuth 제공자)와 사용량(쿼터) 정보를 반환합니다.\n- 인증 필요 (Bearer JWT)\n- userId는 토큰(subject) 기반으로 서버에서 결정\n","operationId":"getUser","responses":{"200":{"description":"성공","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseMeResponseDTO"}}}},"404":{"description":"AUTH4006: 사용자를 찾을 수 없음","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseMeResponseDTO"}}}},"401":{"description":"인증 실패(토큰 누락/만료/위조)","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseMeResponseDTO"}}}}}}},"/api/v1/user/me/entitlements":{"get":{"tags":["UserAPI"],"summary":"내 결제 권한 조회","description":"현재 로그인한 사용자의 활성 결제 권한과 프론트 기능 플래그를 반환합니다.\n- 인증 필요 (Bearer JWT)\n- userId는 토큰(subject) 기반으로 서버에서 결정\n- 광고 제거 적용 여부는 `features.adRemoved` 값으로 판단\n","operationId":"getMyEntitlements","responses":{"200":{"description":"성공","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseEntitlementsResponse"}}}},"404":{"description":"AUTH4006: 사용자를 찾을 수 없음","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseEntitlementsResponse"}}}},"401":{"description":"인증 실패(토큰 누락/만료/위조)","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseEntitlementsResponse"}}}}}}},"/api/v1/user-settings/check-new":{"get":{"tags":["UserSettingAPI"],"summary":"신규 유저 여부 체크","description":"현재 로그인한 사용자가 설정값을 보유하고 있는지로 신규 유저 여부를 판단합니다.","operationId":"checkNewUser","responses":{"200":{"description":"성공","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseBoolean"}}}},"404":{"description":"AUTH4006: 유저 없음","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseBoolean"}}}},"401":{"description":"인증 실패(토큰 누락/만료/위조)","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseBoolean"}}}}}}},"/api/v1/terms/versions/{termVersionId}":{"get":{"tags":["TermAPI"],"summary":"약관 버전 본문 조회","description":"특정 약관 버전의 상세 본문을 반환합니다.\n- 인증 필요 (Bearer JWT)\n- 발행되지 않았거나 아직 효력이 발생하지 않은 버전은 조회할 수 없습니다.\n- `termCode` 초기 후보: SERVICE_TERMS, PRIVACY_POLICY, MARKETING\n- `contentFormat` 후보: TEXT, HTML, MARKDOWN\n","operationId":"getTermVersion","parameters":[{"name":"termVersionId","in":"path","required":true,"schema":{"type":"integer","format":"int64"}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseTermVersionDetailResponse"}}}}}}},"/api/v1/terms/agreement-status":{"get":{"tags":["TermAPI"],"summary":"내 약관 동의 상태 조회","description":"현재 로그인한 사용자의 약관 동의 상태와 서비스 진입 차단 여부를 반환합니다.\n- 인증 필요 (Bearer JWT)\n- 약관 본문은 포함하지 않습니다.\n- 프론트는 `agreementRequired`와 각 약관의 `blocking`, `action`을 기준으로 분기합니다.\n- `reason` 후보: NONE, INITIAL_REQUIRED_TERMS, UPDATED_REQUIRED_TERMS, OPTIONAL_TERMS_AVAILABLE\n- `submitContext` 후보: NONE, SIGNUP, RECONSENT, OPTIONAL_UPDATE\n- `terms[].termCode` 초기 후보: SERVICE_TERMS, PRIVACY_POLICY, MARKETING\n- `terms[].action` 후보: NONE, INITIAL_AGREEMENT_REQUIRED, RECONSENT_REQUIRED, OPTIONAL_CONSENT_AVAILABLE, OPTIONAL_RECONSENT_AVAILABLE\n","operationId":"getAgreementStatus","responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseAgreementStatusResponse"}}}}}}},"/api/v1/terms/agreement-screen":{"get":{"tags":["TermAPI"],"summary":"약관 동의 화면 조회","description":"현재 로그인한 사용자의 약관 동의 화면 구성 데이터를 반환합니다.\n- 인증 필요 (Bearer JWT)\n- 약관 본문을 포함합니다.\n- 프론트 약관 동의 화면 렌더링용 API입니다.\n- 응답 구조는 agreement-status와 같고 `terms[].content`가 포함됩니다.\n- `reason` 후보: NONE, INITIAL_REQUIRED_TERMS, UPDATED_REQUIRED_TERMS, OPTIONAL_TERMS_AVAILABLE\n- `submitContext` 후보: NONE, SIGNUP, RECONSENT, OPTIONAL_UPDATE\n- `terms[].termCode` 초기 후보: SERVICE_TERMS, PRIVACY_POLICY, MARKETING\n- `terms[].action` 후보: NONE, INITIAL_AGREEMENT_REQUIRED, RECONSENT_REQUIRED, OPTIONAL_CONSENT_AVAILABLE, OPTIONAL_RECONSENT_AVAILABLE\n","operationId":"getAgreementScreen","responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseAgreementStatusResponse"}}}}}}},"/api/v1/streak":{"get":{"tags":["StreakAPI"],"summary":"현재 스트릭 조회","description":"[v1.3.0+] KST 기준 연속 작성 일수를 반환합니다.\n- 쿼리 파라미터 없음 (서버가 KST 기준 '오늘'로 계산)\n- 오늘 미작성이어도 마지막 작성일이 '어제'라면 streakDays는 유지됩니다.\n- 마지막 작성일이 '어제'보다 이전이면 streakDays=0 입니다. (이미 끊김)\n- 하루에 여러 개 작성해도 그 날은 +1로만 계산\n","operationId":"getCurrentStreak","responses":{"200":{"description":"성공","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseCurrentStreakResponse"}}}},"404":{"description":"AUTH4006: 사용자를 찾을 수 없음","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseCurrentStreakResponse"}}}}}}},"/api/v1/memory":{"get":{"tags":["UserMemoryAPI"],"summary":"사용자 메모리 조회","description":"현재 사용자의 축적된 메모리 내용을 조회합니다.","operationId":"getUserMemory","responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseMemoryResponse"}}}}}},"delete":{"tags":["UserMemoryAPI"],"summary":"사용자 메모리 초기화","description":"현재 사용자의 축적된 메모리를 모두 삭제합니다.","operationId":"resetUserMemory","responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseMemoryResetResponse"}}}}}}},"/api/v1/calendar/month":{"get":{"tags":["CalendarAPI"],"summary":"월간 일기 미리보기","description":"[v1.3.0] 해당 월의 모든 날짜별 일기 미리보기를 조회합니다. (날짜별 최대 3개, 해시태그 + 이미지만)","operationId":"getCalendarPreview","parameters":[{"name":"year","in":"query","description":"년도","required":true,"schema":{"type":"integer","format":"int32"},"example":2025},{"name":"month","in":"query","description":"월","required":true,"schema":{"type":"integer","format":"int32"},"example":1}],"responses":{"200":{"description":"성공","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseListDailyPreviewResponseDTO"}}}},"404":{"description":"AUTH4006: 사용자를 찾을 수 없음","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseListDailyPreviewResponseDTO"}}}},"400":{"description":"CALENDAR4003: 유효하지 않은 날짜","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseListDailyPreviewResponseDTO"}}}}}}},"/api/v1/calendar/month/summary":{"get":{"tags":["CalendarAPI"],"summary":"월간 일기 전체 조회","description":"[v1.3.0] 해당 월의 모든 날짜별 일기 상세 정보를 조회합니다. (날짜별 최대 3개)","operationId":"getCalendarView","parameters":[{"name":"year","in":"query","description":"년도","required":true,"schema":{"type":"integer","format":"int32"},"example":2025},{"name":"month","in":"query","description":"월","required":true,"schema":{"type":"integer","format":"int32"},"example":1}],"responses":{"200":{"description":"성공","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseListDailySummaryResponseDTO"}}}},"404":{"description":"AUTH4006: 사용자를 찾을 수 없음","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseListDailySummaryResponseDTO"}}}},"400":{"description":"CALENDAR4003: 유효하지 않은 날짜","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseListDailySummaryResponseDTO"}}}}}}},"/api/v1/calendar/feed":{"get":{"tags":["CalendarAPI"],"summary":"피드 전용 최신순 조회 (커서 기반 무한 페이징)","description":"[v1.3.0+] 피드 전용 최신순 정렬(id DESC)을 보장하며, 커서 기반 무한 페이징을 제공합니다.\n- limit은 날짜 묶음 개수입니다 (일기 개수가 아님). 기본 20개, 최대 50개.\n- 첫 요청(첫 페이지)은 cursorDiaryId 없이 호출합니다.\n- 다음 페이지부터는 직전 응답의 pageInfo.nextCursor.cursorDiaryId 값을 그대로 재전송합니다.\n- 마지막 페이지에서는 pageInfo.hasNext=false 이며 pageInfo.nextCursor=null 입니다.\n- 각 날짜 묶음에는 최대 3개의 일기가 포함됩니다.\n","operationId":"getFeed","parameters":[{"name":"limit","in":"query","description":"조회할 날짜 묶음 개수 (기본 20, 최대 50)","required":false,"schema":{"type":"integer","format":"int32"},"example":20},{"name":"cursorDiaryId","in":"query","description":"커서 diaryId (단일 필드 커서)\n- 첫 요청은 미전송(null) 가능\n- 다음 페이지부터는 직전 응답의 pageInfo.nextCursor.cursorDiaryId 값을 그대로 재전송\n- 마지막 페이지는 pageInfo.nextCursor=null 이므로 커서를 다시 미전송\n","required":false,"schema":{"type":"integer","format":"int64"},"example":401}],"responses":{"200":{"description":"성공","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseFeedResponseDTO"}}}},"400":{"description":"CALENDAR4005: 유효하지 않은 limit","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseFeedResponseDTO"}}}},"404":{"description":"AUTH4006: 사용자를 찾을 수 없음","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseFeedResponseDTO"}}}}}}},"/api/v1/calendar/day":{"get":{"tags":["CalendarAPI"],"summary":"특정 날짜 일기 조회","description":"[v1.3.0] 특정 날짜의 일기를 상세 조회합니다. (최대 3개)","operationId":"getDailySummary","parameters":[{"name":"year","in":"query","description":"년도","required":true,"schema":{"type":"integer","format":"int32"},"example":2025},{"name":"month","in":"query","description":"월","required":true,"schema":{"type":"integer","format":"int32"},"example":1},{"name":"day","in":"query","description":"일","required":true,"schema":{"type":"integer","format":"int32"},"example":15}],"responses":{"200":{"description":"성공","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseDailySummaryResponseDTO"}}}},"404":{"description":"AUTH4006: 사용자를 찾을 수 없음","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseDailySummaryResponseDTO"}}}},"400":{"description":"CALENDAR4003: 유효하지 않은 날짜","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseDailySummaryResponseDTO"}}}}}}},"/api/v1/ai-profiles":{"get":{"tags":["AiProfileAPI"],"summary":"AI 프로필 목록 조회","description":"전체 AI 프로필 목록을 조회합니다. (ID 1~5 고정)","operationId":"getAiProfileList","responses":{"200":{"description":"성공","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseListAiProfileResponse"}}}},"404":{"description":"AUTH4006: 사용자를 찾을 수 없음","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseListAiProfileResponse"}}}}}}},"/api/v1/ai-profiles/{aiProfileId}":{"get":{"tags":["AiProfileAPI"],"summary":"AI 프로필 상세 조회","description":"특정 AI 프로필을 상세 조회합니다. (ID 1~5)","operationId":"getAiProfile","parameters":[{"name":"aiProfileId","in":"path","description":"AI 프로필 ID","required":true,"schema":{"type":"integer","format":"int64"},"example":1}],"responses":{"200":{"description":"성공","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseAiProfileResponse"}}}},"404":{"description":"AUTH4006: 사용자를 찾을 수 없음 / PROFILE4002: AI 프로필을 찾을 수 없음","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseAiProfileResponse"}}}}}}},"/api/v1/ai-profiles/{aiProfileId}/question":{"get":{"tags":["AiProfileAPI"],"summary":"AI 프로필 생성 질문 조회","description":"특정 AI 프로필을 만들 당시의 질문을 조회합니다.","operationId":"getAiQuestionProfile","parameters":[{"name":"aiProfileId","in":"path","description":"AI 프로필 ID","required":true,"schema":{"type":"integer","format":"int64"},"example":1}],"responses":{"200":{"description":"성공","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseAiProfileQuestionResponse"}}}},"404":{"description":"AUTH4006: 사용자를 찾을 수 없음 / PROFILE4002: AI 프로필을 찾을 수 없음","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseAiProfileQuestionResponse"}}}}}}},"/api/v1/ai-profiles/recent":{"get":{"tags":["AiProfileAPI"],"summary":"최근 사용 AI 프로필 조회","description":"최근 사용한 AI 프로필 ID를 조회합니다.","operationId":"getAiProfileIdRecent","responses":{"200":{"description":"성공","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseAiProfileResponse"}}}},"404":{"description":"PROFILE4002: AI 프로필을 찾을 수 없음","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseAiProfileResponse"}}}}}}},"/api/v1/user":{"delete":{"tags":["UserAPI"],"description":"회원탈퇴하고, 유저 정보를 리턴합니다.","operationId":"deleteUser","responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseDeleteResultDTO"}}}}}}},"/api/v1/terms/agreements/me":{"delete":{"tags":["TermAPI"],"summary":"사용자 약관 동의 이력 삭제","description":"현재 로그인한 사용자의 약관 동의 이력을 삭제합니다.\n- 인증 필요 (Bearer JWT)\n- 삭제 대상은 user_term_agreement 이력만입니다.\n- term, term_version 데이터는 삭제하지 않습니다.\n- 프론트 약관 동의 플로우 반복 테스트용 API입니다.\n- 정식 약관 철회 기능은 별도 정책 검토 후 분리 구현합니다.\n","operationId":"deleteAgreementHistory","responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseDeleteAgreementHistoryResponse"}}}}}}},"/api/v1/expo-push-tokens/{expoPushToken}":{"delete":{"tags":["ExpoPushTokenAPI"],"summary":"Expo Push Token 삭제","description":"특정 Expo Push Token을 삭제합니다.\n- 인증 필요 (Bearer JWT)\n- 삭제 대상 토큰은 path variable로 전달합니다.\n- `Idempotency-Key` 헤더를 전달하면 같은 삭제 요청의 중복 처리를 방지합니다.\n","operationId":"deleteToken","parameters":[{"name":"expoPushToken","in":"path","description":"삭제할 Expo Push Token. 형식: ExponentPushToken[...]","required":true,"schema":{"type":"string"},"example":"ExponentPushToken[xxxxxxxxxxxxxxxxxxxxxx]"},{"name":"Idempotency-Key","in":"header","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseDeleteResponse"}}}}}}}},"components":{"schemas":{"UserSettingRequest":{"required":["notificationEnabled","notificationTime","sleepTime"],"type":"object","properties":{"sleepTime":{"pattern":"^([01]\\d|2[0-3]):[0-5]\\d$","type":"string","description":"수면 시간 (HH:mm)","example":"23:00"},"notificationTime":{"pattern":"^([01]\\d|2[0-3]):[0-5]\\d$","type":"string","description":"알림 시간 (HH:mm)","example":"21:00"},"notificationEnabled":{"type":"boolean","description":"알림 활성화 여부","example":true}},"description":"사용자 설정 수정 요청"},"ApiResponseUserSettingResponse":{"required":["code","isSuccess","message"],"type":"object","properties":{"isSuccess":{"type":"boolean","description":"요청 성공 여부","example":true},"code":{"type":"string","description":"응답 코드","example":"COMMON200"},"message":{"type":"string","description":"응답 메시지","example":"성공입니다."},"result":{"$ref":"#/components/schemas/UserSettingResponse"}},"description":"API 응답 래퍼"},"UserSettingResponse":{"required":["notificationEnabled","notificationTime","sleepTime"],"type":"object","properties":{"sleepTime":{"type":"string","description":"수면 시간 (기본값: 04:30)","example":"04:30"},"notificationTime":{"type":"string","description":"알림 시간 (기본값: 23:00)","example":"23:00"},"notificationEnabled":{"type":"boolean","description":"알림 활성화 여부","example":true}},"description":"사용자 설정 응답","nullable":true},"DiaryUpdateRequest":{"type":"object","properties":{"title":{"maxLength":100,"minLength":0,"type":"string","description":"일기 제목","nullable":true,"example":"수정된 제목"},"content":{"maxLength":5000,"minLength":0,"type":"string","description":"일기 내용","nullable":true,"example":"수정된 내용"},"mood":{"maxLength":40,"minLength":0,"type":"string","description":"기분","nullable":true,"example":"RELAX","enum":["HAPPY","SAD","TIRED","ANGRY","RELAX"]},"hashtag1":{"maxLength":30,"minLength":0,"type":"string","description":"해시태그 1","nullable":true,"example":"#수정"},"hashtag2":{"maxLength":30,"minLength":0,"type":"string","description":"해시태그 2","nullable":true,"example":"#일기"},"generateImage":{"type":"boolean","description":"이미지 재생성 여부 (기본값 false)","example":false}},"description":"일기 수정 요청 (null이 아닌 필드만 업데이트)"},"ApiResponseDiaryResponse":{"required":["code","isSuccess","message"],"type":"object","properties":{"isSuccess":{"type":"boolean","description":"요청 성공 여부","example":true},"code":{"type":"string","description":"응답 코드","example":"COMMON200"},"message":{"type":"string","description":"응답 메시지","example":"성공입니다."},"result":{"$ref":"#/components/schemas/DiaryResponse"}},"description":"API 응답 래퍼"},"DiaryResponse":{"required":["aiProfileId","createdAt","day","diaryId","month","threadId","type","version","year"],"type":"object","properties":{"diaryId":{"type":"integer","description":"일기 ID","format":"int64","example":1},"threadId":{"type":"integer","description":"스레드 ID (항상 존재)","format":"int64","example":1},"aiProfileId":{"type":"integer","description":"AI 프로필 ID","format":"int64","example":1},"year":{"type":"integer","description":"년도","format":"int32","example":2025},"month":{"type":"integer","description":"월","format":"int32","example":1},"day":{"type":"integer","description":"일","format":"int32","example":15},"title":{"type":"string","description":"일기 제목","nullable":true,"example":"오늘의 일기"},"content":{"type":"string","description":"일기 내용","nullable":true,"example":"오늘은 좋은 하루였다."},"mood":{"type":"string","description":"기분 (기본값: HAPPY)","nullable":true,"example":"HAPPY","enum":["HAPPY","SAD","TIRED","ANGRY","RELAX"]},"type":{"type":"string","description":"일기 생성 타입 (MANUAL: 수동 작성, CHAT_BASED: 채팅 기반 자동 생성)","example":"MANUAL","enum":["MANUAL","CHAT_BASED"]},"hashtag1":{"type":"string","description":"해시태그 1","nullable":true,"example":"#좋은하루"},"hashtag2":{"type":"string","description":"해시태그 2","nullable":true,"example":"#감사"},"imageUrl":{"type":"string","description":"이미지 URL (비동기 생성, 초기에는 null)","nullable":true,"example":"https://s3.amazonaws.com/..."},"imageStatus":{"type":"string","description":"이미지 생성 상태","nullable":true,"example":"PENDING","enum":["NONE","PENDING","READY","FAILED"]},"version":{"type":"integer","description":"버전","format":"int32","example":1},"createdAt":{"type":"string","description":"생성일시","format":"date-time"}},"description":"일기 생성/수정 응답","nullable":true},"AiChatRequestV2":{"required":["aiProfileId","content","day","month","year"],"type":"object","properties":{"aiProfileId":{"type":"integer","description":"AI 프로필 ID","format":"int64","example":1},"content":{"maxLength":1000,"minLength":1,"type":"string","description":"전송할 메시지 내용","example":"오늘 기분이 어때?"},"year":{"maximum":2100,"minimum":2020,"type":"integer","description":"연도","format":"int32","example":2025},"month":{"maximum":12,"minimum":1,"type":"integer","description":"월","format":"int32","example":11},"day":{"maximum":31,"minimum":1,"type":"integer","description":"일","format":"int32","example":30}},"description":"메모리 기반 AI 채팅 요청"},"ServerSentEventString":{"type":"object"},"ApiResponseChatResponse":{"required":["code","isSuccess","message"],"type":"object","properties":{"isSuccess":{"type":"boolean","description":"요청 성공 여부","example":true},"code":{"type":"string","description":"응답 코드","example":"COMMON200"},"message":{"type":"string","description":"응답 메시지","example":"성공입니다."},"result":{"$ref":"#/components/schemas/ChatResponse"}},"description":"API 응답 래퍼"},"ChatResponse":{"required":["aiProfileImageS3","aiProfileName","chatId","content","createAt","role"],"type":"object","properties":{"chatId":{"type":"integer","description":"채팅 ID","format":"int64","example":1},"role":{"type":"string","description":"발신자 역할","example":"USER","enum":["AI","USER"]},"content":{"type":"string","description":"메시지 내용","example":"안녕하세요!"},"createAt":{"type":"string","description":"생성일시","format":"date-time"},"aiProfileName":{"type":"string","description":"AI 프로필 이름 (서버 주입)","example":"루나"},"aiProfileImageS3":{"type":"string","description":"AI 프로필 이미지 URL (서버 주입)","example":"https://s3.amazonaws.com/..."}},"description":"채팅 응답","nullable":true},"ApiResponseVoid":{"required":["code","isSuccess","message"],"type":"object","properties":{"isSuccess":{"type":"boolean","description":"요청 성공 여부","example":true},"code":{"type":"string","description":"응답 코드","example":"COMMON200"},"message":{"type":"string","description":"응답 메시지","example":"성공입니다."},"result":{"type":"object","description":"응답 데이터","nullable":true}},"description":"API 응답 래퍼"},"AgreementDecisionRequest":{"required":["agreed","termVersionId"],"type":"object","properties":{"termVersionId":{"type":"integer","description":"동의 대상 약관 버전 ID. agreement-status 또는 agreement-screen 응답의 terms[].currentTermVersionId 값을 전달","format":"int64","example":1},"agreed":{"type":"boolean","description":"동의 여부. 필수 약관은 true만 가능하며, 선택 약관은 false 제출 가능","example":true}},"description":"약관 버전별 동의/거절 결정"},"SubmitAgreementsRequest":{"required":["agreements","context"],"type":"object","properties":{"context":{"type":"string","description":"약관 동의 제출 맥락. 후보: SIGNUP(최초 동의), RECONSENT(필수 약관 재동의), OPTIONAL_UPDATE(선택 약관 변경/동의), WITHDRAWAL(선택 약관 철회)","example":"SIGNUP","enum":["NONE","SIGNUP","RECONSENT","OPTIONAL_UPDATE","WITHDRAWAL","SIGNUP","RECONSENT","OPTIONAL_UPDATE","WITHDRAWAL"]},"agreements":{"type":"array","description":"약관 버전별 동의/거절 결정 목록. 필수 약관은 반드시 agreed=true로 포함해야 하며, 선택 약관은 agreed=false 제출 가능","items":{"$ref":"#/components/schemas/AgreementDecisionRequest"}}},"description":"약관 동의 제출 요청"},"ApiResponseSubmitAgreementsResponse":{"required":["code","isSuccess","message"],"type":"object","properties":{"isSuccess":{"type":"boolean","description":"요청 성공 여부","example":true},"code":{"type":"string","description":"응답 코드","example":"COMMON200"},"message":{"type":"string","description":"응답 메시지","example":"성공입니다."},"result":{"$ref":"#/components/schemas/SubmitAgreementsResponse"}},"description":"API 응답 래퍼"},"SubmitAgreementsResponse":{"required":["agreementRequired","reason"],"type":"object","properties":{"agreementRequired":{"type":"boolean","description":"서비스 진입 전 약관 동의 화면이 필요한지 여부. false면 필수 약관 기준 서비스 진입 가능","example":false},"reason":{"type":"string","description":"약관 동의 상태 사유. 후보: NONE(필요 없음), INITIAL_REQUIRED_TERMS(최초 필수 약관 동의 필요), UPDATED_REQUIRED_TERMS(개정된 필수 약관 재동의 필요), OPTIONAL_TERMS_AVAILABLE(선택 약관 동의/변경 가능)","example":"NONE","enum":["NONE","INITIAL_REQUIRED_TERMS","UPDATED_REQUIRED_TERMS","OPTIONAL_TERMS_AVAILABLE"]}},"description":"약관 동의 제출 응답","nullable":true},"GoogleVerifyRequest":{"required":["packageName","productId","purchaseToken"],"type":"object","properties":{"productId":{"type":"string","description":"Google Play 상품 ID. 현재 후보: premium(광고 제거)","example":"premium","enum":["premium"]},"packageName":{"type":"string","description":"Android 앱 패키지명","example":"com.melissa.melissaFE"},"purchaseToken":{"type":"string","description":"Google Play Billing purchaseToken"},"orderId":{"type":"string","description":"Google 주문 ID. 없으면 생략 가능","nullable":true,"example":"GPA.1234-5678-9012-34567"}},"description":"Google Play 비소모성 상품 구매 검증 요청"},"ApiResponseVerifyResponse":{"required":["code","isSuccess","message"],"type":"object","properties":{"isSuccess":{"type":"boolean","description":"요청 성공 여부","example":true},"code":{"type":"string","description":"응답 코드","example":"COMMON200"},"message":{"type":"string","description":"응답 메시지","example":"성공입니다."},"result":{"$ref":"#/components/schemas/VerifyResponse"}},"description":"API 응답 래퍼"},"EntitlementSummary":{"required":["active","type"],"type":"object","properties":{"type":{"type":"string","description":"권한 타입. enum 후보: REMOVE_ADS(광고 제거), PREMIUM, EXTRA_STORAGE, AI_CREDIT. 현재 결제 상품은 REMOVE_ADS만 사용","nullable":true,"example":"REMOVE_ADS","enum":["REMOVE_ADS","PREMIUM","EXTRA_STORAGE","AI_CREDIT"]},"active":{"type":"boolean","description":"권한 활성 여부. true면 광고 제거 적용 가능","example":true}},"description":"결제 권한 요약"},"VerifyResponse":{"required":["acknowledged","alreadyProcessed","entitlement","finishRequired","paymentId","platform","productId","purchasedAt","status","verifiedAt"],"type":"object","properties":{"paymentId":{"type":"integer","description":"백엔드 결제 내역 ID","format":"int64","example":1},"platform":{"type":"string","description":"결제 플랫폼. 후보: GOOGLE, APPLE","example":"GOOGLE","enum":["GOOGLE","APPLE"]},"productId":{"type":"string","description":"백엔드 내부 상품 ID. 현재 후보: remove_ads(광고 제거). 스토어 상품 ID가 아니라 내부 상품 ID로 반환","example":"remove_ads","enum":["remove_ads"]},"status":{"type":"string","description":"결제 상태. 후보: PENDING, PURCHASED, FAILED, REFUNDED, REVOKED","example":"PURCHASED","enum":["PENDING","PURCHASED","FAILED","REFUNDED","REVOKED"]},"entitlement":{"$ref":"#/components/schemas/EntitlementSummary"},"acknowledged":{"type":"boolean","description":"Google 구매 acknowledge 완료 여부. Apple은 null","nullable":true,"example":true},"finishRequired":{"type":"boolean","description":"프론트의 구매 완료 처리 필요 여부. Apple 검증 성공 시 true","nullable":true,"example":true},"alreadyProcessed":{"type":"boolean","description":"이미 처리된 같은 구매를 다시 검증했는지 여부","example":false},"purchasedAt":{"type":"string","description":"스토어 구매 시각","format":"date-time","nullable":true},"verifiedAt":{"type":"string","description":"백엔드 검증 시각","format":"date-time","nullable":true}},"description":"스토어 구매 검증 응답","nullable":true},"GoogleRestoreRequest":{"required":["purchases"],"type":"object","properties":{"purchases":{"type":"array","description":"Google Play Billing에서 조회한 보유 구매 목록","items":{"$ref":"#/components/schemas/GoogleVerifyRequest"}}},"description":"Google Play 구매 복원 요청"},"ApiResponseRestoreResponse":{"required":["code","isSuccess","message"],"type":"object","properties":{"isSuccess":{"type":"boolean","description":"요청 성공 여부","example":true},"code":{"type":"string","description":"응답 코드","example":"COMMON200"},"message":{"type":"string","description":"응답 메시지","example":"성공입니다."},"result":{"$ref":"#/components/schemas/RestoreResponse"}},"description":"API 응답 래퍼"},"FailedPurchase":{"required":["code","identifier","message","platform","productId"],"type":"object","properties":{"platform":{"type":"string","description":"결제 플랫폼. 후보: GOOGLE, APPLE","example":"GOOGLE","enum":["GOOGLE","APPLE"]},"productId":{"type":"string","description":"요청으로 전달된 스토어 상품 ID","example":"premium"},"identifier":{"type":"string","description":"실패 항목 식별자. Google은 orderId 또는 purchaseToken, Apple은 transactionId","example":"GPA.1234-5678-9012-34567"},"code":{"type":"string","description":"실패 코드","example":"PAYMENT4004"},"message":{"type":"string","description":"실패 메시지","example":"스토어 구매 검증에 실패했습니다."}},"description":"복원 실패 구매 요약"},"FeatureSummary":{"required":["adRemoved"],"type":"object","properties":{"adRemoved":{"type":"boolean","description":"광고 제거 적용 여부. 프론트는 이 값을 기준으로 광고 표시 여부를 판단","example":true}},"description":"프론트 기능 플래그"},"RestoreResponse":{"required":["failed","features","restored"],"type":"object","properties":{"restored":{"type":"array","description":"복원에 성공한 구매 목록","items":{"$ref":"#/components/schemas/RestoredPurchase"}},"failed":{"type":"array","description":"검증에 실패한 구매 목록. 일부 실패가 있어도 API 자체는 성공할 수 있음","items":{"$ref":"#/components/schemas/FailedPurchase"}},"features":{"$ref":"#/components/schemas/FeatureSummary"}},"description":"스토어 구매 복원 응답","nullable":true},"RestoredPurchase":{"required":["entitlementType","paymentId","platform","productId","status"],"type":"object","properties":{"paymentId":{"type":"integer","description":"백엔드 결제 내역 ID","format":"int64","example":1},"platform":{"type":"string","description":"결제 플랫폼. 후보: GOOGLE, APPLE","example":"APPLE","enum":["GOOGLE","APPLE"]},"productId":{"type":"string","description":"백엔드 내부 상품 ID. 현재 후보: remove_ads(광고 제거)","example":"remove_ads","enum":["remove_ads"]},"status":{"type":"string","description":"결제 상태. 후보: PENDING, PURCHASED, FAILED, REFUNDED, REVOKED","example":"PURCHASED","enum":["PENDING","PURCHASED","FAILED","REFUNDED","REVOKED"]},"entitlementType":{"type":"string","description":"복원된 권한 타입. enum 후보: REMOVE_ADS(광고 제거), PREMIUM, EXTRA_STORAGE, AI_CREDIT. 현재 결제 상품은 REMOVE_ADS만 사용","nullable":true,"example":"REMOVE_ADS","enum":["REMOVE_ADS","PREMIUM","EXTRA_STORAGE","AI_CREDIT"]}},"description":"복원 성공 구매 요약"},"AppleVerifyRequest":{"required":["bundleId","environment","productId","transactionId"],"type":"object","properties":{"productId":{"type":"string","description":"Apple 인앱결제 상품 ID. 현재 후보: com.melissa.melissaFE.premium(광고 제거)","example":"com.melissa.melissaFE.premium","enum":["com.melissa.melissaFE.premium"]},"transactionId":{"type":"string","description":"Apple transactionId","example":"2000000123456789"},"originalTransactionId":{"type":"string","description":"Apple originalTransactionId. 없으면 생략 가능","nullable":true,"example":"2000000123456789"},"environment":{"type":"string","description":"Apple 거래 환경. 후보: SANDBOX(테스트 결제), PRODUCTION(상용 결제)","example":"SANDBOX","enum":["SANDBOX","PRODUCTION"]},"bundleId":{"type":"string","description":"iOS 앱 bundleId","example":"com.melissa.melissaFE"}},"description":"Apple App Store 거래 검증 요청"},"AppleRestoreRequest":{"required":["transactions"],"type":"object","properties":{"transactions":{"type":"array","description":"App Store에서 조회한 보유 거래 목록","items":{"$ref":"#/components/schemas/AppleVerifyRequest"}}},"description":"Apple App Store 구매 복원 요청"},"RegisterTokenRequest":{"required":["expoPushToken","platform"],"type":"object","properties":{"expoPushToken":{"pattern":"^ExponentPushToken\\[.+\\]$","type":"string","description":"Expo Push Token. 형식: ExponentPushToken[...]","example":"ExponentPushToken[xxxxxxxxxxxxxxxxxxxxxx]"},"platform":{"type":"string","description":"클라이언트 플랫폼. 후보: ANDROID, IOS","example":"ANDROID","enum":["ANDROID","IOS","ANDROID","IOS"]},"deviceId":{"type":"string","description":"기기 ID. 앱에서 관리하는 디바이스 식별자가 있으면 전달하며, 없으면 생략 가능","nullable":true,"example":"device-uuid-1234"}}},"ApiResponseTokenResponse":{"required":["code","isSuccess","message"],"type":"object","properties":{"isSuccess":{"type":"boolean","description":"요청 성공 여부","example":true},"code":{"type":"string","description":"응답 코드","example":"COMMON200"},"message":{"type":"string","description":"응답 메시지","example":"성공입니다."},"result":{"$ref":"#/components/schemas/TokenResponse"}},"description":"API 응답 래퍼"},"TokenResponse":{"required":["createdAt","expoPushToken","id","invalid","platform","updatedAt"],"type":"object","properties":{"id":{"type":"integer","description":"토큰 ID","format":"int64","example":1},"expoPushToken":{"type":"string","description":"Expo Push Token. 형식: ExponentPushToken[...]","example":"ExponentPushToken[xxxxxxxxxxxxxxxxxxxxxx]"},"platform":{"type":"string","description":"클라이언트 플랫폼. 후보: ANDROID, IOS","example":"ANDROID","enum":["ANDROID","IOS","ANDROID","IOS"]},"deviceId":{"type":"string","description":"기기 ID","nullable":true,"example":"device-uuid-1234"},"invalid":{"type":"boolean","description":"유효하지 않은 토큰 여부. true이면 발송 실패 등으로 무효 처리된 토큰","example":false},"createdAt":{"type":"string","description":"생성일시","format":"date-time"},"updatedAt":{"type":"string","description":"수정일시","format":"date-time"}},"description":"Expo Push Token 응답","nullable":true},"ManualDiaryCreateRequest":{"required":["aiProfileId","content","day","month","year"],"type":"object","properties":{"aiProfileId":{"type":"integer","description":"AI 프로필 ID","format":"int64","example":1},"year":{"maximum":2100,"minimum":2020,"type":"integer","description":"년도","format":"int32","example":2025},"month":{"maximum":12,"minimum":1,"type":"integer","description":"월","format":"int32","example":1},"day":{"maximum":31,"minimum":1,"type":"integer","description":"일","format":"int32","example":15},"title":{"maxLength":100,"minLength":0,"type":"string","description":"일기 제목","nullable":true,"example":"오늘의 일기"},"content":{"maxLength":5000,"minLength":1,"type":"string","description":"일기 내용","example":"오늘은 좋은 하루였다."},"mood":{"maxLength":40,"minLength":0,"type":"string","description":"기분","nullable":true,"example":"HAPPY","enum":["HAPPY","SAD","TIRED","ANGRY","RELAX"]},"generateImage":{"type":"boolean","description":"이미지 생성 여부 (기본값 true)","example":true}},"description":"수동 일기 작성 요청"},"ChatDiaryCreateRequest":{"required":["aiProfileId","day","month","year"],"type":"object","properties":{"aiProfileId":{"type":"integer","description":"AI 프로필 ID","format":"int64","example":1},"year":{"maximum":2100,"minimum":2020,"type":"integer","description":"년도","format":"int32","example":2025},"month":{"maximum":12,"minimum":1,"type":"integer","description":"월","format":"int32","example":1},"day":{"maximum":31,"minimum":1,"type":"integer","description":"일","format":"int32","example":15},"generateImage":{"type":"boolean","description":"이미지 생성 여부 (기본값 true)","example":true}},"description":"채팅 기반 일기 생성 요청"},"ApiResponseThreadResponse":{"required":["code","isSuccess","message"],"type":"object","properties":{"isSuccess":{"type":"boolean","description":"요청 성공 여부","example":true},"code":{"type":"string","description":"응답 코드","example":"COMMON200"},"message":{"type":"string","description":"응답 메시지","example":"성공입니다."},"result":{"$ref":"#/components/schemas/ThreadResponse"}},"description":"API 응답 래퍼"},"ThreadResponse":{"required":["day","month","threadId","year"],"type":"object","properties":{"threadId":{"type":"integer","description":"스레드 ID (생성/재생성/삭제된 ID)","format":"int64","example":1},"year":{"type":"integer","description":"년도","format":"int32","example":2025},"month":{"type":"integer","description":"월","format":"int32","example":1},"day":{"type":"integer","description":"일","format":"int32","example":15}},"description":"스레드 응답","nullable":true},"AiChatRequest":{"required":["aiProfileId","content","day","month","year"],"type":"object","properties":{"aiProfileId":{"type":"integer","description":"AI 프로필 ID","format":"int64","example":1},"content":{"maxLength":1000,"minLength":1,"type":"string","description":"전송할 메시지 내용","example":"오늘 기분이 어때?"},"year":{"maximum":2100,"minimum":2020,"type":"integer","description":"연도","format":"int32","example":2025},"month":{"maximum":12,"minimum":1,"type":"integer","description":"월","format":"int32","example":11},"day":{"maximum":31,"minimum":1,"type":"integer","description":"일","format":"int32","example":30}},"description":"AI 채팅 요청"},"ApiResponseOAuthLoginResultDTO":{"required":["code","isSuccess","message"],"type":"object","properties":{"isSuccess":{"type":"boolean","description":"요청 성공 여부","example":true},"code":{"type":"string","description":"응답 코드","example":"COMMON200"},"message":{"type":"string","description":"응답 메시지","example":"성공입니다."},"result":{"$ref":"#/components/schemas/OAuthLoginResultDTO"}},"description":"API 응답 래퍼"},"OAuthLoginResultDTO":{"required":["accessToken","refreshToken","tokenType","userId"],"type":"object","properties":{"userId":{"type":"integer","description":"사용자 ID","format":"int64","example":1},"oauthProvider":{"type":"string","description":"OAuth 제공자. 후보: GOOGLE, KAKAO, APPLE","nullable":true,"example":"GOOGLE","enum":["GOOGLE","KAKAO","APPLE"]},"email":{"type":"string","description":"이메일","nullable":true,"example":"user@example.com"},"nickname":{"type":"string","description":"닉네임","nullable":true,"example":"홍길동"},"accessToken":{"type":"string","description":"액세스 토큰","example":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."},"refreshToken":{"type":"string","description":"리프레시 토큰","example":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."},"tokenType":{"type":"string","description":"토큰 타입. 현재는 Bearer 고정","example":"Bearer","enum":["Bearer"]}},"description":"OAuth 로그인 결과","nullable":true},"KakaoOAuthDTO":{"required":["accessToken"],"type":"object","properties":{"accessToken":{"type":"string","description":"Kakao Access Token","example":"xxxxxxxxxxxxxxxxxxxxx"}},"description":"Kakao OAuth 로그인 요청"},"GoogleOAuthDTO":{"required":["idToken"],"type":"object","properties":{"idToken":{"type":"string","description":"Google ID Token","example":"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9..."}},"description":"Google OAuth 로그인 요청"},"AppleOAuthDTO":{"required":["idToken"],"type":"object","properties":{"idToken":{"type":"string","description":"Apple ID Token","example":"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9..."}},"description":"Apple OAuth 로그인 요청"},"AdminManualRefundRequest":{"required":["reason"],"type":"object","properties":{"reason":{"maxLength":100,"minLength":0,"type":"string","description":"수동 환불 반영 사유","example":"Google Play Console 환불 처리 확인"},"refundedAt":{"type":"string","description":"스토어 환불 처리 시각. 생략하면 서버 처리 시각 사용","format":"date-time","nullable":true}},"description":"관리자 수동 환불 반영 요청"},"AdminManualRefundResponse":{"required":["alreadyProcessed","entitlementActive","entitlementRevoked","entitlementType","paymentId","platform","processedAt","productId","refundedAt","status","userId"],"type":"object","properties":{"paymentId":{"type":"integer","description":"백엔드 결제 내역 ID","format":"int64","example":1},"userId":{"type":"integer","description":"환불 처리 대상 사용자 ID","format":"int64","example":10},"platform":{"type":"string","description":"결제 플랫폼. 후보: GOOGLE, APPLE","example":"GOOGLE","enum":["GOOGLE","APPLE"]},"productId":{"type":"string","description":"백엔드 내부 상품 ID. 현재 후보: remove_ads(광고 제거)","example":"remove_ads","enum":["remove_ads"]},"status":{"type":"string","description":"결제 상태. 후보: PENDING, PURCHASED, FAILED, REFUNDED, REVOKED","example":"REFUNDED","enum":["PENDING","PURCHASED","FAILED","REFUNDED","REVOKED"]},"entitlementType":{"type":"string","description":"회수 대상 권한 타입. enum 후보: REMOVE_ADS(광고 제거), PREMIUM, EXTRA_STORAGE, AI_CREDIT. 회수 대상 권한이 없으면 null","nullable":true,"example":"REMOVE_ADS","enum":["REMOVE_ADS","PREMIUM","EXTRA_STORAGE","AI_CREDIT"]},"entitlementRevoked":{"type":"boolean","description":"권한 회수 완료 여부","example":true},"entitlementActive":{"type":"boolean","description":"권한 활성 여부","nullable":true,"example":false},"alreadyProcessed":{"type":"boolean","description":"이미 환불 처리된 결제였는지 여부","example":false},"refundedAt":{"type":"string","description":"환불 반영 시각","format":"date-time","nullable":true},"processedAt":{"type":"string","description":"관리자 fallback 처리 시각","format":"date-time"}},"description":"관리자 수동 환불 반영 응답","nullable":true},"ApiResponseAdminManualRefundResponse":{"required":["code","isSuccess","message"],"type":"object","properties":{"isSuccess":{"type":"boolean","description":"요청 성공 여부","example":true},"code":{"type":"string","description":"응답 코드","example":"COMMON200"},"message":{"type":"string","description":"응답 메시지","example":"성공입니다."},"result":{"$ref":"#/components/schemas/AdminManualRefundResponse"}},"description":"API 응답 래퍼"},"ChatLogUpdateRequest":{"required":["content"],"type":"object","properties":{"content":{"maxLength":1000,"minLength":0,"type":"string","description":"수정할 메시지 내용","example":"수정된 메시지 내용입니다."}},"description":"채팅 로그 수정 요청"},"ApiResponseChatLogResponse":{"required":["code","isSuccess","message"],"type":"object","properties":{"isSuccess":{"type":"boolean","description":"요청 성공 여부","example":true},"code":{"type":"string","description":"응답 코드","example":"COMMON200"},"message":{"type":"string","description":"응답 메시지","example":"성공입니다."},"result":{"$ref":"#/components/schemas/ChatLogResponse"}},"description":"API 응답 래퍼"},"ChatLogResponse":{"required":["chatId","content","createdAt","role"],"type":"object","properties":{"chatId":{"type":"integer","description":"채팅 ID","format":"int64","example":1},"role":{"type":"string","description":"발신자 역할","example":"USER","enum":["AI","USER"]},"content":{"type":"string","description":"메시지 내용","example":"안녕하세요!"},"createdAt":{"type":"string","description":"생성일시","format":"date-time"}},"description":"채팅 로그 응답","nullable":true},"ApiResponseMeResponseDTO":{"required":["code","isSuccess","message"],"type":"object","properties":{"isSuccess":{"type":"boolean","description":"요청 성공 여부","example":true},"code":{"type":"string","description":"응답 코드","example":"COMMON200"},"message":{"type":"string","description":"응답 메시지","example":"성공입니다."},"result":{"$ref":"#/components/schemas/MeResponseDTO"}},"description":"API 응답 래퍼"},"MeResponseDTO":{"required":["usage","userId"],"type":"object","properties":{"userId":{"type":"integer","description":"사용자 ID","format":"int64","example":1},"email":{"type":"string","description":"이메일","nullable":true,"example":"user@example.com"},"nickname":{"type":"string","description":"닉네임","nullable":true,"example":"홍길동"},"oauthProvider":{"type":"string","description":"OAuth 제공자. 후보: GOOGLE, KAKAO, APPLE","nullable":true,"example":"GOOGLE","enum":["GOOGLE","KAKAO","APPLE"]},"usage":{"$ref":"#/components/schemas/UsageDTO"}},"description":"유저 정보 조회 응답","nullable":true},"UsageDTO":{"required":["dailyQuotaLimit","dailyQuotaRemaining","dailyQuotaUsed","quotaDate"],"type":"object","properties":{"dailyQuotaRemaining":{"type":"integer","description":"오늘 남은 쿼터","format":"int32","example":97},"dailyQuotaLimit":{"type":"integer","description":"일일 쿼터 제한(고정값 - 서버 상수)","format":"int32","example":100},"dailyQuotaUsed":{"type":"integer","description":"오늘 사용한 쿼터","format":"int32","example":3},"quotaDate":{"type":"string","description":"사용량 기준 날짜(DB 저장값 그대로)","format":"date","example":"2026-01-10"}},"description":"일일 사용량(쿼터) 정보"},"ApiResponseEntitlementsResponse":{"required":["code","isSuccess","message"],"type":"object","properties":{"isSuccess":{"type":"boolean","description":"요청 성공 여부","example":true},"code":{"type":"string","description":"응답 코드","example":"COMMON200"},"message":{"type":"string","description":"응답 메시지","example":"성공입니다."},"result":{"$ref":"#/components/schemas/EntitlementsResponse"}},"description":"API 응답 래퍼"},"EntitlementsResponse":{"required":["entitlements","features"],"type":"object","properties":{"entitlements":{"type":"array","description":"활성 권한 목록","items":{"$ref":"#/components/schemas/EntitlementSummary"}},"features":{"$ref":"#/components/schemas/FeatureSummary"}},"description":"현재 사용자의 활성 권한 응답","nullable":true},"ApiResponseBoolean":{"required":["code","isSuccess","message"],"type":"object","properties":{"isSuccess":{"type":"boolean","description":"요청 성공 여부","example":true},"code":{"type":"string","description":"응답 코드","example":"COMMON200"},"message":{"type":"string","description":"응답 메시지","example":"성공입니다."},"result":{"type":"boolean","description":"응답 데이터","nullable":true}},"description":"API 응답 래퍼"},"ApiResponseTermVersionDetailResponse":{"required":["code","isSuccess","message"],"type":"object","properties":{"isSuccess":{"type":"boolean","description":"요청 성공 여부","example":true},"code":{"type":"string","description":"응답 코드","example":"COMMON200"},"message":{"type":"string","description":"응답 메시지","example":"성공입니다."},"result":{"$ref":"#/components/schemas/TermVersionDetailResponse"}},"description":"API 응답 래퍼"},"TermVersionDetailResponse":{"required":["content","contentFormat","effectiveFrom","required","termCode","termVersionId","title","version"],"type":"object","properties":{"termCode":{"type":"string","description":"약관 코드. 초기 후보: SERVICE_TERMS(서비스 이용약관), PRIVACY_POLICY(개인정보 처리방침), MARKETING(마케팅 정보 수신 동의)","example":"SERVICE_TERMS","enum":["SERVICE_TERMS","PRIVACY_POLICY","MARKETING"]},"title":{"type":"string","description":"약관 제목","example":"서비스 이용약관"},"required":{"type":"boolean","description":"필수 약관 여부. true면 동의해야 서비스 이용 가능","example":true},"termVersionId":{"type":"integer","description":"약관 버전 ID","format":"int64","example":1},"version":{"type":"string","description":"약관 버전","example":"1.0"},"effectiveFrom":{"type":"string","description":"약관 효력 발생 시각","format":"date-time"},"contentFormat":{"type":"string","description":"약관 본문 형식. 후보: TEXT(일반 텍스트), HTML(HTML), MARKDOWN(마크다운)","example":"TEXT","enum":["TEXT","HTML","MARKDOWN"]},"content":{"type":"string","description":"약관 본문"}},"description":"약관 버전 상세 응답","nullable":true},"AgreementStatusResponse":{"required":["agreementRequired","reason","submitContext","terms"],"type":"object","properties":{"agreementRequired":{"type":"boolean","description":"서비스 진입 전 약관 동의 화면이 필요한지 여부. true면 서비스 진입 전 약관 동의 화면으로 이동","example":true},"reason":{"type":"string","description":"약관 동의 상태 사유. 후보: NONE(필요 없음), INITIAL_REQUIRED_TERMS(최초 필수 약관 동의 필요), UPDATED_REQUIRED_TERMS(개정된 필수 약관 재동의 필요), OPTIONAL_TERMS_AVAILABLE(선택 약관 동의/변경 가능)","example":"INITIAL_REQUIRED_TERMS","enum":["NONE","INITIAL_REQUIRED_TERMS","UPDATED_REQUIRED_TERMS","OPTIONAL_TERMS_AVAILABLE"]},"submitContext":{"type":"string","description":"프론트가 POST /api/v1/terms/agreements 호출 시 context로 사용할 값. 후보: NONE, SIGNUP, RECONSENT, OPTIONAL_UPDATE","example":"SIGNUP","enum":["NONE","SIGNUP","RECONSENT","OPTIONAL_UPDATE"]},"terms":{"type":"array","description":"현재 사용자 기준 약관 항목 목록","items":{"$ref":"#/components/schemas/TermItemResponse"}}},"description":"약관 동의 상태 응답","nullable":true},"ApiResponseAgreementStatusResponse":{"required":["code","isSuccess","message"],"type":"object","properties":{"isSuccess":{"type":"boolean","description":"요청 성공 여부","example":true},"code":{"type":"string","description":"응답 코드","example":"COMMON200"},"message":{"type":"string","description":"응답 메시지","example":"성공입니다."},"result":{"$ref":"#/components/schemas/AgreementStatusResponse"}},"description":"API 응답 래퍼"},"TermItemResponse":{"required":["action","agreed","blocking","content","contentUrl","currentTermVersionId","currentVersion","needsAgreement","previousVersion","required","requiresReconsent","termCode","title","updated"],"type":"object","properties":{"termCode":{"type":"string","description":"약관 코드. 초기 후보: SERVICE_TERMS(서비스 이용약관), PRIVACY_POLICY(개인정보 처리방침), MARKETING(마케팅 정보 수신 동의)","example":"SERVICE_TERMS","enum":["SERVICE_TERMS","PRIVACY_POLICY","MARKETING"]},"title":{"type":"string","description":"약관 제목","example":"서비스 이용약관"},"required":{"type":"boolean","description":"필수 약관 여부. true면 동의해야 서비스 이용 가능","example":true},"currentTermVersionId":{"type":"integer","description":"현재 최신 약관 버전 ID","format":"int64","example":1},"currentVersion":{"type":"string","description":"현재 최신 약관 버전","example":"1.0"},"previousVersion":{"type":"string","description":"사용자가 이전에 결정한 약관 버전. 최초 동의 전이면 null","nullable":true,"example":"1.0"},"agreed":{"type":"boolean","description":"현재 최신 버전에 동의한 상태인지 여부. true면 해당 currentTermVersionId에 이미 동의한 상태","example":false},"needsAgreement":{"type":"boolean","description":"이번 화면에서 사용자에게 새 동의/거절 결정을 받아야 하는지 여부","example":true},"updated":{"type":"boolean","description":"사용자 이전 결정 버전과 현재 최신 버전이 다른지 여부","example":false},"requiresReconsent":{"type":"boolean","description":"현재 최신 버전이 재동의를 요구하는지 여부","example":true},"blocking":{"type":"boolean","description":"동의 전 서비스 진입 차단 여부. true면 해당 약관 동의 전 서비스 진입 차단","example":true},"action":{"type":"string","description":"프론트 화면 분기용 서버 계산 액션. 후보: NONE(처리 없음), INITIAL_AGREEMENT_REQUIRED(최초 동의 필요), RECONSENT_REQUIRED(필수 약관 재동의 필요), OPTIONAL_CONSENT_AVAILABLE(선택 약관 동의 가능), OPTIONAL_RECONSENT_AVAILABLE(선택 약관 재동의 가능)","example":"INITIAL_AGREEMENT_REQUIRED","enum":["NONE","INITIAL_AGREEMENT_REQUIRED","RECONSENT_REQUIRED","OPTIONAL_CONSENT_AVAILABLE","OPTIONAL_RECONSENT_AVAILABLE"]},"contentUrl":{"type":"string","description":"약관 본문 상세 조회 URL","nullable":true,"example":"/api/v1/terms/versions/1"},"content":{"type":"string","description":"약관 본문. agreement-screen 응답에서만 포함","nullable":true}},"description":"약관 항목 응답"},"ApiResponseCurrentStreakResponse":{"required":["code","isSuccess","message"],"type":"object","properties":{"isSuccess":{"type":"boolean","description":"요청 성공 여부","example":true},"code":{"type":"string","description":"응답 코드","example":"COMMON200"},"message":{"type":"string","description":"응답 메시지","example":"성공입니다."},"result":{"$ref":"#/components/schemas/CurrentStreakResponse"}},"description":"API 응답 래퍼"},"CurrentStreakResponse":{"required":["streakDays"],"type":"object","properties":{"streakDays":{"type":"integer","description":"현재 스트릭(연속 작성 일수). 오늘 작성이 없으면 0","format":"int32","example":7}},"description":"스트릭 조회 응답","nullable":true},"ApiResponseMemoryResponse":{"required":["code","isSuccess","message"],"type":"object","properties":{"isSuccess":{"type":"boolean","description":"요청 성공 여부","example":true},"code":{"type":"string","description":"응답 코드","example":"COMMON200"},"message":{"type":"string","description":"응답 메시지","example":"성공입니다."},"result":{"$ref":"#/components/schemas/MemoryResponse"}},"description":"API 응답 래퍼"},"MemoryResponse":{"required":["hasMemory"],"type":"object","properties":{"memoryContent":{"type":"string","description":"메모리 내용","nullable":true,"example":"사용자는 커피를 좋아합니다."},"lastUpdatedAt":{"type":"string","description":"마지막 수정일시","format":"date-time","nullable":true},"hasMemory":{"type":"boolean","description":"메모리 존재 여부","example":true}},"description":"사용자 메모리 응답","nullable":true},"ApiResponseListTokenResponse":{"required":["code","isSuccess","message"],"type":"object","properties":{"isSuccess":{"type":"boolean","description":"요청 성공 여부","example":true},"code":{"type":"string","description":"응답 코드","example":"COMMON200"},"message":{"type":"string","description":"응답 메시지","example":"성공입니다."},"result":{"type":"array","description":"응답 데이터","nullable":true,"items":{"$ref":"#/components/schemas/TokenResponse"}}},"description":"API 응답 래퍼"},"ApiResponseChatListResponse":{"required":["code","isSuccess","message"],"type":"object","properties":{"isSuccess":{"type":"boolean","description":"요청 성공 여부","example":true},"code":{"type":"string","description":"응답 코드","example":"COMMON200"},"message":{"type":"string","description":"응답 메시지","example":"성공입니다."},"result":{"$ref":"#/components/schemas/ChatListResponse"}},"description":"API 응답 래퍼"},"ChatListResponse":{"required":["aiProfileImageS3","aiProfileName","chats"],"type":"object","properties":{"aiProfileName":{"type":"string","description":"스레드의 AI 프로필 이름 (서버 주입)","example":"루나"},"aiProfileImageS3":{"type":"string","description":"스레드의 AI 프로필 이미지 URL (서버 주입)","example":"https://s3.amazonaws.com/..."},"chats":{"type":"array","description":"채팅 목록","items":{"$ref":"#/components/schemas/ChatResponse"}}},"description":"채팅 목록 응답","nullable":true},"ApiResponseListDailyPreviewResponseDTO":{"required":["code","isSuccess","message"],"type":"object","properties":{"isSuccess":{"type":"boolean","description":"요청 성공 여부","example":true},"code":{"type":"string","description":"응답 코드","example":"COMMON200"},"message":{"type":"string","description":"응답 메시지","example":"성공입니다."},"result":{"type":"array","description":"응답 데이터","nullable":true,"items":{"$ref":"#/components/schemas/DailyPreviewResponseDTO"}}},"description":"API 응답 래퍼"},"DailyPreviewResponseDTO":{"required":["day","diaries","month","year"],"type":"object","properties":{"year":{"type":"integer","description":"년도","format":"int32","example":2025},"month":{"type":"integer","description":"월","format":"int32","example":1},"day":{"type":"integer","description":"일","format":"int32","example":15},"diaries":{"type":"array","description":"일기 미리보기 목록 (최대 3개)","items":{"$ref":"#/components/schemas/DiaryPreviewDTO"}}},"description":"날짜별 일기 미리보기 응답","nullable":true},"DiaryPreviewDTO":{"required":["aiProfileId","diaryId","type"],"type":"object","properties":{"diaryId":{"type":"integer","description":"일기 ID","format":"int64","example":1},"aiProfileId":{"type":"integer","description":"AI 프로필 ID","format":"int64","example":1},"type":{"type":"string","description":"일기 생성 타입 (MANUAL: 수동 작성, CHAT_BASED: 채팅 기반 자동 생성)","example":"MANUAL","enum":["MANUAL","CHAT_BASED"]},"hashtag1":{"type":"string","description":"해시태그 1","nullable":true,"example":"#좋은하루"},"hashtag2":{"type":"string","description":"해시태그 2","nullable":true,"example":"#감사"},"imageUrl":{"type":"string","description":"이미지 URL","nullable":true,"example":"https://s3.amazonaws.com/..."},"imageStatus":{"type":"string","description":"이미지 생성 상태","nullable":true,"example":"READY","enum":["NONE","PENDING","READY","FAILED"]}},"description":"일기 미리보기"},"ApiResponseListDailySummaryResponseDTO":{"required":["code","isSuccess","message"],"type":"object","properties":{"isSuccess":{"type":"boolean","description":"요청 성공 여부","example":true},"code":{"type":"string","description":"응답 코드","example":"COMMON200"},"message":{"type":"string","description":"응답 메시지","example":"성공입니다."},"result":{"type":"array","description":"응답 데이터","nullable":true,"items":{"$ref":"#/components/schemas/DailySummaryResponseDTO"}}},"description":"API 응답 래퍼"},"DailySummaryResponseDTO":{"required":["day","diaries","month","year"],"type":"object","properties":{"year":{"type":"integer","description":"년도","format":"int32","example":2025},"month":{"type":"integer","description":"월","format":"int32","example":1},"day":{"type":"integer","description":"일","format":"int32","example":15},"diaries":{"type":"array","description":"일기 목록 (최대 3개)","items":{"$ref":"#/components/schemas/DiaryDetailDTO"}}},"description":"날짜별 일기 상세 응답","nullable":true},"DiaryDetailDTO":{"required":["aiProfileId","createdAt","diaryId","type","version"],"type":"object","properties":{"diaryId":{"type":"integer","description":"일기 ID","format":"int64","example":1},"aiProfileId":{"type":"integer","description":"AI 프로필 ID","format":"int64","example":1},"title":{"type":"string","description":"일기 제목","nullable":true,"example":"오늘의 일기"},"content":{"type":"string","description":"일기 내용","nullable":true,"example":"오늘은 좋은 하루였다."},"mood":{"type":"string","description":"기분 (기본값: HAPPY)","nullable":true,"example":"HAPPY","enum":["HAPPY","SAD","TIRED","ANGRY","RELAX"]},"type":{"type":"string","description":"일기 생성 타입 (MANUAL: 수동 작성, CHAT_BASED: 채팅 기반 자동 생성)","example":"MANUAL","enum":["MANUAL","CHAT_BASED"]},"hashtag1":{"type":"string","description":"해시태그 1","nullable":true,"example":"#좋은하루"},"hashtag2":{"type":"string","description":"해시태그 2","nullable":true,"example":"#감사"},"imageUrl":{"type":"string","description":"이미지 URL","nullable":true,"example":"https://s3.amazonaws.com/..."},"imageStatus":{"type":"string","description":"이미지 생성 상태","nullable":true,"example":"READY","enum":["NONE","PENDING","READY","FAILED"]},"version":{"type":"integer","description":"버전","format":"int32","example":1},"createdAt":{"type":"string","description":"생성일시","format":"date-time"}},"description":"일기 상세 정보"},"ApiResponseFeedResponseDTO":{"required":["code","isSuccess","message"],"type":"object","properties":{"isSuccess":{"type":"boolean","description":"요청 성공 여부","example":true},"code":{"type":"string","description":"응답 코드","example":"COMMON200"},"message":{"type":"string","description":"응답 메시지","example":"성공입니다."},"result":{"$ref":"#/components/schemas/FeedResponseDTO"}},"description":"API 응답 래퍼"},"FeedNextCursorDTO":{"required":["cursorDiaryId"],"type":"object","properties":{"cursorDiaryId":{"type":"integer","description":"커서 diaryId (서버가 내려준 값을 그대로 재전송)","format":"int64","example":401}},"description":"피드 다음 커서","nullable":true},"FeedPageInfoDTO":{"required":["hasNext"],"type":"object","properties":{"hasNext":{"type":"boolean","description":"다음 페이지 존재 여부","example":true},"nextCursor":{"$ref":"#/components/schemas/FeedNextCursorDTO"}},"description":"피드 페이지 정보"},"FeedResponseDTO":{"required":["days","pageInfo"],"type":"object","properties":{"days":{"type":"array","description":"일자별 일기 목록 (최신순 피드)","items":{"$ref":"#/components/schemas/DailySummaryResponseDTO"}},"pageInfo":{"$ref":"#/components/schemas/FeedPageInfoDTO"}},"description":"피드 조회 응답","nullable":true},"ApiResponseDailySummaryResponseDTO":{"required":["code","isSuccess","message"],"type":"object","properties":{"isSuccess":{"type":"boolean","description":"요청 성공 여부","example":true},"code":{"type":"string","description":"응답 코드","example":"COMMON200"},"message":{"type":"string","description":"응답 메시지","example":"성공입니다."},"result":{"$ref":"#/components/schemas/DailySummaryResponseDTO"}},"description":"API 응답 래퍼"},"AiProfileResponse":{"required":["aiProfileId","createdAt","feature1","feature2","feature3","hashTag1","hashTag2","imageUrl","profileName"],"type":"object","properties":{"aiProfileId":{"type":"integer","description":"AI 프로필 ID","format":"int64","example":1},"profileName":{"type":"string","description":"프로필 이름","example":"루나"},"imageUrl":{"type":"string","description":"프로필 이미지 URL (서버 주입)","example":"https://s3.amazonaws.com/..."},"hashTag1":{"type":"string","description":"해시태그 1 (서버 주입)","example":"#위로"},"hashTag2":{"type":"string","description":"해시태그 2 (서버 주입)","example":"#공감"},"feature1":{"type":"string","description":"특징 1 (서버 주입)","example":"공감을 잘해요"},"feature2":{"type":"string","description":"특징 2 (서버 주입)","example":"위로를 잘해요"},"feature3":{"type":"string","description":"특징 3 (서버 주입)","example":"따뜻해요"},"createdAt":{"type":"string","description":"생성일시","format":"date-time"},"default":{"type":"boolean"}},"description":"AI 프로필 응답","nullable":true},"ApiResponseListAiProfileResponse":{"required":["code","isSuccess","message"],"type":"object","properties":{"isSuccess":{"type":"boolean","description":"요청 성공 여부","example":true},"code":{"type":"string","description":"응답 코드","example":"COMMON200"},"message":{"type":"string","description":"응답 메시지","example":"성공입니다."},"result":{"type":"array","description":"응답 데이터","nullable":true,"items":{"$ref":"#/components/schemas/AiProfileResponse"}}},"description":"API 응답 래퍼"},"ApiResponseAiProfileResponse":{"required":["code","isSuccess","message"],"type":"object","properties":{"isSuccess":{"type":"boolean","description":"요청 성공 여부","example":true},"code":{"type":"string","description":"응답 코드","example":"COMMON200"},"message":{"type":"string","description":"응답 메시지","example":"성공입니다."},"result":{"$ref":"#/components/schemas/AiProfileResponse"}},"description":"API 응답 래퍼"},"AiProfileQuestionResponse":{"required":["createdAt","q1","q2","q3","q4","q5","q6"],"type":"object","properties":{"q1":{"type":"string","description":"질문 1 (서버 주입)","example":"어떤 말투를 원하시나요?"},"q2":{"type":"string","description":"질문 2 (서버 주입)","example":"답변 길이는 어떻게 할까요?"},"q3":{"type":"string","description":"질문 3 (서버 주입)","example":"어떤 성격이면 좋겠나요?"},"q4":{"type":"string","description":"질문 4 (서버 주입)","example":"어떤 대화를 원하시나요?"},"q5":{"type":"string","description":"질문 5 (서버 주입)","example":"어떤 반응을 원하시나요?"},"q6":{"type":"string","description":"질문 6 (서버 주입)","example":"추가 요청사항이 있나요?"},"createdAt":{"type":"string","description":"생성일시","format":"date-time"}},"description":"AI 프로필 생성 질문 응답","nullable":true},"ApiResponseAiProfileQuestionResponse":{"required":["code","isSuccess","message"],"type":"object","properties":{"isSuccess":{"type":"boolean","description":"요청 성공 여부","example":true},"code":{"type":"string","description":"응답 코드","example":"COMMON200"},"message":{"type":"string","description":"응답 메시지","example":"성공입니다."},"result":{"$ref":"#/components/schemas/AiProfileQuestionResponse"}},"description":"API 응답 래퍼"},"ApiResponseDeleteResultDTO":{"required":["code","isSuccess","message"],"type":"object","properties":{"isSuccess":{"type":"boolean","description":"요청 성공 여부","example":true},"code":{"type":"string","description":"응답 코드","example":"COMMON200"},"message":{"type":"string","description":"응답 메시지","example":"성공입니다."},"result":{"$ref":"#/components/schemas/DeleteResultDTO"}},"description":"API 응답 래퍼"},"DeleteResultDTO":{"required":["userId"],"type":"object","properties":{"userId":{"type":"integer","description":"사용자 ID","format":"int64","example":1},"oauthProvider":{"type":"string","description":"OAuth 제공자. 후보: GOOGLE, KAKAO, APPLE","nullable":true,"example":"GOOGLE","enum":["GOOGLE","KAKAO","APPLE"]},"providerId":{"type":"string","description":"제공자 ID","nullable":true,"example":"1234567890"},"email":{"type":"string","description":"이메일","nullable":true,"example":"user@example.com"},"nickname":{"type":"string","description":"닉네임","nullable":true,"example":"홍길동"}},"description":"회원 탈퇴 결과","nullable":true},"ApiResponseDeleteAgreementHistoryResponse":{"required":["code","isSuccess","message"],"type":"object","properties":{"isSuccess":{"type":"boolean","description":"요청 성공 여부","example":true},"code":{"type":"string","description":"응답 코드","example":"COMMON200"},"message":{"type":"string","description":"응답 메시지","example":"성공입니다."},"result":{"$ref":"#/components/schemas/DeleteAgreementHistoryResponse"}},"description":"API 응답 래퍼"},"DeleteAgreementHistoryResponse":{"required":["agreementRequired","deletedCount","reason"],"type":"object","properties":{"deletedCount":{"type":"integer","description":"삭제된 사용자 약관 동의 이력 수","format":"int64","example":3},"agreementRequired":{"type":"boolean","description":"삭제 후 서비스 진입 전 약관 동의 화면이 필요한지 여부","example":true},"reason":{"type":"string","description":"삭제 후 약관 동의 상태 사유. 후보: NONE(필요 없음), INITIAL_REQUIRED_TERMS(최초 필수 약관 동의 필요), UPDATED_REQUIRED_TERMS(개정된 필수 약관 재동의 필요), OPTIONAL_TERMS_AVAILABLE(선택 약관 동의/변경 가능)","example":"INITIAL_REQUIRED_TERMS","enum":["NONE","INITIAL_REQUIRED_TERMS","UPDATED_REQUIRED_TERMS","OPTIONAL_TERMS_AVAILABLE"]}},"description":"약관 동의 이력 삭제 응답","nullable":true},"ApiResponseMemoryResetResponse":{"required":["code","isSuccess","message"],"type":"object","properties":{"isSuccess":{"type":"boolean","description":"요청 성공 여부","example":true},"code":{"type":"string","description":"응답 코드","example":"COMMON200"},"message":{"type":"string","description":"응답 메시지","example":"성공입니다."},"result":{"$ref":"#/components/schemas/MemoryResetResponse"}},"description":"API 응답 래퍼"},"MemoryResetResponse":{"required":["message","resetAt"],"type":"object","properties":{"message":{"type":"string","description":"결과 메시지","example":"메모리가 초기화되었습니다."},"resetAt":{"type":"string","description":"초기화 일시","format":"date-time"}},"description":"사용자 메모리 초기화 응답","nullable":true},"ApiResponseDeleteResponse":{"required":["code","isSuccess","message"],"type":"object","properties":{"isSuccess":{"type":"boolean","description":"요청 성공 여부","example":true},"code":{"type":"string","description":"응답 코드","example":"COMMON200"},"message":{"type":"string","description":"응답 메시지","example":"성공입니다."},"result":{"$ref":"#/components/schemas/DeleteResponse"}},"description":"API 응답 래퍼"},"DeleteResponse":{"required":["expoPushToken","message"],"type":"object","properties":{"expoPushToken":{"type":"string","description":"삭제된 Expo Push Token","example":"ExponentPushToken[xxxxxxxxxxxxxxxxxxxxxx]"},"message":{"type":"string","description":"결과 메시지","example":"토큰이 삭제되었습니다."}},"description":"Expo Push Token 삭제 응답","nullable":true},"ApiResponseDiaryDeleteResponse":{"required":["code","isSuccess","message"],"type":"object","properties":{"isSuccess":{"type":"boolean","description":"요청 성공 여부","example":true},"code":{"type":"string","description":"응답 코드","example":"COMMON200"},"message":{"type":"string","description":"응답 메시지","example":"성공입니다."},"result":{"$ref":"#/components/schemas/DiaryDeleteResponse"}},"description":"API 응답 래퍼"},"DiaryDeleteResponse":{"required":["diaryId","message"],"type":"object","properties":{"diaryId":{"type":"integer","description":"삭제된 일기 ID","format":"int64","example":1},"message":{"type":"string","description":"결과 메시지","example":"일기가 삭제되었습니다."}},"description":"일기 삭제 응답","nullable":true},"ApiResponseChatLogDeleteResponse":{"required":["code","isSuccess","message"],"type":"object","properties":{"isSuccess":{"type":"boolean","description":"요청 성공 여부","example":true},"code":{"type":"string","description":"응답 코드","example":"COMMON200"},"message":{"type":"string","description":"응답 메시지","example":"성공입니다."},"result":{"$ref":"#/components/schemas/ChatLogDeleteResponse"}},"description":"API 응답 래퍼"},"ChatLogDeleteResponse":{"required":["chatId","message"],"type":"object","properties":{"chatId":{"type":"integer","description":"삭제된 채팅 ID","format":"int64","example":1},"message":{"type":"string","description":"결과 메시지","example":"채팅 메시지가 삭제되었습니다."}},"description":"채팅 로그 삭제 응답","nullable":true}},"securitySchemes":{"JWT TOKEN":{"type":"http","scheme":"bearer","bearerFormat":"JWT"}}}}