docs(ai-character): 관리자 API 계약과 검증 기록을 갱신한다

This commit is contained in:
2026-07-30 00:35:34 +09:00
parent d86a9fb059
commit 5a90fbf98e
11 changed files with 9179 additions and 287 deletions

View File

@@ -2,17 +2,17 @@
"openapi": "3.1.0",
"info": {
"title": "AI 캐릭터 관리자 API",
"version": "2.0.0",
"description": "클라이언트 개발용 정식 계약. 신규 관리자 endpoint와 path target을 사용하되 JSON 필드명, 타입, optional/nullable, 기본값과 성공 data 형태는 레거시 API를 유지한다. path로 이동한 ID만 body에서 제거한다."
"version": "2.3.0",
"description": "클라이언트 개발용 정식 계약. 신규 관리자 endpoint와 path target을 사용하되 JSON 필드명, 타입, optional/nullable, 기본값과 성공 data 형태는 승인된 예외 외에는 레거시 API를 유지한다. path로 이동한 ID만 body에서 제거한다. AI 캐릭터 관리자 API의 날짜·시간 예외 계약은 timezone query/body 없이 ISO-8601 UTC(Z)를 사용한다."
},
"servers": [{"url": "/", "description": "현재 호스트"}],
"security": [{"bearerAuth": []}],
"tags": [
{"name": "Character", "description": "AI 캐릭터 조회·생성·수정"},
{"name": "AudioContent", "description": "오디오 콘텐츠 테마·조회·생성·수정"},
{"name": "Series", "description": "시리즈연결 콘텐츠 관리"},
{"name": "Community", "description": "커뮤니티 게시글 관리"},
{"name": "FanTalk", "description": "FanTalk 관리자 목록creator reply"}
{"name": "Character", "description": "AI 캐릭터 조회·생성·수정과 등록용 원작 검색"},
{"name": "AudioContent", "description": "오디오 콘텐츠 테마·조회·생성·수정과 댓글 관리"},
{"name": "Series", "description": "시리즈·등록용 장르·연결 콘텐츠 관리"},
{"name": "Community", "description": "커뮤니티 게시글과 댓글 관리"},
{"name": "FanTalk", "description": "FanTalk 관리자 목록·creator reply 작성·수정·팬 원글 삭제"}
],
"paths": {
"/api/v2/admin/ai-characters": {
@@ -21,7 +21,7 @@
"tags": ["Character"],
"summary": "AI 캐릭터 목록/검색",
"operationId": "listAiCharacters",
"x-implementation-status": "implemented-contract-alignment-required",
"x-implementation-status": "implemented",
"x-legacy-sources": ["AdminChatCharacterController.getCharacterList", "AdminChatCharacterController.searchCharacters", "ChatCharacterListPageResponse", "ChatCharacterSearchListPageResponse"],
"parameters": [
{"name": "searchTerm", "in": "query", "required": false, "description": "생략하면 활성 목록, 지정하면 레거시 검색을 수행한다.", "schema": {"type": "string"}},
@@ -43,7 +43,7 @@
"tags": ["Character"],
"summary": "AI 캐릭터 생성",
"operationId": "createAiCharacter",
"x-implementation-status": "implemented-contract-alignment-required",
"x-implementation-status": "implemented",
"x-legacy-sources": ["AdminChatCharacterController.registerCharacter", "ChatCharacterRegisterRequest"],
"requestBody": {"$ref": "#/components/requestBodies/CharacterCreateMultipart"},
"responses": {
@@ -59,13 +59,36 @@
}
}
},
"/api/v2/admin/ai-characters/original-works/search": {
"parameters": [{"$ref": "#/components/parameters/AcceptLanguage"}],
"get": {
"tags": ["Character"],
"summary": "캐릭터 등록용 원작 검색",
"operationId": "searchAiCharacterOriginalWorks",
"x-implementation-status": "implemented",
"x-legacy-sources": ["AdminOriginalWorkController.search", "AdminOriginalWorkService.searchOriginalWorksAll", "OriginalWorkResponse"],
"parameters": [
{"name": "searchTerm", "in": "query", "required": true, "description": "제목·콘텐츠 타입·카테고리 부분 검색어", "schema": {"type": "string"}}
],
"responses": {
"200": {"$ref": "#/components/responses/OriginalWorkSearchSuccess"},
"400": {"$ref": "#/components/responses/BadRequest"},
"401": {"$ref": "#/components/responses/Unauthorized"},
"403": {"$ref": "#/components/responses/Forbidden"},
"404": {"$ref": "#/components/responses/NotFound"},
"405": {"$ref": "#/components/responses/MethodNotAllowed"},
"406": {"$ref": "#/components/responses/NotAcceptable"},
"500": {"$ref": "#/components/responses/InternalServerError"}
}
}
},
"/api/v2/admin/ai-characters/{characterId}": {
"parameters": [{"$ref": "#/components/parameters/AcceptLanguage"}, {"$ref": "#/components/parameters/CharacterId"}],
"get": {
"tags": ["Character"],
"summary": "AI 캐릭터 상세",
"operationId": "getAiCharacter",
"x-implementation-status": "implemented-contract-alignment-required",
"x-implementation-status": "implemented",
"x-legacy-sources": ["AdminChatCharacterController.getCharacterDetail", "ChatCharacterDetailResponse"],
"responses": {
"200": {"$ref": "#/components/responses/CharacterDetailSuccess"},
@@ -83,7 +106,7 @@
"summary": "AI 캐릭터 수정/soft delete",
"description": "레거시 ChatCharacterUpdateRequest의 id만 path characterId로 이동한다.",
"operationId": "updateAiCharacter",
"x-implementation-status": "implemented-contract-alignment-required",
"x-implementation-status": "implemented",
"x-legacy-sources": ["AdminChatCharacterController.updateCharacter", "ChatCharacterUpdateRequest"],
"requestBody": {"$ref": "#/components/requestBodies/CharacterUpdateMultipart"},
"responses": {
@@ -105,7 +128,7 @@
"tags": ["AudioContent"],
"summary": "활성 오디오 콘텐츠 테마 목록",
"operationId": "listAiCharacterAudioContentThemes",
"x-implementation-status": "implemented-contract-alignment-required",
"x-implementation-status": "implemented",
"x-legacy-sources": ["GetAudioContentThemeResponse"],
"responses": {
"200": {"$ref": "#/components/responses/AudioThemeListSuccess"},
@@ -119,13 +142,13 @@
}
}
},
"/api/v2/admin/ai-characters/{characterId}/audio-contents": {
"/api/v2/admin/ai-characters/{characterId}/audio-contents": {
"parameters": [{"$ref": "#/components/parameters/AcceptLanguage"}, {"$ref": "#/components/parameters/CharacterId"}],
"get": {
"tags": ["AudioContent"],
"summary": "오디오 콘텐츠 목록/검색",
"operationId": "listAiCharacterAudioContents",
"x-implementation-status": "implemented-contract-alignment-required",
"x-implementation-status": "implemented",
"x-legacy-sources": ["CreatorAdminContentController.getAudioContentList", "CreatorAdminContentController.searchAudioContent", "GetCreatorAdminContentListResponse"],
"parameters": [
{"name": "search_word", "in": "query", "required": false, "description": "지정하면 레거시 검색을 수행하며 2자 이상이어야 한다.", "schema": {"type": "string"}},
@@ -143,11 +166,11 @@
"500": {"$ref": "#/components/responses/InternalServerError"}
}
},
"post": {
"post": {
"tags": ["AudioContent"],
"summary": "오디오 콘텐츠 생성",
"operationId": "createAiCharacterAudioContent",
"x-implementation-status": "implemented-contract-alignment-required",
"x-implementation-status": "implemented",
"x-legacy-sources": ["AudioContentController.createAudioContent", "CreateAudioContentRequest", "CreateAudioContentResponse"],
"requestBody": {"$ref": "#/components/requestBodies/AudioContentCreateMultipart"},
"responses": {
@@ -163,15 +186,14 @@
}
}
},
"/api/v2/admin/ai-characters/{characterId}/audio-contents/{contentId}": {
"/api/v2/admin/ai-characters/{characterId}/audio-contents/{contentId}": {
"parameters": [{"$ref": "#/components/parameters/AcceptLanguage"}, {"$ref": "#/components/parameters/CharacterId"}, {"$ref": "#/components/parameters/ContentId"}],
"get": {
"get": {
"tags": ["AudioContent"],
"summary": "오디오 콘텐츠 상세",
"operationId": "getAiCharacterAudioContent",
"x-implementation-status": "implemented-contract-alignment-required",
"x-implementation-status": "implemented",
"x-legacy-sources": ["AudioContentController.getDetail", "GetAudioContentDetailResponse"],
"parameters": [{"$ref": "#/components/parameters/Timezone"}],
"responses": {
"200": {"$ref": "#/components/responses/AudioContentDetailSuccess"},
"400": {"$ref": "#/components/responses/BadRequest"},
@@ -188,7 +210,7 @@
"summary": "오디오 콘텐츠 수정/soft delete",
"description": "레거시 UpdateCreatorAdminContentRequest의 id만 path contentId로 이동한다.",
"operationId": "updateAiCharacterAudioContent",
"x-implementation-status": "implemented-contract-alignment-required",
"x-implementation-status": "implemented",
"x-legacy-sources": ["CreatorAdminContentController.modifyAudioContent", "UpdateCreatorAdminContentRequest"],
"requestBody": {"$ref": "#/components/requestBodies/AudioContentUpdateMultipart"},
"responses": {
@@ -204,13 +226,161 @@
}
}
},
"/api/v2/admin/ai-characters/{characterId}/audio-contents/{contentId}/comments": {
"parameters": [
{"$ref": "#/components/parameters/AcceptLanguage"},
{"$ref": "#/components/parameters/CharacterId"},
{"$ref": "#/components/parameters/ContentId"}
],
"get": {
"tags": ["AudioContent"],
"summary": "오디오 콘텐츠 댓글 목록",
"operationId": "listAiCharacterAudioContentComments",
"x-implementation-status": "implemented",
"x-legacy-sources": ["AudioContentCommentController.getCommentList", "GetAudioContentCommentListResponse"],
"parameters": [
{"$ref": "#/components/parameters/Page"},
{"$ref": "#/components/parameters/Size"}
],
"responses": {
"200": {"$ref": "#/components/responses/AudioContentCommentListSuccess"},
"400": {"$ref": "#/components/responses/BadRequest"},
"401": {"$ref": "#/components/responses/Unauthorized"},
"403": {"$ref": "#/components/responses/Forbidden"},
"404": {"$ref": "#/components/responses/NotFound"},
"405": {"$ref": "#/components/responses/MethodNotAllowed"},
"406": {"$ref": "#/components/responses/NotAcceptable"},
"500": {"$ref": "#/components/responses/InternalServerError"}
}
},
"post": {
"tags": ["AudioContent"],
"summary": "오디오 콘텐츠 댓글 또는 답글 작성",
"description": "parentId가 없으면 원댓글, 있으면 같은 콘텐츠의 활성 원댓글에 대한 답글을 target AI 캐릭터 명의로 작성한다.",
"operationId": "createAiCharacterAudioContentComment",
"x-implementation-status": "implemented",
"x-legacy-sources": ["AudioContentCommentController.registerComment", "RegisterCommentRequest"],
"requestBody": {
"required": true,
"content": {"application/json": {"schema": {"$ref": "#/components/schemas/AudioContentCommentCreateRequest"}}}
},
"responses": {
"200": {"$ref": "#/components/responses/NullSuccess"},
"400": {"$ref": "#/components/responses/BadRequest"},
"401": {"$ref": "#/components/responses/Unauthorized"},
"403": {"$ref": "#/components/responses/Forbidden"},
"404": {"$ref": "#/components/responses/NotFound"},
"405": {"$ref": "#/components/responses/MethodNotAllowed"},
"406": {"$ref": "#/components/responses/NotAcceptable"},
"415": {"$ref": "#/components/responses/UnsupportedMediaType"},
"500": {"$ref": "#/components/responses/InternalServerError"}
}
}
},
"/api/v2/admin/ai-characters/{characterId}/audio-contents/{contentId}/comments/{commentId}": {
"parameters": [
{"$ref": "#/components/parameters/AcceptLanguage"},
{"$ref": "#/components/parameters/CharacterId"},
{"$ref": "#/components/parameters/ContentId"},
{"$ref": "#/components/parameters/CommentId"}
],
"put": {
"tags": ["AudioContent"],
"summary": "AI 캐릭터 작성 오디오 콘텐츠 댓글 수정",
"operationId": "updateAiCharacterAudioContentComment",
"x-implementation-status": "implemented",
"x-legacy-sources": ["AudioContentCommentController.modifyComment", "ModifyCommentRequest"],
"requestBody": {
"required": true,
"content": {"application/json": {"schema": {"$ref": "#/components/schemas/CommentUpdateRequest"}}}
},
"responses": {
"200": {"$ref": "#/components/responses/NullSuccess"},
"400": {"$ref": "#/components/responses/BadRequest"},
"401": {"$ref": "#/components/responses/Unauthorized"},
"403": {"$ref": "#/components/responses/Forbidden"},
"404": {"$ref": "#/components/responses/NotFound"},
"405": {"$ref": "#/components/responses/MethodNotAllowed"},
"406": {"$ref": "#/components/responses/NotAcceptable"},
"415": {"$ref": "#/components/responses/UnsupportedMediaType"},
"500": {"$ref": "#/components/responses/InternalServerError"}
}
},
"delete": {
"tags": ["AudioContent"],
"summary": "오디오 콘텐츠 댓글 soft delete",
"description": "target 소유 콘텐츠의 댓글 또는 답글을 작성자와 관계없이 해당 row만 isActive=false로 변경한다. 이미 비활성이면 성공 no-op이며 하위 답글은 변경하지 않는다.",
"operationId": "deleteAiCharacterAudioContentComment",
"x-implementation-status": "implemented",
"x-legacy-sources": ["AudioContentCommentService.modifyComment", "ModifyCommentRequest.isActive"],
"responses": {
"200": {"$ref": "#/components/responses/NullSuccess"},
"400": {"$ref": "#/components/responses/BadRequest"},
"401": {"$ref": "#/components/responses/Unauthorized"},
"403": {"$ref": "#/components/responses/Forbidden"},
"404": {"$ref": "#/components/responses/NotFound"},
"405": {"$ref": "#/components/responses/MethodNotAllowed"},
"406": {"$ref": "#/components/responses/NotAcceptable"},
"500": {"$ref": "#/components/responses/InternalServerError"}
}
}
},
"/api/v2/admin/ai-characters/{characterId}/audio-contents/{contentId}/comments/{commentId}/replies": {
"parameters": [
{"$ref": "#/components/parameters/AcceptLanguage"},
{"$ref": "#/components/parameters/CharacterId"},
{"$ref": "#/components/parameters/ContentId"},
{"$ref": "#/components/parameters/CommentId"}
],
"get": {
"tags": ["AudioContent"],
"summary": "오디오 콘텐츠 댓글 답글 목록",
"operationId": "listAiCharacterAudioContentCommentReplies",
"x-implementation-status": "implemented",
"x-legacy-sources": ["AudioContentCommentController.getCommentReplyList", "GetAudioContentCommentListResponse"],
"parameters": [
{"$ref": "#/components/parameters/Page"},
{"$ref": "#/components/parameters/Size"}
],
"responses": {
"200": {"$ref": "#/components/responses/AudioContentCommentListSuccess"},
"400": {"$ref": "#/components/responses/BadRequest"},
"401": {"$ref": "#/components/responses/Unauthorized"},
"403": {"$ref": "#/components/responses/Forbidden"},
"404": {"$ref": "#/components/responses/NotFound"},
"405": {"$ref": "#/components/responses/MethodNotAllowed"},
"406": {"$ref": "#/components/responses/NotAcceptable"},
"500": {"$ref": "#/components/responses/InternalServerError"}
}
}
},
"/api/v2/admin/ai-characters/series-genres": {
"parameters": [{"$ref": "#/components/parameters/AcceptLanguage"}],
"get": {
"tags": ["Series"],
"summary": "시리즈 등록용 활성 장르 목록",
"operationId": "listAiCharacterSeriesGenres",
"x-implementation-status": "implemented",
"x-legacy-sources": ["AdminContentSeriesGenreController.getSeriesGenreList", "GetSeriesGenreListResponse"],
"responses": {
"200": {"$ref": "#/components/responses/SeriesGenreListSuccess"},
"400": {"$ref": "#/components/responses/BadRequest"},
"401": {"$ref": "#/components/responses/Unauthorized"},
"403": {"$ref": "#/components/responses/Forbidden"},
"404": {"$ref": "#/components/responses/NotFound"},
"405": {"$ref": "#/components/responses/MethodNotAllowed"},
"406": {"$ref": "#/components/responses/NotAcceptable"},
"500": {"$ref": "#/components/responses/InternalServerError"}
}
}
},
"/api/v2/admin/ai-characters/{characterId}/series": {
"parameters": [{"$ref": "#/components/parameters/AcceptLanguage"}, {"$ref": "#/components/parameters/CharacterId"}],
"get": {
"tags": ["Series"],
"summary": "시리즈 목록",
"operationId": "listAiCharacterSeries",
"x-implementation-status": "planned",
"x-implementation-status": "implemented",
"x-legacy-sources": ["CreatorAdminContentSeriesController.getSeriesList", "GetCreatorAdminContentSeriesListResponse"],
"parameters": [{"$ref": "#/components/parameters/Page"}, {"$ref": "#/components/parameters/Size"}],
"responses": {
@@ -228,7 +398,7 @@
"tags": ["Series"],
"summary": "시리즈 생성",
"operationId": "createAiCharacterSeries",
"x-implementation-status": "planned",
"x-implementation-status": "implemented",
"x-legacy-sources": ["CreatorAdminContentSeriesController.createSeries", "CreateSeriesRequest"],
"requestBody": {"$ref": "#/components/requestBodies/SeriesCreateMultipart"},
"responses": {
@@ -250,7 +420,7 @@
"tags": ["Series"],
"summary": "시리즈 순서 변경",
"operationId": "reorderAiCharacterSeries",
"x-implementation-status": "planned",
"x-implementation-status": "implemented",
"x-legacy-sources": ["CreatorAdminContentSeriesController.updateSeriesOrders", "UpdateOrdersRequest"],
"requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/SeriesOrderUpdateRequest"}}}},
"responses": {
@@ -271,9 +441,10 @@
"get": {
"tags": ["Series"],
"summary": "시리즈 상세",
"description": "성공 data는 시리즈 목록 items의 단일 항목과 동일한 schema를 사용한다.",
"operationId": "getAiCharacterSeries",
"x-implementation-status": "planned",
"x-legacy-sources": ["CreatorAdminContentSeriesController.getDetail", "GetCreatorAdminContentSeriesDetailResponse"],
"x-implementation-status": "implemented",
"x-legacy-sources": ["CreatorAdminContentSeriesController.getSeriesList", "GetCreatorAdminContentSeriesListItem"],
"responses": {
"200": {"$ref": "#/components/responses/SeriesDetailSuccess"},
"400": {"$ref": "#/components/responses/BadRequest"},
@@ -290,7 +461,7 @@
"summary": "시리즈 수정/soft delete",
"description": "레거시 ModifySeriesRequest의 seriesId만 path로 이동한다.",
"operationId": "updateAiCharacterSeries",
"x-implementation-status": "planned",
"x-implementation-status": "implemented",
"x-legacy-sources": ["CreatorAdminContentSeriesController.modifySeries", "ModifySeriesRequest"],
"requestBody": {"$ref": "#/components/requestBodies/SeriesUpdateMultipart"},
"responses": {
@@ -312,7 +483,7 @@
"tags": ["Series"],
"summary": "시리즈 연결 콘텐츠 목록",
"operationId": "listAiCharacterSeriesContents",
"x-implementation-status": "planned",
"x-implementation-status": "implemented",
"x-legacy-sources": ["CreatorAdminContentSeriesController.getSeriesContent", "GetCreatorAdminContentSeriesContentResponse"],
"parameters": [{"$ref": "#/components/parameters/Page"}, {"$ref": "#/components/parameters/Size"}],
"responses": {
@@ -331,7 +502,7 @@
"summary": "시리즈 콘텐츠 연결",
"description": "레거시 AddingContentToTheSeriesRequest의 seriesId만 path로 이동한다.",
"operationId": "addAiCharacterSeriesContents",
"x-implementation-status": "planned",
"x-implementation-status": "implemented",
"x-legacy-sources": ["CreatorAdminContentSeriesController.addingContentToTheSeries", "AddingContentToTheSeriesRequest"],
"requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/SeriesContentAddRequest"}}}},
"responses": {
@@ -353,7 +524,7 @@
"tags": ["Series"],
"summary": "시리즈 미연결 콘텐츠 검색",
"operationId": "searchAiCharacterContentsNotInSeries",
"x-implementation-status": "planned",
"x-implementation-status": "implemented",
"x-legacy-sources": ["CreatorAdminContentSeriesController.searchContentNotInSeries", "SearchContentNotInSeriesResponse"],
"parameters": [{"name": "search_word", "in": "query", "required": true, "schema": {"type": "string"}}],
"responses": {
@@ -375,7 +546,7 @@
"summary": "시리즈 콘텐츠 연결 해제",
"description": "레거시 RemoveContentToTheSeriesRequest의 seriesId와 contentId를 path로 이동해 body가 없다.",
"operationId": "removeAiCharacterSeriesContent",
"x-implementation-status": "planned",
"x-implementation-status": "implemented",
"x-legacy-sources": ["CreatorAdminContentSeriesController.removeContentInTheSeries", "RemoveContentToTheSeriesRequest"],
"responses": {
"200": {"$ref": "#/components/responses/NullSuccess"},
@@ -395,9 +566,9 @@
"tags": ["Community"],
"summary": "커뮤니티 게시글 목록",
"operationId": "listAiCharacterCommunityPosts",
"x-implementation-status": "planned",
"x-implementation-status": "implemented",
"x-legacy-sources": ["CreatorCommunityController.getCommunityPostList", "GetCommunityPostListResponse"],
"parameters": [{"$ref": "#/components/parameters/Timezone"}, {"$ref": "#/components/parameters/Page"}, {"$ref": "#/components/parameters/Size"}],
"parameters": [{"$ref": "#/components/parameters/Page"}, {"$ref": "#/components/parameters/Size"}],
"responses": {
"200": {"$ref": "#/components/responses/CommunityPostListSuccess"},
"400": {"$ref": "#/components/responses/BadRequest"},
@@ -413,7 +584,7 @@
"tags": ["Community"],
"summary": "커뮤니티 게시글 등록",
"operationId": "createAiCharacterCommunityPost",
"x-implementation-status": "planned",
"x-implementation-status": "implemented",
"x-legacy-sources": ["CreatorCommunityController.createCommunityPost", "CreateCommunityPostRequest"],
"requestBody": {"$ref": "#/components/requestBodies/CommunityPostCreateMultipart"},
"responses": {
@@ -436,7 +607,7 @@
"summary": "커뮤니티 게시글 수정/고정/soft delete",
"description": "ModifyCommunityPostRequest의 creatorCommunityId와 UpdateCommunityPostFixedRequest의 postId를 path로 이동하고 나머지 레거시 필드를 하나의 request에 합친다.",
"operationId": "updateAiCharacterCommunityPost",
"x-implementation-status": "planned",
"x-implementation-status": "implemented",
"x-legacy-sources": ["CreatorCommunityController.modifyCommunityPost", "CreatorCommunityController.updateCommunityPostFixed", "ModifyCommunityPostRequest", "UpdateCommunityPostFixedRequest"],
"requestBody": {"$ref": "#/components/requestBodies/CommunityPostUpdateMultipart"},
"responses": {
@@ -452,6 +623,134 @@
}
}
},
"/api/v2/admin/ai-characters/{characterId}/community-posts/{postId}/comments": {
"parameters": [
{"$ref": "#/components/parameters/AcceptLanguage"},
{"$ref": "#/components/parameters/CharacterId"},
{"$ref": "#/components/parameters/PostId"}
],
"get": {
"tags": ["Community"],
"summary": "커뮤니티 게시글 댓글 목록",
"operationId": "listAiCharacterCommunityPostComments",
"x-implementation-status": "implemented",
"x-legacy-sources": ["CreatorCommunityController.getCommunityPostCommentList", "GetCommunityPostCommentListResponse"],
"parameters": [
{"$ref": "#/components/parameters/Page"},
{"$ref": "#/components/parameters/Size"}
],
"responses": {
"200": {"$ref": "#/components/responses/CommunityCommentListSuccess"},
"400": {"$ref": "#/components/responses/BadRequest"},
"401": {"$ref": "#/components/responses/Unauthorized"},
"403": {"$ref": "#/components/responses/Forbidden"},
"404": {"$ref": "#/components/responses/NotFound"},
"405": {"$ref": "#/components/responses/MethodNotAllowed"},
"406": {"$ref": "#/components/responses/NotAcceptable"},
"500": {"$ref": "#/components/responses/InternalServerError"}
}
},
"post": {
"tags": ["Community"],
"summary": "커뮤니티 게시글 댓글 또는 답글 작성",
"description": "parentId가 없으면 원댓글, 있으면 같은 게시글의 활성 원댓글에 대한 답글을 target AI 캐릭터 명의로 작성한다.",
"operationId": "createAiCharacterCommunityPostComment",
"x-implementation-status": "implemented",
"x-legacy-sources": ["CreatorCommunityController.createCommunityPostComment", "CreateCommunityPostCommentRequest"],
"requestBody": {
"required": true,
"content": {"application/json": {"schema": {"$ref": "#/components/schemas/CommunityCommentCreateRequest"}}}
},
"responses": {
"200": {"$ref": "#/components/responses/NullSuccess"},
"400": {"$ref": "#/components/responses/BadRequest"},
"401": {"$ref": "#/components/responses/Unauthorized"},
"403": {"$ref": "#/components/responses/Forbidden"},
"404": {"$ref": "#/components/responses/NotFound"},
"405": {"$ref": "#/components/responses/MethodNotAllowed"},
"406": {"$ref": "#/components/responses/NotAcceptable"},
"415": {"$ref": "#/components/responses/UnsupportedMediaType"},
"500": {"$ref": "#/components/responses/InternalServerError"}
}
}
},
"/api/v2/admin/ai-characters/{characterId}/community-posts/{postId}/comments/{commentId}": {
"parameters": [
{"$ref": "#/components/parameters/AcceptLanguage"},
{"$ref": "#/components/parameters/CharacterId"},
{"$ref": "#/components/parameters/PostId"},
{"$ref": "#/components/parameters/CommentId"}
],
"put": {
"tags": ["Community"],
"summary": "AI 캐릭터 작성 커뮤니티 댓글 수정",
"operationId": "updateAiCharacterCommunityPostComment",
"x-implementation-status": "implemented",
"x-legacy-sources": ["CreatorCommunityController.modifyCommunityPostComment", "ModifyCommunityPostCommentRequest"],
"requestBody": {
"required": true,
"content": {"application/json": {"schema": {"$ref": "#/components/schemas/CommentUpdateRequest"}}}
},
"responses": {
"200": {"$ref": "#/components/responses/NullSuccess"},
"400": {"$ref": "#/components/responses/BadRequest"},
"401": {"$ref": "#/components/responses/Unauthorized"},
"403": {"$ref": "#/components/responses/Forbidden"},
"404": {"$ref": "#/components/responses/NotFound"},
"405": {"$ref": "#/components/responses/MethodNotAllowed"},
"406": {"$ref": "#/components/responses/NotAcceptable"},
"415": {"$ref": "#/components/responses/UnsupportedMediaType"},
"500": {"$ref": "#/components/responses/InternalServerError"}
}
},
"delete": {
"tags": ["Community"],
"summary": "커뮤니티 게시글 댓글 soft delete",
"description": "target 소유 게시글의 댓글 또는 답글을 작성자와 관계없이 해당 row만 isActive=false로 변경한다. 이미 비활성이면 성공 no-op이며 하위 답글은 변경하지 않는다.",
"operationId": "deleteAiCharacterCommunityPostComment",
"x-implementation-status": "implemented",
"x-legacy-sources": ["CreatorCommunityService.modifyCommunityPostComment", "ModifyCommunityPostCommentRequest.isActive"],
"responses": {
"200": {"$ref": "#/components/responses/NullSuccess"},
"400": {"$ref": "#/components/responses/BadRequest"},
"401": {"$ref": "#/components/responses/Unauthorized"},
"403": {"$ref": "#/components/responses/Forbidden"},
"404": {"$ref": "#/components/responses/NotFound"},
"405": {"$ref": "#/components/responses/MethodNotAllowed"},
"406": {"$ref": "#/components/responses/NotAcceptable"},
"500": {"$ref": "#/components/responses/InternalServerError"}
}
}
},
"/api/v2/admin/ai-characters/{characterId}/community-posts/{postId}/comments/{commentId}/replies": {
"parameters": [
{"$ref": "#/components/parameters/AcceptLanguage"},
{"$ref": "#/components/parameters/CharacterId"},
{"$ref": "#/components/parameters/PostId"},
{"$ref": "#/components/parameters/CommentId"}
],
"get": {
"tags": ["Community"],
"summary": "커뮤니티 게시글 댓글 답글 목록",
"operationId": "listAiCharacterCommunityPostCommentReplies",
"x-implementation-status": "implemented",
"x-legacy-sources": ["CreatorCommunityController.getCommentReplyList", "GetCommunityPostCommentListResponse"],
"parameters": [
{"$ref": "#/components/parameters/Page"},
{"$ref": "#/components/parameters/Size"}
],
"responses": {
"200": {"$ref": "#/components/responses/CommunityCommentListSuccess"},
"400": {"$ref": "#/components/responses/BadRequest"},
"401": {"$ref": "#/components/responses/Unauthorized"},
"403": {"$ref": "#/components/responses/Forbidden"},
"404": {"$ref": "#/components/responses/NotFound"},
"405": {"$ref": "#/components/responses/MethodNotAllowed"},
"406": {"$ref": "#/components/responses/NotAcceptable"},
"500": {"$ref": "#/components/responses/InternalServerError"}
}
}
},
"/api/v2/admin/ai-characters/{characterId}/fan-talks": {
"parameters": [{"$ref": "#/components/parameters/AcceptLanguage"}, {"$ref": "#/components/parameters/CharacterId"}],
"get": {
@@ -459,7 +758,7 @@
"summary": "FanTalk 관리자 목록",
"description": "공개 v2 응답 필드 형태를 유지하되 관리자 target/ownership 정책을 사용하고 viewer/block 필터를 적용하지 않는다.",
"operationId": "listAiCharacterFanTalks",
"x-implementation-status": "planned",
"x-implementation-status": "implemented",
"x-legacy-sources": ["CreatorChannelFanTalkController.getFanTalkTab", "CreatorChannelFanTalkTabResponse"],
"parameters": [{"$ref": "#/components/parameters/FanTalkPage"}, {"$ref": "#/components/parameters/FanTalkSize"}],
"responses": {
@@ -474,6 +773,31 @@
}
}
},
"/api/v2/admin/ai-characters/{characterId}/fan-talks/{fanTalkId}": {
"parameters": [
{"$ref": "#/components/parameters/AcceptLanguage"},
{"$ref": "#/components/parameters/CharacterId"},
{"$ref": "#/components/parameters/FanTalkId"}
],
"delete": {
"tags": ["FanTalk"],
"summary": "팬 작성 FanTalk 원글 soft delete",
"description": "target 채널의 팬 작성 root만 비활성화하며 이미 비활성이면 성공 no-op이다. 연결 creator reply row는 변경하지 않는다.",
"operationId": "deleteAiCharacterFanTalk",
"x-implementation-status": "implemented",
"x-legacy-sources": ["ExplorerService.modifyCheers", "PutWriteCheersRequest.isActive"],
"responses": {
"200": {"$ref": "#/components/responses/NullSuccess"},
"400": {"$ref": "#/components/responses/BadRequest"},
"401": {"$ref": "#/components/responses/Unauthorized"},
"403": {"$ref": "#/components/responses/Forbidden"},
"404": {"$ref": "#/components/responses/NotFound"},
"405": {"$ref": "#/components/responses/MethodNotAllowed"},
"406": {"$ref": "#/components/responses/NotAcceptable"},
"500": {"$ref": "#/components/responses/InternalServerError"}
}
}
},
"/api/v2/admin/ai-characters/{characterId}/fan-talks/{fanTalkId}/replies": {
"parameters": [{"$ref": "#/components/parameters/AcceptLanguage"}, {"$ref": "#/components/parameters/CharacterId"}, {"$ref": "#/components/parameters/FanTalkId"}],
"post": {
@@ -481,7 +805,7 @@
"summary": "FanTalk 답변 작성",
"description": "사용자가 승인한 예외로 신규 관리자 축약 응답을 반환한다.",
"operationId": "createAiCharacterFanTalkReply",
"x-implementation-status": "planned",
"x-implementation-status": "implemented",
"x-legacy-sources": ["ExplorerController.writeCheers", "PostWriteCheersRequest", "CreatorChannelFanTalkReplyResponse"],
"requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/FanTalkReplyCreateRequest"}}}},
"responses": {
@@ -496,6 +820,29 @@
"500": {"$ref": "#/components/responses/InternalServerError"}
}
}
},
"/api/v2/admin/ai-characters/{characterId}/fan-talks/{fanTalkId}/replies/{replyId}": {
"parameters": [{"$ref": "#/components/parameters/AcceptLanguage"}, {"$ref": "#/components/parameters/CharacterId"}, {"$ref": "#/components/parameters/FanTalkId"}, {"$ref": "#/components/parameters/ReplyId"}],
"put": {
"tags": ["FanTalk"],
"summary": "FanTalk 답변 수정",
"description": "target AI가 작성하고 path의 활성 root에 직접 연결된 reply만 수정한다. 레거시처럼 optional/nullable content와 isActive의 non-null 값만 반영하며 빈 객체는 성공 no-op이다. 비활성 reply는 isActive=true로 재활성화할 수 있고 성공 data는 CreatorChannelFanTalkResponse 필드 형태다.",
"operationId": "updateAiCharacterFanTalkReply",
"x-implementation-status": "implemented",
"x-legacy-sources": ["ExplorerController.modifyCheers", "ExplorerService.modifyCheers", "PutWriteCheersRequest", "CreatorChannelFanTalkResponse"],
"requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/FanTalkReplyUpdateRequest"}}}},
"responses": {
"200": {"$ref": "#/components/responses/FanTalkReplyUpdateSuccess"},
"400": {"$ref": "#/components/responses/BadRequest"},
"401": {"$ref": "#/components/responses/Unauthorized"},
"403": {"$ref": "#/components/responses/Forbidden"},
"404": {"$ref": "#/components/responses/NotFound"},
"405": {"$ref": "#/components/responses/MethodNotAllowed"},
"406": {"$ref": "#/components/responses/NotAcceptable"},
"415": {"$ref": "#/components/responses/UnsupportedMediaType"},
"500": {"$ref": "#/components/responses/InternalServerError"}
}
}
}
},
"components": {
@@ -514,12 +861,13 @@
"ContentId": {"name": "contentId", "in": "path", "required": true, "schema": {"type": "integer", "format": "int64"}},
"SeriesId": {"name": "seriesId", "in": "path", "required": true, "schema": {"type": "integer", "format": "int64"}},
"PostId": {"name": "postId", "in": "path", "required": true, "schema": {"type": "integer", "format": "int64"}},
"CommentId": {"name": "commentId", "in": "path", "required": true, "schema": {"type": "integer", "format": "int64"}},
"FanTalkId": {"name": "fanTalkId", "in": "path", "required": true, "schema": {"type": "integer", "format": "int64"}},
"ReplyId": {"name": "replyId", "in": "path", "required": true, "schema": {"type": "integer", "format": "int64"}},
"Page": {"name": "page", "in": "query", "required": false, "schema": {"type": "integer", "format": "int32", "default": 0, "minimum": 0}},
"Size": {"name": "size", "in": "query", "required": false, "schema": {"type": "integer", "format": "int32", "default": 20, "minimum": 1}},
"FanTalkPage": {"name": "page", "in": "query", "required": false, "description": "공개 v2 정책에서 0 이상으로 보정한다.", "schema": {"type": "integer", "format": "int32", "default": 0}},
"FanTalkSize": {"name": "size", "in": "query", "required": false, "description": "공개 v2 정책에서 20..50으로 보정한다.", "schema": {"type": "integer", "format": "int32", "default": 20}},
"Timezone": {"name": "timezone", "in": "query", "required": true, "example": "Asia/Seoul", "schema": {"type": "string"}}
"FanTalkSize": {"name": "size", "in": "query", "required": false, "description": "공개 v2 정책에서 20..50으로 보정한다.", "schema": {"type": "integer", "format": "int32", "default": 20}}
},
"requestBodies": {
"CharacterCreateMultipart": {
@@ -558,17 +906,22 @@
"responses": {
"CharacterListSuccess": {"description": "성공", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/CharacterListApiResponse"}}}},
"CharacterDetailSuccess": {"description": "성공", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/CharacterDetailApiResponse"}}}},
"OriginalWorkSearchSuccess": {"description": "성공", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/OriginalWorkSearchApiResponse"}}}},
"AudioThemeListSuccess": {"description": "성공", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/AudioThemeListApiResponse"}}}},
"AudioContentListSuccess": {"description": "성공", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/AudioContentListApiResponse"}}}},
"AudioContentCreateSuccess": {"description": "성공", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/AudioContentCreateApiResponse"}}}},
"AudioContentDetailSuccess": {"description": "성공", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/AudioContentDetailApiResponse"}}}},
"AudioContentCommentListSuccess": {"description": "성공", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/AudioContentCommentListApiResponse"}}}},
"SeriesListSuccess": {"description": "성공", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/SeriesListApiResponse"}}}},
"SeriesDetailSuccess": {"description": "성공", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/SeriesDetailApiResponse"}}}},
"SeriesGenreListSuccess": {"description": "성공", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/SeriesGenreListApiResponse"}}}},
"SeriesContentListSuccess": {"description": "성공", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/SeriesContentListApiResponse"}}}},
"SeriesContentSearchSuccess": {"description": "성공", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/SeriesContentSearchApiResponse"}}}},
"CommunityPostListSuccess": {"description": "성공", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/CommunityPostListApiResponse"}}}},
"CommunityCommentListSuccess": {"description": "성공", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/CommunityCommentListApiResponse"}}}},
"FanTalkListSuccess": {"description": "성공", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/FanTalkListApiResponse"}}}},
"FanTalkReplySuccess": {"description": "성공", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/FanTalkReplyApiResponse"}}}},
"FanTalkReplyUpdateSuccess": {"description": "레거시 FanTalk 답변 수정 성공", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/FanTalkReplyUpdateApiResponse"}}}},
"NullSuccess": {"description": "레거시 mutation 성공", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/NullSuccessResponse"}}}},
"BadRequest": {"description": "잘못된 요청/target/domain 오류", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ApiErrorResponse"}}}},
"Unauthorized": {"description": "인증 실패", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ApiErrorResponse"}}}},
@@ -796,6 +1149,27 @@
},
"CharacterListApiResponse": {"allOf": [{"$ref": "#/components/schemas/ApiSuccessBase"}, {"type": "object", "required": ["message", "data", "errorProperty"], "properties": {"message": {"type": ["string", "null"]}, "data": {"$ref": "#/components/schemas/CharacterListResponse"}, "errorProperty": {"type": ["string", "null"], "const": null}}}]},
"CharacterDetailApiResponse": {"allOf": [{"$ref": "#/components/schemas/ApiSuccessBase"}, {"type": "object", "required": ["message", "data", "errorProperty"], "properties": {"message": {"type": ["string", "null"]}, "data": {"$ref": "#/components/schemas/CharacterDetailResponse"}, "errorProperty": {"type": ["string", "null"], "const": null}}}]},
"OriginalWorkSearchItem": {
"type": "object",
"additionalProperties": false,
"required": ["id", "title", "contentType", "category", "isAdult", "description", "originalWork", "originalLink", "writer", "studio", "originalLinks", "tags", "imageUrl"],
"properties": {
"id": {"type": "integer", "format": "int64"},
"title": {"type": "string"},
"contentType": {"type": "string"},
"category": {"type": "string"},
"isAdult": {"type": "boolean"},
"description": {"type": "string"},
"originalWork": {"$ref": "#/components/schemas/NullableString"},
"originalLink": {"$ref": "#/components/schemas/NullableString"},
"writer": {"$ref": "#/components/schemas/NullableString"},
"studio": {"$ref": "#/components/schemas/NullableString"},
"originalLinks": {"type": "array", "items": {"type": "string"}},
"tags": {"type": "array", "items": {"type": "string"}},
"imageUrl": {"$ref": "#/components/schemas/NullableString"}
}
},
"OriginalWorkSearchApiResponse": {"allOf": [{"$ref": "#/components/schemas/ApiSuccessBase"}, {"type": "object", "required": ["message", "data", "errorProperty"], "properties": {"message": {"type": ["string", "null"]}, "data": {"type": "array", "items": {"$ref": "#/components/schemas/OriginalWorkSearchItem"}}, "errorProperty": {"type": ["string", "null"], "const": null}}}]},
"AudioContentTheme": {
"type": "object",
@@ -815,8 +1189,7 @@
"price": {"type": "integer", "format": "int32"},
"purchaseOption": {"$ref": "#/components/schemas/PurchaseOption", "default": "BOTH"},
"limited": {"$ref": "#/components/schemas/NullableInt32"},
"timezone": {"type": "string", "default": "Asia/Seoul"},
"releaseDate": {"type": ["string", "null"], "description": "yyyy-MM-dd HH:mm"},
"releaseDate": {"type": ["string", "null"], "format": "date-time", "pattern": "Z$", "description": "클라이언트가 UTC로 변환해 보내는 ISO-8601 시각. 예: 2026-07-29T09:00:00Z"},
"themeId": {"type": "integer", "format": "int64", "default": 0, "description": "0은 binding 기본값이며 domain validation에서 유효하지 않다."},
"isAdult": {"type": "boolean", "default": false},
"isGeneratePreview": {"type": "boolean", "default": false},
@@ -938,10 +1311,37 @@
"languageCode": {"$ref": "#/components/schemas/NullableString"},
"isSecret": {"type": "boolean"},
"donationCan": {"type": "integer", "format": "int32"},
"date": {"type": "string"},
"date": {"type": "string", "format": "date-time", "pattern": "Z$", "description": "ISO-8601 UTC 시각(Z)"},
"replyCount": {"type": "integer", "format": "int32"}
}
},
"AudioContentCommentCreateRequest": {
"type": "object",
"additionalProperties": false,
"required": ["comment"],
"properties": {
"comment": {"type": "string"},
"parentId": {"$ref": "#/components/schemas/NullableInt64"},
"isSecret": {"type": "boolean", "default": false},
"languageCode": {"$ref": "#/components/schemas/NullableString"}
}
},
"CommentUpdateRequest": {
"type": "object",
"additionalProperties": false,
"required": ["comment"],
"properties": {"comment": {"type": "string"}}
},
"AudioContentCommentListResponse": {
"type": "object",
"additionalProperties": false,
"required": ["totalCount", "items"],
"properties": {
"totalCount": {"type": "integer", "format": "int32"},
"items": {"type": "array", "items": {"$ref": "#/components/schemas/AudioContentComment"}}
}
},
"AudioContentCommentListApiResponse": {"allOf": [{"$ref": "#/components/schemas/ApiSuccessBase"}, {"type": "object", "required": ["message", "data", "errorProperty"], "properties": {"message": {"type": ["string", "null"]}, "data": {"$ref": "#/components/schemas/AudioContentCommentListResponse"}, "errorProperty": {"type": ["string", "null"], "const": null}}}]},
"TranslatedContent": {
"type": "object",
"additionalProperties": false,
@@ -963,7 +1363,7 @@
"tag": {"type": "string"},
"price": {"type": "integer", "format": "int32"},
"duration": {"type": "string"},
"releaseDate": {"$ref": "#/components/schemas/NullableString"},
"releaseDate": {"type": ["string", "null"], "format": "date-time", "pattern": "Z$", "description": "기존 null/노출 조건을 유지하는 ISO-8601 UTC 시각(Z)"},
"totalContentCount": {"$ref": "#/components/schemas/NullableInt32"},
"remainingContentCount": {"$ref": "#/components/schemas/NullableInt32"},
"orderSequence": {"$ref": "#/components/schemas/NullableInt32"},
@@ -1060,22 +1460,14 @@
"required": ["totalCount", "items"],
"properties": {"totalCount": {"type": "integer", "format": "int32"}, "items": {"type": "array", "items": {"$ref": "#/components/schemas/SeriesListItem"}}}
},
"SeriesDetailResponse": {
"SeriesGenreItem": {
"type": "object",
"additionalProperties": false,
"required": ["seriesId", "title", "introduction", "coverImageUrl", "publishedDaysOfWeek", "genre", "keywords", "isAdult", "state", "writer", "studio"],
"required": ["id", "genre", "isAdult"],
"properties": {
"seriesId": {"type": "integer", "format": "int64"},
"title": {"type": "string"},
"introduction": {"type": "string"},
"coverImageUrl": {"type": "string"},
"publishedDaysOfWeek": {"type": "string", "description": "예: 월, 수"},
"id": {"type": "integer", "format": "int64"},
"genre": {"type": "string"},
"keywords": {"type": "string"},
"isAdult": {"type": "boolean"},
"state": {"type": "string", "description": "레거시 String 필드. 현재 관찰 값: 연재중, 휴재중, 완결"},
"writer": {"$ref": "#/components/schemas/NullableString"},
"studio": {"$ref": "#/components/schemas/NullableString"}
"isAdult": {"type": "boolean"}
}
},
"SeriesContentListItem": {
@@ -1109,7 +1501,8 @@
"properties": {"ids": {"type": "array", "items": {"type": "integer", "format": "int64"}}}
},
"SeriesListApiResponse": {"allOf": [{"$ref": "#/components/schemas/ApiSuccessBase"}, {"type": "object", "required": ["message", "data", "errorProperty"], "properties": {"message": {"type": ["string", "null"]}, "data": {"$ref": "#/components/schemas/SeriesListResponse"}, "errorProperty": {"type": ["string", "null"], "const": null}}}]},
"SeriesDetailApiResponse": {"allOf": [{"$ref": "#/components/schemas/ApiSuccessBase"}, {"type": "object", "required": ["message", "data", "errorProperty"], "properties": {"message": {"type": ["string", "null"]}, "data": {"$ref": "#/components/schemas/SeriesDetailResponse"}, "errorProperty": {"type": ["string", "null"], "const": null}}}]},
"SeriesDetailApiResponse": {"allOf": [{"$ref": "#/components/schemas/ApiSuccessBase"}, {"type": "object", "required": ["message", "data", "errorProperty"], "properties": {"message": {"type": ["string", "null"]}, "data": {"$ref": "#/components/schemas/SeriesListItem"}, "errorProperty": {"type": ["string", "null"], "const": null}}}]},
"SeriesGenreListApiResponse": {"allOf": [{"$ref": "#/components/schemas/ApiSuccessBase"}, {"type": "object", "required": ["message", "data", "errorProperty"], "properties": {"message": {"type": ["string", "null"]}, "data": {"type": "array", "items": {"$ref": "#/components/schemas/SeriesGenreItem"}}, "errorProperty": {"type": ["string", "null"], "const": null}}}]},
"SeriesContentListApiResponse": {"allOf": [{"$ref": "#/components/schemas/ApiSuccessBase"}, {"type": "object", "required": ["message", "data", "errorProperty"], "properties": {"message": {"type": ["string", "null"]}, "data": {"$ref": "#/components/schemas/SeriesContentListResponse"}, "errorProperty": {"type": ["string", "null"], "const": null}}}]},
"SeriesContentSearchApiResponse": {"allOf": [{"$ref": "#/components/schemas/ApiSuccessBase"}, {"type": "object", "required": ["message", "data", "errorProperty"], "properties": {"message": {"type": ["string", "null"]}, "data": {"type": "array", "items": {"$ref": "#/components/schemas/SeriesContentSearchItem"}}, "errorProperty": {"type": ["string", "null"], "const": null}}}]},
@@ -1124,10 +1517,30 @@
"profileUrl": {"type": "string"},
"comment": {"type": "string"},
"isSecret": {"type": "boolean"},
"date": {"type": "string"},
"date": {"type": "string", "format": "date-time", "pattern": "Z$", "description": "ISO-8601 UTC 시각(Z)"},
"replyCount": {"type": "integer", "format": "int32"}
}
},
"CommunityCommentCreateRequest": {
"type": "object",
"additionalProperties": false,
"required": ["comment"],
"properties": {
"parentId": {"$ref": "#/components/schemas/NullableInt64"},
"comment": {"type": "string"},
"isSecret": {"type": "boolean", "default": false}
}
},
"CommunityCommentListResponse": {
"type": "object",
"additionalProperties": false,
"required": ["totalCount", "items"],
"properties": {
"totalCount": {"type": "integer", "format": "int32"},
"items": {"type": "array", "items": {"$ref": "#/components/schemas/CommunityPostComment"}}
}
},
"CommunityCommentListApiResponse": {"allOf": [{"$ref": "#/components/schemas/ApiSuccessBase"}, {"type": "object", "required": ["message", "data", "errorProperty"], "properties": {"message": {"type": ["string", "null"]}, "data": {"$ref": "#/components/schemas/CommunityCommentListResponse"}, "errorProperty": {"type": ["string", "null"], "const": null}}}]},
"CommunityPostListItem": {
"type": "object",
"additionalProperties": false,
@@ -1153,6 +1566,18 @@
"firstComment": {"oneOf": [{"$ref": "#/components/schemas/CommunityPostComment"}, {"type": "null"}]}
}
},
"CommunityPostListResponse": {
"type": "object",
"additionalProperties": false,
"required": ["totalCount", "page", "size", "hasNext", "items"],
"properties": {
"totalCount": {"type": "integer", "format": "int64", "minimum": 0},
"page": {"type": "integer", "format": "int32", "minimum": 0},
"size": {"type": "integer", "format": "int32", "minimum": 1},
"hasNext": {"type": "boolean"},
"items": {"type": "array", "items": {"$ref": "#/components/schemas/CommunityPostListItem"}}
}
},
"CommunityPostCreateRequest": {
"type": "object",
"additionalProperties": false,
@@ -1194,7 +1619,7 @@
"request": {"$ref": "#/components/schemas/CommunityPostUpdateRequest"}
}
},
"CommunityPostListApiResponse": {"allOf": [{"$ref": "#/components/schemas/ApiSuccessBase"}, {"type": "object", "required": ["message", "data", "errorProperty"], "properties": {"message": {"type": ["string", "null"]}, "data": {"type": "array", "items": {"$ref": "#/components/schemas/CommunityPostListItem"}}, "errorProperty": {"type": ["string", "null"], "const": null}}}]},
"CommunityPostListApiResponse": {"allOf": [{"$ref": "#/components/schemas/ApiSuccessBase"}, {"type": "object", "required": ["message", "data", "errorProperty"], "properties": {"message": {"type": ["string", "null"]}, "data": {"$ref": "#/components/schemas/CommunityPostListResponse"}, "errorProperty": {"type": ["string", "null"], "const": null}}}]},
"FanTalkCreatorReply": {
"type": "object",
@@ -1241,6 +1666,15 @@
"required": ["content"],
"properties": {"content": {"type": "string"}}
},
"FanTalkReplyUpdateRequest": {
"type": "object",
"additionalProperties": false,
"description": "레거시 PutWriteCheersRequest에서 path로 이동한 cheersId만 제외한다. content와 isActive는 optional/nullable이며 둘 다 생략하거나 null이면 성공 no-op이다.",
"properties": {
"content": {"$ref": "#/components/schemas/NullableString"},
"isActive": {"$ref": "#/components/schemas/NullableBoolean"}
}
},
"FanTalkReplyResponse": {
"type": "object",
"additionalProperties": false,
@@ -1254,7 +1688,8 @@
}
},
"FanTalkListApiResponse": {"allOf": [{"$ref": "#/components/schemas/ApiSuccessBase"}, {"type": "object", "required": ["message", "data", "errorProperty"], "properties": {"message": {"type": ["string", "null"]}, "data": {"$ref": "#/components/schemas/FanTalkListResponse"}, "errorProperty": {"type": ["string", "null"], "const": null}}}]},
"FanTalkReplyApiResponse": {"allOf": [{"$ref": "#/components/schemas/ApiSuccessBase"}, {"type": "object", "required": ["message", "data", "errorProperty"], "properties": {"message": {"type": ["string", "null"]}, "data": {"$ref": "#/components/schemas/FanTalkReplyResponse"}, "errorProperty": {"type": ["string", "null"], "const": null}}}]}
"FanTalkReplyApiResponse": {"allOf": [{"$ref": "#/components/schemas/ApiSuccessBase"}, {"type": "object", "required": ["message", "data", "errorProperty"], "properties": {"message": {"type": ["string", "null"]}, "data": {"$ref": "#/components/schemas/FanTalkReplyResponse"}, "errorProperty": {"type": ["string", "null"], "const": null}}}]},
"FanTalkReplyUpdateApiResponse": {"allOf": [{"$ref": "#/components/schemas/ApiSuccessBase"}, {"type": "object", "required": ["message", "data", "errorProperty"], "properties": {"message": {"type": ["string", "null"]}, "data": {"$ref": "#/components/schemas/FanTalkListItem", "description": "레거시 CreatorChannelFanTalkResponse 필드 형태. fanTalkId는 수정한 reply row ID이며 creatorReplies는 빈 배열이다."}, "errorProperty": {"type": ["string", "null"], "const": null}}}]}
}
}
}