kt-event-marketing/design/backend/api/event-service-api.yaml
cherry2250 6b1c4224f7 7개 마이크로서비스 API 명세서 컨벤션 통일
- 공통 OpenAPI 3.0.3 컨벤션 문서 작성 (design/backend/api/API_CONVENTION.md)
- 7개 서비스 API 명세서 표준화 완료:
  * User Service (8081)
  * Event Service (8080)
  * Content Service (8082)
  * AI Service (8083)
  * Participation Service (8084)
  * Distribution Service (8085)
  * Analytics Service (8086)

주요 변경사항:
- API 경로에서 /api prefix 제거 (/api/users → /users)
- 서버 URL 패턴 통일 (Local → Dev → Prod)
- 연락처 정보 표준화 (Digital Garage Team)
- ErrorResponse 스키마 통일 (error → message, details 추가)
- securitySchemes 이름 통일 (BearerAuth)
- 포트 번호 명확히 할당

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-23 17:12:28 +09:00

1385 lines
41 KiB
YAML

openapi: 3.0.3
info:
title: Event Service API
description: |
KT AI 기반 소상공인 이벤트 자동 생성 서비스 - Event Service API
이벤트 전체 생명주기 관리 (생성, 조회, 수정, 배포, 종료)
- AI 기반 이벤트 추천 및 커스터마이징
- 이미지 생성 및 편집 오케스트레이션
- 배포 채널 관리 및 최종 배포
- 이벤트 상태 관리 (DRAFT, PUBLISHED, ENDED)
version: 1.0.0
contact:
name: Digital Garage Team
email: support@kt-event-marketing.com
servers:
- url: http://localhost:8080
description: Local Development Server
- url: https://dev-api.kt-event-marketing.com/event/v1
description: Development Server
- url: https://api.kt-event-marketing.com/event/v1
description: Production Server
security:
- BearerAuth: []
tags:
- name: Dashboard
description: 대시보드 및 이벤트 목록 조회
- name: Event Creation
description: 이벤트 생성 플로우
- name: Event Management
description: 이벤트 수정, 삭제, 종료
- name: Job Status
description: 비동기 작업 상태 조회
paths:
/events:
get:
tags:
- Dashboard
summary: 이벤트 목록 조회
description: |
사용자의 이벤트 목록을 조회합니다 (대시보드, 전체보기).
필터, 검색, 페이징을 지원합니다.
operationId: getEvents
x-user-story: UFR-EVENT-010, UFR-EVENT-070
x-controller: EventController.getEvents
parameters:
- name: status
in: query
description: 이벤트 상태 필터 (DRAFT, PUBLISHED, ENDED)
required: false
schema:
type: string
enum: [DRAFT, PUBLISHED, ENDED]
example: PUBLISHED
- name: objective
in: query
description: 이벤트 목적 필터
required: false
schema:
type: string
example: 신규 고객 유치
- name: search
in: query
description: 검색어 (이벤트명)
required: false
schema:
type: string
example: 봄맞이
- name: page
in: query
description: 페이지 번호 (0부터 시작)
required: false
schema:
type: integer
minimum: 0
default: 0
example: 0
- name: size
in: query
description: 페이지 크기
required: false
schema:
type: integer
minimum: 1
maximum: 100
default: 20
example: 20
- name: sort
in: query
description: 정렬 기준 (createdAt, startDate, endDate)
required: false
schema:
type: string
enum: [createdAt, startDate, endDate]
default: createdAt
example: createdAt
- name: order
in: query
description: 정렬 순서 (asc, desc)
required: false
schema:
type: string
enum: [asc, desc]
default: desc
example: desc
responses:
'200':
description: 이벤트 목록 조회 성공
content:
application/json:
schema:
$ref: '#/components/schemas/EventListResponse'
'401':
$ref: '#/components/responses/Unauthorized'
'500':
$ref: '#/components/responses/InternalServerError'
/events/{eventId}:
get:
tags:
- Dashboard
summary: 이벤트 상세 조회
description: 특정 이벤트의 상세 정보를 조회합니다.
operationId: getEvent
x-user-story: UFR-EVENT-060
x-controller: EventController.getEvent
parameters:
- $ref: '#/components/parameters/EventId'
responses:
'200':
description: 이벤트 상세 조회 성공
content:
application/json:
schema:
$ref: '#/components/schemas/EventDetailResponse'
'401':
$ref: '#/components/responses/Unauthorized'
'404':
$ref: '#/components/responses/NotFound'
'500':
$ref: '#/components/responses/InternalServerError'
put:
tags:
- Event Management
summary: 이벤트 수정
description: |
기존 이벤트의 정보를 수정합니다.
DRAFT 상태의 이벤트만 전체 수정 가능하며,
PUBLISHED 상태에서는 제한적 수정만 가능합니다.
operationId: updateEvent
x-user-story: UFR-EVENT-060
x-controller: EventController.updateEvent
parameters:
- $ref: '#/components/parameters/EventId'
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/UpdateEventRequest'
responses:
'200':
description: 이벤트 수정 성공
content:
application/json:
schema:
$ref: '#/components/schemas/EventDetailResponse'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'404':
$ref: '#/components/responses/NotFound'
'409':
description: 이벤트 상태로 인해 수정 불가
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
example:
code: EVENT_NOT_MODIFIABLE
message: PUBLISHED 상태의 이벤트는 제한적으로만 수정 가능합니다.
'500':
$ref: '#/components/responses/InternalServerError'
delete:
tags:
- Event Management
summary: 이벤트 삭제
description: |
이벤트를 삭제합니다.
DRAFT 상태의 이벤트만 삭제 가능합니다.
operationId: deleteEvent
x-user-story: UFR-EVENT-070
x-controller: EventController.deleteEvent
parameters:
- $ref: '#/components/parameters/EventId'
responses:
'204':
description: 이벤트 삭제 성공
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'404':
$ref: '#/components/responses/NotFound'
'409':
description: 이벤트 상태로 인해 삭제 불가
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
example:
code: EVENT_NOT_DELETABLE
message: DRAFT 상태의 이벤트만 삭제 가능합니다.
'500':
$ref: '#/components/responses/InternalServerError'
/events/objectives:
post:
tags:
- Event Creation
summary: 이벤트 목적 선택 (Step 1)
description: |
이벤트 생성 플로우의 첫 단계입니다.
사용자가 이벤트 목적을 선택하고 DRAFT 상태의 이벤트를 생성합니다.
operationId: selectObjective
x-user-story: UFR-EVENT-020
x-controller: EventController.selectObjective
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/SelectObjectiveRequest'
responses:
'201':
description: 이벤트 생성 성공 (DRAFT 상태)
content:
application/json:
schema:
$ref: '#/components/schemas/EventCreatedResponse'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'500':
$ref: '#/components/responses/InternalServerError'
/events/{eventId}/ai-recommendations:
post:
tags:
- Event Creation
summary: AI 추천 요청 (Step 2)
description: |
AI 서비스에 이벤트 추천 생성을 요청합니다.
Kafka Job을 발행하고 jobId를 반환합니다.
Job 상태는 /jobs/{jobId}로 폴링하여 확인합니다.
operationId: requestAiRecommendations
x-user-story: UFR-EVENT-030
x-controller: EventController.requestAiRecommendations
parameters:
- $ref: '#/components/parameters/EventId'
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/AiRecommendationRequest'
responses:
'202':
description: AI 추천 요청 접수
content:
application/json:
schema:
$ref: '#/components/schemas/JobAcceptedResponse'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'404':
$ref: '#/components/responses/NotFound'
'409':
description: 이벤트 상태가 적절하지 않음
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
example:
code: INVALID_EVENT_STATE
message: DRAFT 상태의 이벤트만 AI 추천을 요청할 수 있습니다.
'500':
$ref: '#/components/responses/InternalServerError'
/events/{eventId}/recommendations:
put:
tags:
- Event Creation
summary: AI 추천 선택 및 커스터마이징 (Step 2-2)
description: |
AI가 생성한 추천 중 하나를 선택하고,
필요시 이벤트명, 문구, 기간 등을 커스터마이징합니다.
operationId: selectRecommendation
x-user-story: UFR-EVENT-030
x-controller: EventController.selectRecommendation
parameters:
- $ref: '#/components/parameters/EventId'
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/SelectRecommendationRequest'
responses:
'200':
description: AI 추천 선택 및 커스터마이징 성공
content:
application/json:
schema:
$ref: '#/components/schemas/EventDetailResponse'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'404':
$ref: '#/components/responses/NotFound'
'409':
description: 이벤트 상태가 적절하지 않음
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
example:
code: INVALID_EVENT_STATE
message: AI 추천이 완료된 DRAFT 상태의 이벤트만 선택 가능합니다.
'500':
$ref: '#/components/responses/InternalServerError'
/events/{eventId}/images:
post:
tags:
- Event Creation
summary: 이미지 생성 요청 (Step 3)
description: |
Content Service에 이미지 생성을 요청합니다.
Kafka Job을 발행하고 jobId를 반환합니다.
Job 상태는 /jobs/{jobId}로 폴링하여 확인합니다.
operationId: requestImageGeneration
x-user-story: UFR-CONT-010
x-controller: EventController.requestImageGeneration
parameters:
- $ref: '#/components/parameters/EventId'
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/ImageGenerationRequest'
responses:
'202':
description: 이미지 생성 요청 접수
content:
application/json:
schema:
$ref: '#/components/schemas/JobAcceptedResponse'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'404':
$ref: '#/components/responses/NotFound'
'409':
description: 이벤트 상태가 적절하지 않음
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
example:
code: INVALID_EVENT_STATE
message: AI 추천이 선택된 DRAFT 상태의 이벤트만 이미지 생성이 가능합니다.
'500':
$ref: '#/components/responses/InternalServerError'
/events/{eventId}/images/{imageId}/select:
put:
tags:
- Event Creation
summary: 이미지 선택 (Step 3-2)
description: |
생성된 이미지 중 하나를 선택합니다.
선택된 이미지는 이벤트의 대표 이미지로 설정됩니다.
operationId: selectImage
x-user-story: UFR-CONT-010
x-controller: EventController.selectImage
parameters:
- $ref: '#/components/parameters/EventId'
- name: imageId
in: path
description: 이미지 ID
required: true
schema:
type: string
format: uuid
example: "550e8400-e29b-41d4-a716-446655440006"
responses:
'200':
description: 이미지 선택 성공
content:
application/json:
schema:
$ref: '#/components/schemas/EventDetailResponse'
'401':
$ref: '#/components/responses/Unauthorized'
'404':
$ref: '#/components/responses/NotFound'
'409':
description: 이벤트 또는 이미지 상태가 적절하지 않음
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
example:
code: INVALID_IMAGE_STATE
message: 해당 이미지는 이 이벤트에 속하지 않습니다.
'500':
$ref: '#/components/responses/InternalServerError'
/events/{eventId}/images/{imageId}/edit:
put:
tags:
- Event Creation
summary: 이미지 편집 (Step 3-3)
description: |
선택된 이미지를 편집합니다.
Content Service에 편집 요청을 보내고 새로운 이미지 URL을 받습니다.
operationId: editImage
x-user-story: UFR-CONT-020
x-controller: EventController.editImage
parameters:
- $ref: '#/components/parameters/EventId'
- name: imageId
in: path
description: 이미지 ID
required: true
schema:
type: string
format: uuid
example: "550e8400-e29b-41d4-a716-446655440006"
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/ImageEditRequest'
responses:
'200':
description: 이미지 편집 성공
content:
application/json:
schema:
$ref: '#/components/schemas/ImageEditResponse'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'404':
$ref: '#/components/responses/NotFound'
'409':
description: 이미지 상태가 적절하지 않음
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
example:
code: IMAGE_NOT_EDITABLE
message: 선택된 이미지만 편집 가능합니다.
'500':
$ref: '#/components/responses/InternalServerError'
/events/{eventId}/channels:
put:
tags:
- Event Creation
summary: 배포 채널 선택 (Step 4)
description: |
이벤트를 배포할 채널을 선택합니다.
(웹사이트, 카카오톡, Instagram, Facebook 등)
operationId: selectChannels
x-user-story: UFR-EVENT-040
x-controller: EventController.selectChannels
parameters:
- $ref: '#/components/parameters/EventId'
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/SelectChannelsRequest'
responses:
'200':
description: 배포 채널 선택 성공
content:
application/json:
schema:
$ref: '#/components/schemas/EventDetailResponse'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'404':
$ref: '#/components/responses/NotFound'
'409':
description: 이벤트 상태가 적절하지 않음
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
example:
code: INVALID_EVENT_STATE
message: 이미지가 선택된 DRAFT 상태의 이벤트만 채널 선택이 가능합니다.
'500':
$ref: '#/components/responses/InternalServerError'
/events/{eventId}/publish:
post:
tags:
- Event Creation
summary: 최종 승인 및 배포 (Step 5)
description: |
이벤트를 최종 승인하고 선택된 채널에 배포합니다.
Distribution Service를 동기 호출하여 배포하고,
이벤트 상태를 PUBLISHED로 변경합니다.
Kafka Event (EventCreated)를 발행합니다.
operationId: publishEvent
x-user-story: UFR-EVENT-050
x-controller: EventController.publishEvent
parameters:
- $ref: '#/components/parameters/EventId'
responses:
'200':
description: 이벤트 배포 성공
content:
application/json:
schema:
$ref: '#/components/schemas/EventPublishedResponse'
'401':
$ref: '#/components/responses/Unauthorized'
'404':
$ref: '#/components/responses/NotFound'
'409':
description: 이벤트 상태가 적절하지 않음
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
example:
code: EVENT_NOT_PUBLISHABLE
message: 배포 채널이 선택된 DRAFT 상태의 이벤트만 배포 가능합니다.
'500':
$ref: '#/components/responses/InternalServerError'
'503':
description: Distribution Service 호출 실패
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
example:
code: DISTRIBUTION_SERVICE_UNAVAILABLE
message: 배포 서비스를 일시적으로 사용할 수 없습니다.
/events/{eventId}/end:
post:
tags:
- Event Management
summary: 이벤트 조기 종료
description: |
진행 중인 이벤트를 조기 종료합니다.
PUBLISHED 상태의 이벤트만 종료 가능하며,
종료 시 상태가 ENDED로 변경됩니다.
operationId: endEvent
x-user-story: UFR-EVENT-060
x-controller: EventController.endEvent
parameters:
- $ref: '#/components/parameters/EventId'
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/EndEventRequest'
responses:
'200':
description: 이벤트 종료 성공
content:
application/json:
schema:
$ref: '#/components/schemas/EventDetailResponse'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'404':
$ref: '#/components/responses/NotFound'
'409':
description: 이벤트 상태로 인해 종료 불가
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
example:
code: EVENT_NOT_ENDABLE
message: PUBLISHED 상태의 이벤트만 종료 가능합니다.
'500':
$ref: '#/components/responses/InternalServerError'
/jobs/{jobId}:
get:
tags:
- Job Status
summary: Job 상태 폴링
description: |
비동기 작업(AI 추천 생성, 이미지 생성)의 상태를 조회합니다.
클라이언트는 COMPLETED 또는 FAILED가 될 때까지 폴링합니다.
COMPLETED 시 Redis에서 결과를 조회할 수 있습니다.
operationId: getJobStatus
x-user-story: UFR-EVENT-030, UFR-CONT-010
x-controller: JobController.getJobStatus
parameters:
- name: jobId
in: path
description: Job ID
required: true
schema:
type: string
format: uuid
example: "550e8400-e29b-41d4-a716-446655440005"
responses:
'200':
description: Job 상태 조회 성공
content:
application/json:
schema:
$ref: '#/components/schemas/JobStatusResponse'
'401':
$ref: '#/components/responses/Unauthorized'
'404':
$ref: '#/components/responses/NotFound'
'500':
$ref: '#/components/responses/InternalServerError'
components:
securitySchemes:
BearerAuth:
type: http
scheme: bearer
bearerFormat: JWT
description: |
JWT Bearer 토큰 인증
**형식:** Authorization: Bearer {JWT_TOKEN}
**토큰 만료:** 7일
**Claims:**
- userId: 사용자 ID
- role: 사용자 역할 (OWNER)
- iat: 발급 시각
- exp: 만료 시각
parameters:
EventId:
name: eventId
in: path
description: 이벤트 ID
required: true
schema:
type: string
format: uuid
example: "550e8400-e29b-41d4-a716-446655440000"
schemas:
EventListResponse:
type: object
properties:
content:
type: array
items:
$ref: '#/components/schemas/EventSummary'
page:
$ref: '#/components/schemas/PageInfo'
required:
- content
- page
EventSummary:
type: object
properties:
eventId:
type: string
format: uuid
description: 이벤트 ID
example: "550e8400-e29b-41d4-a716-446655440000"
eventName:
type: string
description: 이벤트명
example: "봄맞이 20% 할인 이벤트"
objective:
type: string
description: 이벤트 목적
example: "신규 고객 유치"
status:
type: string
enum: [DRAFT, PUBLISHED, ENDED]
description: 이벤트 상태
example: "PUBLISHED"
startDate:
type: string
format: date
description: 시작일
example: "2025-03-01"
endDate:
type: string
format: date
description: 종료일
example: "2025-03-31"
thumbnailUrl:
type: string
format: uri
description: 썸네일 이미지 URL
example: "https://cdn.kt-event.com/images/event-thumb-001.jpg"
createdAt:
type: string
format: date-time
description: 생성일시
example: "2025-02-15T10:30:00Z"
required:
- eventId
- eventName
- objective
- status
- startDate
- endDate
- createdAt
EventDetailResponse:
type: object
properties:
eventId:
type: string
format: uuid
description: 이벤트 ID
example: "550e8400-e29b-41d4-a716-446655440000"
userId:
type: string
format: uuid
description: 사용자 ID
example: "550e8400-e29b-41d4-a716-446655440001"
storeId:
type: string
format: uuid
description: 매장 ID
example: "550e8400-e29b-41d4-a716-446655440002"
eventName:
type: string
description: 이벤트명
example: "봄맞이 20% 할인 이벤트"
objective:
type: string
description: 이벤트 목적
example: "신규 고객 유치"
description:
type: string
description: 이벤트 설명
example: "봄을 맞이하여 모든 상품 20% 할인 행사를 진행합니다."
targetAudience:
type: string
description: 타겟 고객
example: "20-30대 여성"
promotionType:
type: string
description: 프로모션 유형
example: "할인"
discountRate:
type: integer
description: 할인율 (%)
example: 20
startDate:
type: string
format: date
description: 시작일
example: "2025-03-01"
endDate:
type: string
format: date
description: 종료일
example: "2025-03-31"
status:
type: string
enum: [DRAFT, PUBLISHED, ENDED]
description: 이벤트 상태
example: "PUBLISHED"
selectedImageId:
type: string
format: uuid
description: 선택된 이미지 ID
example: "550e8400-e29b-41d4-a716-446655440006"
selectedImageUrl:
type: string
format: uri
description: 선택된 이미지 URL
example: "https://cdn.kt-event.com/images/event-img-001.jpg"
generatedImages:
type: array
description: 생성된 이미지 목록
items:
$ref: '#/components/schemas/GeneratedImage'
channels:
type: array
description: 배포 채널 목록
items:
type: string
example: "WEBSITE"
aiRecommendations:
type: array
description: AI 추천 목록
items:
$ref: '#/components/schemas/AiRecommendation'
createdAt:
type: string
format: date-time
description: 생성일시
example: "2025-02-15T10:30:00Z"
updatedAt:
type: string
format: date-time
description: 수정일시
example: "2025-02-20T14:45:00Z"
required:
- eventId
- userId
- storeId
- eventName
- objective
- status
- startDate
- endDate
- createdAt
GeneratedImage:
type: object
properties:
imageId:
type: string
format: uuid
description: 이미지 ID
example: "550e8400-e29b-41d4-a716-446655440006"
imageUrl:
type: string
format: uri
description: 이미지 URL
example: "https://cdn.kt-event.com/images/event-img-001.jpg"
isSelected:
type: boolean
description: 선택 여부
example: true
createdAt:
type: string
format: date-time
description: 생성일시
example: "2025-02-16T11:00:00Z"
required:
- imageId
- imageUrl
- isSelected
- createdAt
AiRecommendation:
type: object
properties:
recommendationId:
type: string
format: uuid
description: 추천 ID
example: "550e8400-e29b-41d4-a716-446655440007"
eventName:
type: string
description: 추천 이벤트명
example: "봄맞이 20% 할인 이벤트"
description:
type: string
description: 추천 설명
example: "봄을 맞이하여 모든 상품 20% 할인 행사를 진행합니다."
promotionType:
type: string
description: 추천 프로모션 유형
example: "할인"
targetAudience:
type: string
description: 추천 타겟 고객
example: "20-30대 여성"
isSelected:
type: boolean
description: 선택 여부
example: true
required:
- recommendationId
- eventName
- description
- isSelected
SelectObjectiveRequest:
type: object
properties:
objective:
type: string
description: 이벤트 목적
example: "신규 고객 유치"
required:
- objective
EventCreatedResponse:
type: object
properties:
eventId:
type: string
format: uuid
description: 생성된 이벤트 ID
example: "550e8400-e29b-41d4-a716-446655440000"
status:
type: string
enum: [DRAFT]
description: 이벤트 상태 (항상 DRAFT)
example: "DRAFT"
objective:
type: string
description: 선택된 이벤트 목적
example: "신규 고객 유치"
createdAt:
type: string
format: date-time
description: 생성일시
example: "2025-02-15T10:30:00Z"
required:
- eventId
- status
- objective
- createdAt
AiRecommendationRequest:
type: object
properties:
storeInfo:
type: object
description: 매장 정보 (User Service에서 조회)
properties:
storeId:
type: string
format: uuid
example: "550e8400-e29b-41d4-a716-446655440002"
storeName:
type: string
example: "우진네 고깃집"
category:
type: string
example: "음식점"
description:
type: string
example: "신선한 한우를 제공하는 고깃집"
required:
- storeId
- storeName
- category
required:
- storeInfo
JobAcceptedResponse:
type: object
properties:
jobId:
type: string
format: uuid
description: 생성된 Job ID
example: "550e8400-e29b-41d4-a716-446655440005"
status:
type: string
enum: [PENDING]
description: Job 상태 (초기 상태는 PENDING)
example: "PENDING"
message:
type: string
description: 안내 메시지
example: "AI 추천 생성 요청이 접수되었습니다. /jobs/{jobId}로 상태를 확인하세요."
required:
- jobId
- status
- message
JobStatusResponse:
type: object
properties:
jobId:
type: string
format: uuid
description: Job ID
example: "550e8400-e29b-41d4-a716-446655440005"
jobType:
type: string
enum: [AI_RECOMMENDATION, IMAGE_GENERATION]
description: Job 유형
example: "AI_RECOMMENDATION"
status:
type: string
enum: [PENDING, PROCESSING, COMPLETED, FAILED]
description: Job 상태
example: "COMPLETED"
progress:
type: integer
minimum: 0
maximum: 100
description: 진행률 (%)
example: 100
resultKey:
type: string
description: Redis 결과 키 (COMPLETED 시)
example: "ai:recommendation:550e8400-e29b-41d4-a716-446655440005"
errorMessage:
type: string
description: 에러 메시지 (FAILED 시)
example: "AI 서비스 연결 실패"
createdAt:
type: string
format: date-time
description: Job 생성일시
example: "2025-02-15T10:31:00Z"
completedAt:
type: string
format: date-time
description: Job 완료일시
example: "2025-02-15T10:31:30Z"
required:
- jobId
- jobType
- status
- progress
- createdAt
SelectRecommendationRequest:
type: object
properties:
recommendationId:
type: string
format: uuid
description: 선택한 추천 ID
example: "550e8400-e29b-41d4-a716-446655440007"
customizations:
type: object
description: 커스터마이징 항목
properties:
eventName:
type: string
description: 수정된 이벤트명
example: "봄맞이 특별 할인 이벤트"
description:
type: string
description: 수정된 설명
example: "봄을 맞이하여 전 메뉴 20% 할인"
startDate:
type: string
format: date
description: 수정된 시작일
example: "2025-03-01"
endDate:
type: string
format: date
description: 수정된 종료일
example: "2025-03-31"
discountRate:
type: integer
description: 수정된 할인율
example: 20
required:
- recommendationId
ImageGenerationRequest:
type: object
properties:
eventInfo:
type: object
description: 이벤트 정보 (이미지 생성에 필요한 정보)
properties:
eventName:
type: string
example: "봄맞이 20% 할인 이벤트"
description:
type: string
example: "봄을 맞이하여 모든 상품 20% 할인 행사를 진행합니다."
promotionType:
type: string
example: "할인"
required:
- eventName
- description
imageCount:
type: integer
minimum: 1
maximum: 5
description: 생성할 이미지 개수
default: 3
example: 3
required:
- eventInfo
ImageEditRequest:
type: object
properties:
editType:
type: string
enum: [TEXT_OVERLAY, COLOR_ADJUST, CROP, FILTER]
description: 편집 유형
example: "TEXT_OVERLAY"
parameters:
type: object
description: 편집 파라미터 (편집 유형에 따라 다름)
additionalProperties: true
example:
text: "20% 할인"
fontSize: 48
color: "#FF0000"
position: "center"
required:
- editType
- parameters
ImageEditResponse:
type: object
properties:
imageId:
type: string
format: uuid
description: 편집된 이미지 ID
example: "550e8400-e29b-41d4-a716-446655440008"
imageUrl:
type: string
format: uri
description: 편집된 이미지 URL
example: "https://cdn.kt-event.com/images/event-img-001-edited.jpg"
editedAt:
type: string
format: date-time
description: 편집일시
example: "2025-02-16T15:20:00Z"
required:
- imageId
- imageUrl
- editedAt
SelectChannelsRequest:
type: object
properties:
channels:
type: array
description: 배포 채널 목록
items:
type: string
enum: [WEBSITE, KAKAO, INSTAGRAM, FACEBOOK, NAVER_BLOG]
example: ["WEBSITE", "KAKAO", "INSTAGRAM"]
minItems: 1
required:
- channels
EventPublishedResponse:
type: object
properties:
eventId:
type: string
format: uuid
description: 이벤트 ID
example: "550e8400-e29b-41d4-a716-446655440000"
status:
type: string
enum: [PUBLISHED]
description: 이벤트 상태 (항상 PUBLISHED)
example: "PUBLISHED"
publishedAt:
type: string
format: date-time
description: 배포일시
example: "2025-02-20T16:00:00Z"
channels:
type: array
description: 배포된 채널 목록
items:
type: string
example: "WEBSITE"
distributionResults:
type: array
description: 채널별 배포 결과
items:
$ref: '#/components/schemas/DistributionResult'
required:
- eventId
- status
- publishedAt
- channels
- distributionResults
DistributionResult:
type: object
properties:
channel:
type: string
description: 채널명
example: "WEBSITE"
success:
type: boolean
description: 배포 성공 여부
example: true
url:
type: string
format: uri
description: 배포된 URL
example: "https://store.kt-event.com/event/550e8400-e29b-41d4-a716-446655440000"
message:
type: string
description: 배포 결과 메시지
example: "웹사이트에 성공적으로 배포되었습니다."
required:
- channel
- success
UpdateEventRequest:
type: object
properties:
eventName:
type: string
description: 이벤트명
example: "봄맞이 특별 할인 이벤트"
description:
type: string
description: 이벤트 설명
example: "봄을 맞이하여 전 메뉴 20% 할인"
startDate:
type: string
format: date
description: 시작일
example: "2025-03-01"
endDate:
type: string
format: date
description: 종료일
example: "2025-03-31"
discountRate:
type: integer
description: 할인율
example: 20
EndEventRequest:
type: object
properties:
reason:
type: string
description: 종료 사유
example: "목표 달성으로 조기 종료"
required:
- reason
PageInfo:
type: object
properties:
page:
type: integer
description: 현재 페이지 번호
example: 0
size:
type: integer
description: 페이지 크기
example: 20
totalElements:
type: integer
description: 전체 요소 개수
example: 45
totalPages:
type: integer
description: 전체 페이지 개수
example: 3
required:
- page
- size
- totalElements
- totalPages
ErrorResponse:
type: object
required:
- code
- message
- timestamp
properties:
code:
type: string
description: 에러 코드
example: "INVALID_REQUEST"
message:
type: string
description: 에러 메시지
example: "요청 파라미터가 올바르지 않습니다."
timestamp:
type: string
format: date-time
description: 에러 발생 시각
example: "2025-02-15T10:30:00Z"
details:
type: array
description: 상세 에러 정보 (선택 사항)
items:
type: string
example: ["objective 필드는 필수입니다."]
responses:
BadRequest:
description: 잘못된 요청
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
example:
code: INVALID_REQUEST
message: 요청 파라미터가 올바르지 않습니다.
details:
- "objective 필드는 필수입니다."
timestamp: "2025-02-15T10:30:00Z"
Unauthorized:
description: 인증 실패
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
example:
code: UNAUTHORIZED
message: 인증에 실패했습니다.
timestamp: "2025-02-15T10:30:00Z"
Forbidden:
description: 권한 없음
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
example:
code: FORBIDDEN
message: 해당 리소스에 접근할 권한이 없습니다.
timestamp: "2025-02-15T10:30:00Z"
NotFound:
description: 리소스를 찾을 수 없음
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
example:
code: NOT_FOUND
message: 요청한 리소스를 찾을 수 없습니다.
timestamp: "2025-02-15T10:30:00Z"
InternalServerError:
description: 서버 내부 오류
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
example:
code: INTERNAL_SERVER_ERROR
message: 서버 내부 오류가 발생했습니다.
timestamp: "2025-02-15T10:30:00Z"