mirror of
https://github.com/ktds-dg0501/kt-event-marketing.git
synced 2025-12-06 20:06:23 +00:00
1059 lines
29 KiB
YAML
1059 lines
29 KiB
YAML
openapi: 3.0.3
|
|
info:
|
|
title: Event Service API
|
|
version: 1.0.0
|
|
description: |
|
|
KT AI 기반 소상공인 이벤트 자동 생성 서비스의 Event Service API 명세입니다.
|
|
|
|
**주요 기능:**
|
|
- 이벤트 대시보드 조회
|
|
- 이벤트 목적 선택 및 초안 생성
|
|
- AI 이벤트 추천 요청 및 결과 조회
|
|
- 이미지 생성 요청 및 결과 조회
|
|
- 콘텐츠 선택 및 편집
|
|
- 최종 승인 및 배포
|
|
- 이벤트 상세 조회 및 목록 관리
|
|
|
|
servers:
|
|
- url: http://localhost:8080
|
|
description: 로컬 개발 서버
|
|
- url: https://api-dev.kt-event-marketing.com
|
|
description: 개발 서버
|
|
- url: https://api.kt-event-marketing.com
|
|
description: 프로덕션 서버
|
|
|
|
tags:
|
|
- name: Dashboard
|
|
description: 대시보드 관리
|
|
- name: EventDraft
|
|
description: 이벤트 초안 관리
|
|
- name: AIRecommendation
|
|
description: AI 추천 관리
|
|
- name: ContentGeneration
|
|
description: 콘텐츠 생성 관리
|
|
- name: EventPublish
|
|
description: 이벤트 발행 관리
|
|
- name: EventManagement
|
|
description: 이벤트 조회 및 관리
|
|
- name: Job
|
|
description: 비동기 작업 관리
|
|
|
|
paths:
|
|
/api/events/dashboard:
|
|
get:
|
|
tags:
|
|
- Dashboard
|
|
summary: 대시보드 이벤트 목록 조회
|
|
description: |
|
|
UFR-EVENT-010: 소상공인의 대시보드에서 진행중/예정/종료된 이벤트를 조회합니다.
|
|
|
|
**비즈니스 로직:**
|
|
- 상태별로 최대 5개씩 표시 (최신순)
|
|
- Redis 캐시 우선 조회 (TTL 1분)
|
|
- 참여자 수, 조회수 등 기본 통계 포함
|
|
operationId: getDashboard
|
|
security:
|
|
- bearerAuth: []
|
|
responses:
|
|
'200':
|
|
description: 대시보드 데이터 조회 성공
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/DashboardResponse'
|
|
'401':
|
|
$ref: '#/components/responses/Unauthorized'
|
|
'500':
|
|
$ref: '#/components/responses/InternalServerError'
|
|
|
|
/api/events/purposes:
|
|
post:
|
|
tags:
|
|
- EventDraft
|
|
summary: 이벤트 목적 선택 및 초안 생성
|
|
description: |
|
|
UFR-EVENT-020: 이벤트 목적을 선택하고 초안을 생성합니다.
|
|
|
|
**비즈니스 로직:**
|
|
- 목적 유효성 검증 (신규 고객 유치, 재방문 유도, 매출 증대, 인지도 향상)
|
|
- EventDraft 엔티티 생성 및 DB 저장
|
|
- Redis 캐시 저장 (TTL 30분)
|
|
- Kafka EventDraftCreated 이벤트 발행
|
|
operationId: createEventDraft
|
|
security:
|
|
- bearerAuth: []
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/CreateEventDraftRequest'
|
|
responses:
|
|
'200':
|
|
description: 이벤트 초안 생성 성공
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/EventDraftResponse'
|
|
'400':
|
|
$ref: '#/components/responses/BadRequest'
|
|
'401':
|
|
$ref: '#/components/responses/Unauthorized'
|
|
'500':
|
|
$ref: '#/components/responses/InternalServerError'
|
|
|
|
/api/events/{id}/ai-recommendations:
|
|
post:
|
|
tags:
|
|
- AIRecommendation
|
|
summary: AI 이벤트 추천 요청
|
|
description: |
|
|
UFR-EVENT-030: AI 트렌드 분석 및 이벤트 추천을 요청합니다.
|
|
|
|
**비동기 처리:**
|
|
- Kafka ai-job-topic에 Job 발행
|
|
- Redis에 Job 상태 저장 (TTL 1시간)
|
|
- 202 Accepted 응답 (jobId 반환)
|
|
- 클라이언트는 폴링으로 결과 조회
|
|
operationId: requestAIRecommendation
|
|
security:
|
|
- bearerAuth: []
|
|
parameters:
|
|
- name: id
|
|
in: path
|
|
required: true
|
|
description: 이벤트 초안 ID
|
|
schema:
|
|
type: string
|
|
format: uuid
|
|
responses:
|
|
'202':
|
|
description: AI 추천 요청 접수
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/JobResponse'
|
|
'400':
|
|
$ref: '#/components/responses/BadRequest'
|
|
'401':
|
|
$ref: '#/components/responses/Unauthorized'
|
|
'404':
|
|
$ref: '#/components/responses/NotFound'
|
|
'500':
|
|
$ref: '#/components/responses/InternalServerError'
|
|
|
|
/api/jobs/{jobId}/status:
|
|
get:
|
|
tags:
|
|
- Job
|
|
summary: Job 상태 조회 (폴링)
|
|
description: |
|
|
AI 추천 또는 이미지 생성 Job의 상태를 조회합니다.
|
|
|
|
**폴링 패턴:**
|
|
- AI 추천: 2초 간격, 최대 30초 (15회)
|
|
- 이미지 생성: 3초 간격, 최대 30초 (10회)
|
|
- 상태: PENDING, PROCESSING, COMPLETED, FAILED
|
|
operationId: getJobStatus
|
|
security:
|
|
- bearerAuth: []
|
|
parameters:
|
|
- name: jobId
|
|
in: path
|
|
required: true
|
|
description: Job ID
|
|
schema:
|
|
type: string
|
|
format: uuid
|
|
responses:
|
|
'200':
|
|
description: Job 상태 조회 성공
|
|
content:
|
|
application/json:
|
|
schema:
|
|
oneOf:
|
|
- $ref: '#/components/schemas/AIRecommendationJobResult'
|
|
- $ref: '#/components/schemas/ImageGenerationJobResult'
|
|
'404':
|
|
$ref: '#/components/responses/NotFound'
|
|
'500':
|
|
$ref: '#/components/responses/InternalServerError'
|
|
|
|
/api/events/{id}/content-generation:
|
|
post:
|
|
tags:
|
|
- ContentGeneration
|
|
summary: 이미지 생성 요청
|
|
description: |
|
|
UFR-CONT-010: SNS용 이미지 생성을 요청합니다.
|
|
|
|
**비동기 처리:**
|
|
- Kafka image-job-topic에 Job 발행
|
|
- Redis에 Job 상태 저장 (TTL 1시간)
|
|
- 202 Accepted 응답 (jobId 반환)
|
|
- Content Service가 3가지 스타일 이미지 생성
|
|
operationId: requestImageGeneration
|
|
security:
|
|
- bearerAuth: []
|
|
parameters:
|
|
- name: id
|
|
in: path
|
|
required: true
|
|
description: 이벤트 초안 ID
|
|
schema:
|
|
type: string
|
|
format: uuid
|
|
responses:
|
|
'202':
|
|
description: 이미지 생성 요청 접수
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/JobResponse'
|
|
'400':
|
|
$ref: '#/components/responses/BadRequest'
|
|
'401':
|
|
$ref: '#/components/responses/Unauthorized'
|
|
'404':
|
|
$ref: '#/components/responses/NotFound'
|
|
'500':
|
|
$ref: '#/components/responses/InternalServerError'
|
|
|
|
/api/events/drafts/{id}/content:
|
|
put:
|
|
tags:
|
|
- ContentGeneration
|
|
summary: 선택한 콘텐츠 저장
|
|
description: |
|
|
UFR-CONT-020: 선택한 이미지와 편집한 콘텐츠를 저장합니다.
|
|
|
|
**비즈니스 로직:**
|
|
- 선택한 이미지 URL 검증
|
|
- 편집 내용 적용 (텍스트, 색상)
|
|
- EventDraft 업데이트
|
|
- Redis 캐시 무효화
|
|
operationId: updateEventContent
|
|
security:
|
|
- bearerAuth: []
|
|
parameters:
|
|
- name: id
|
|
in: path
|
|
required: true
|
|
description: 이벤트 초안 ID
|
|
schema:
|
|
type: string
|
|
format: uuid
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/UpdateContentRequest'
|
|
responses:
|
|
'200':
|
|
description: 콘텐츠 저장 성공
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/EventContentResponse'
|
|
'400':
|
|
$ref: '#/components/responses/BadRequest'
|
|
'401':
|
|
$ref: '#/components/responses/Unauthorized'
|
|
'404':
|
|
$ref: '#/components/responses/NotFound'
|
|
'500':
|
|
$ref: '#/components/responses/InternalServerError'
|
|
|
|
/api/events/{id}/publish:
|
|
post:
|
|
tags:
|
|
- EventPublish
|
|
summary: 이벤트 최종 승인 및 배포
|
|
description: |
|
|
UFR-EVENT-050: 이벤트를 최종 승인하고 배포를 시작합니다.
|
|
|
|
**비즈니스 로직:**
|
|
- 발행 준비 검증 (목적, AI 추천, 콘텐츠, 채널 선택)
|
|
- 상태 변경: DRAFT → APPROVED → ACTIVE
|
|
- Kafka EventCreated 이벤트 발행
|
|
- Distribution Service 동기 호출 (Timeout 70초, Circuit Breaker 적용)
|
|
- Redis 캐시 무효화
|
|
operationId: publishEvent
|
|
security:
|
|
- bearerAuth: []
|
|
parameters:
|
|
- name: id
|
|
in: path
|
|
required: true
|
|
description: 이벤트 초안 ID
|
|
schema:
|
|
type: string
|
|
format: uuid
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/PublishEventRequest'
|
|
responses:
|
|
'200':
|
|
description: 이벤트 발행 성공
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/PublishEventResponse'
|
|
'400':
|
|
$ref: '#/components/responses/BadRequest'
|
|
'401':
|
|
$ref: '#/components/responses/Unauthorized'
|
|
'404':
|
|
$ref: '#/components/responses/NotFound'
|
|
'500':
|
|
$ref: '#/components/responses/InternalServerError'
|
|
'503':
|
|
description: Distribution Service 호출 실패
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
|
|
/api/events/{id}:
|
|
get:
|
|
tags:
|
|
- EventManagement
|
|
summary: 이벤트 상세 조회
|
|
description: |
|
|
UFR-EVENT-060: 이벤트의 상세 정보를 조회합니다.
|
|
|
|
**비즈니스 로직:**
|
|
- Redis 캐시 우선 조회 (TTL 5분)
|
|
- 경품 정보 및 배포 이력 JOIN 조회
|
|
- 사용자 권한 검증
|
|
operationId: getEventDetail
|
|
security:
|
|
- bearerAuth: []
|
|
parameters:
|
|
- name: id
|
|
in: path
|
|
required: true
|
|
description: 이벤트 ID
|
|
schema:
|
|
type: string
|
|
format: uuid
|
|
responses:
|
|
'200':
|
|
description: 이벤트 상세 조회 성공
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/EventDetailResponse'
|
|
'401':
|
|
$ref: '#/components/responses/Unauthorized'
|
|
'403':
|
|
$ref: '#/components/responses/Forbidden'
|
|
'404':
|
|
$ref: '#/components/responses/NotFound'
|
|
'500':
|
|
$ref: '#/components/responses/InternalServerError'
|
|
|
|
/api/events:
|
|
get:
|
|
tags:
|
|
- EventManagement
|
|
summary: 이벤트 목록 조회 (필터/검색)
|
|
description: |
|
|
UFR-EVENT-070: 이벤트 목록을 조회하고 필터링/검색합니다.
|
|
|
|
**비즈니스 로직:**
|
|
- Redis 캐시 우선 조회 (TTL 1분)
|
|
- 상태별 필터링
|
|
- 키워드 검색 (제목, 설명)
|
|
- 페이지네이션 (기본 20개/페이지)
|
|
- 정렬 (최신순, 참여자순, ROI순)
|
|
operationId: getEventList
|
|
security:
|
|
- bearerAuth: []
|
|
parameters:
|
|
- name: status
|
|
in: query
|
|
description: 이벤트 상태 필터
|
|
schema:
|
|
type: string
|
|
enum: [DRAFT, APPROVED, ACTIVE, COMPLETED]
|
|
- name: keyword
|
|
in: query
|
|
description: 검색 키워드 (제목, 설명)
|
|
schema:
|
|
type: string
|
|
- name: page
|
|
in: query
|
|
description: 페이지 번호 (0부터 시작)
|
|
schema:
|
|
type: integer
|
|
minimum: 0
|
|
default: 0
|
|
- name: size
|
|
in: query
|
|
description: 페이지 크기
|
|
schema:
|
|
type: integer
|
|
minimum: 1
|
|
maximum: 100
|
|
default: 20
|
|
- name: sort
|
|
in: query
|
|
description: 정렬 기준
|
|
schema:
|
|
type: string
|
|
enum: [createdAt,desc, participantCount,desc, roi,desc]
|
|
default: createdAt,desc
|
|
responses:
|
|
'200':
|
|
description: 이벤트 목록 조회 성공
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/EventListResponse'
|
|
'400':
|
|
$ref: '#/components/responses/BadRequest'
|
|
'401':
|
|
$ref: '#/components/responses/Unauthorized'
|
|
'500':
|
|
$ref: '#/components/responses/InternalServerError'
|
|
|
|
components:
|
|
securitySchemes:
|
|
bearerAuth:
|
|
type: http
|
|
scheme: bearer
|
|
bearerFormat: JWT
|
|
description: JWT 토큰을 사용한 인증 (User Service에서 발급)
|
|
|
|
schemas:
|
|
# Dashboard Schemas
|
|
DashboardResponse:
|
|
type: object
|
|
required:
|
|
- active
|
|
- approved
|
|
- completed
|
|
properties:
|
|
active:
|
|
type: array
|
|
description: 진행중 이벤트 목록 (최대 5개)
|
|
maxItems: 5
|
|
items:
|
|
$ref: '#/components/schemas/EventSummary'
|
|
approved:
|
|
type: array
|
|
description: 배포 대기중 이벤트 목록 (최대 5개)
|
|
maxItems: 5
|
|
items:
|
|
$ref: '#/components/schemas/EventSummary'
|
|
completed:
|
|
type: array
|
|
description: 종료된 이벤트 목록 (최대 5개)
|
|
maxItems: 5
|
|
items:
|
|
$ref: '#/components/schemas/EventSummary'
|
|
|
|
EventSummary:
|
|
type: object
|
|
required:
|
|
- eventId
|
|
- title
|
|
- status
|
|
- createdAt
|
|
properties:
|
|
eventId:
|
|
type: string
|
|
format: uuid
|
|
description: 이벤트 ID
|
|
title:
|
|
type: string
|
|
description: 이벤트 제목
|
|
maxLength: 100
|
|
period:
|
|
$ref: '#/components/schemas/EventPeriod'
|
|
status:
|
|
type: string
|
|
enum: [DRAFT, APPROVED, ACTIVE, COMPLETED]
|
|
description: 이벤트 상태
|
|
participantCount:
|
|
type: integer
|
|
description: 참여자 수
|
|
default: 0
|
|
viewCount:
|
|
type: integer
|
|
description: 조회수
|
|
default: 0
|
|
createdAt:
|
|
type: string
|
|
format: date-time
|
|
description: 생성일시
|
|
|
|
EventPeriod:
|
|
type: object
|
|
properties:
|
|
startDate:
|
|
type: string
|
|
format: date
|
|
description: 시작일
|
|
endDate:
|
|
type: string
|
|
format: date
|
|
description: 종료일
|
|
|
|
# Event Draft Schemas
|
|
CreateEventDraftRequest:
|
|
type: object
|
|
required:
|
|
- objective
|
|
- storeInfo
|
|
properties:
|
|
objective:
|
|
type: string
|
|
enum: [NEW_CUSTOMER, REVISIT, SALES_INCREASE, BRAND_AWARENESS]
|
|
description: |
|
|
이벤트 목적
|
|
- NEW_CUSTOMER: 신규 고객 유치
|
|
- REVISIT: 재방문 유도
|
|
- SALES_INCREASE: 매출 증대
|
|
- BRAND_AWARENESS: 인지도 향상
|
|
storeInfo:
|
|
$ref: '#/components/schemas/StoreInfo'
|
|
|
|
StoreInfo:
|
|
type: object
|
|
required:
|
|
- storeName
|
|
- industry
|
|
- region
|
|
properties:
|
|
storeName:
|
|
type: string
|
|
description: 매장명
|
|
maxLength: 50
|
|
industry:
|
|
type: string
|
|
description: 업종
|
|
maxLength: 30
|
|
region:
|
|
type: string
|
|
description: 지역
|
|
maxLength: 50
|
|
address:
|
|
type: string
|
|
description: 주소
|
|
maxLength: 200
|
|
|
|
EventDraftResponse:
|
|
type: object
|
|
required:
|
|
- eventDraftId
|
|
- objective
|
|
- status
|
|
properties:
|
|
eventDraftId:
|
|
type: string
|
|
format: uuid
|
|
description: 이벤트 초안 ID
|
|
objective:
|
|
type: string
|
|
enum: [NEW_CUSTOMER, REVISIT, SALES_INCREASE, BRAND_AWARENESS]
|
|
description: 이벤트 목적
|
|
status:
|
|
type: string
|
|
enum: [DRAFT]
|
|
description: 초안 상태
|
|
createdAt:
|
|
type: string
|
|
format: date-time
|
|
description: 생성일시
|
|
|
|
# Job Schemas
|
|
JobResponse:
|
|
type: object
|
|
required:
|
|
- jobId
|
|
- status
|
|
properties:
|
|
jobId:
|
|
type: string
|
|
format: uuid
|
|
description: Job ID
|
|
status:
|
|
type: string
|
|
enum: [PENDING, PROCESSING, COMPLETED, FAILED]
|
|
description: Job 상태
|
|
|
|
AIRecommendationJobResult:
|
|
type: object
|
|
required:
|
|
- jobId
|
|
- status
|
|
properties:
|
|
jobId:
|
|
type: string
|
|
format: uuid
|
|
status:
|
|
type: string
|
|
enum: [PENDING, PROCESSING, COMPLETED, FAILED]
|
|
recommendations:
|
|
type: array
|
|
description: AI 추천 결과 (3가지)
|
|
minItems: 3
|
|
maxItems: 3
|
|
items:
|
|
$ref: '#/components/schemas/EventRecommendation'
|
|
error:
|
|
type: string
|
|
description: 에러 메시지 (FAILED 상태일 때만)
|
|
|
|
EventRecommendation:
|
|
type: object
|
|
required:
|
|
- title
|
|
- prize
|
|
- participationMethod
|
|
- estimatedCost
|
|
- estimatedParticipants
|
|
- estimatedROI
|
|
properties:
|
|
title:
|
|
type: string
|
|
description: 이벤트 제목 (수정 가능)
|
|
maxLength: 50
|
|
prize:
|
|
type: string
|
|
description: 경품 (수정 가능)
|
|
maxLength: 100
|
|
participationMethod:
|
|
type: string
|
|
description: 참여 방법
|
|
maxLength: 200
|
|
estimatedCost:
|
|
type: integer
|
|
description: 예상 비용 (원)
|
|
minimum: 0
|
|
estimatedParticipants:
|
|
type: integer
|
|
description: 예상 참여자 수
|
|
minimum: 0
|
|
estimatedROI:
|
|
type: number
|
|
format: double
|
|
description: 예상 투자 대비 수익률 (%)
|
|
|
|
ImageGenerationJobResult:
|
|
type: object
|
|
required:
|
|
- jobId
|
|
- status
|
|
properties:
|
|
jobId:
|
|
type: string
|
|
format: uuid
|
|
status:
|
|
type: string
|
|
enum: [PENDING, PROCESSING, COMPLETED, FAILED]
|
|
progress:
|
|
type: integer
|
|
description: 진행률 (%) - PROCESSING 상태일 때
|
|
minimum: 0
|
|
maximum: 100
|
|
imageUrls:
|
|
type: object
|
|
description: 생성된 이미지 URL (3가지 스타일) - COMPLETED 상태일 때
|
|
properties:
|
|
simple:
|
|
type: string
|
|
format: uri
|
|
description: 심플 스타일 이미지 URL
|
|
fancy:
|
|
type: string
|
|
format: uri
|
|
description: 화려한 스타일 이미지 URL
|
|
trendy:
|
|
type: string
|
|
format: uri
|
|
description: 트렌디 스타일 이미지 URL
|
|
error:
|
|
type: string
|
|
description: 에러 메시지 (FAILED 상태일 때만)
|
|
|
|
# Content Schemas
|
|
UpdateContentRequest:
|
|
type: object
|
|
required:
|
|
- selectedImageUrl
|
|
- editedContent
|
|
properties:
|
|
selectedImageUrl:
|
|
type: string
|
|
format: uri
|
|
description: 선택한 이미지 URL (simple, fancy, trendy 중 하나)
|
|
editedContent:
|
|
$ref: '#/components/schemas/EditedContent'
|
|
|
|
EditedContent:
|
|
type: object
|
|
properties:
|
|
title:
|
|
type: string
|
|
description: 편집된 제목
|
|
maxLength: 100
|
|
prizeText:
|
|
type: string
|
|
description: 편집된 경품 정보 텍스트
|
|
maxLength: 200
|
|
participationText:
|
|
type: string
|
|
description: 편집된 참여 안내 텍스트
|
|
maxLength: 300
|
|
backgroundColor:
|
|
type: string
|
|
pattern: '^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$'
|
|
description: 배경색 (Hex 코드)
|
|
textColor:
|
|
type: string
|
|
pattern: '^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$'
|
|
description: 텍스트 색상 (Hex 코드)
|
|
accentColor:
|
|
type: string
|
|
pattern: '^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$'
|
|
description: 강조 색상 (Hex 코드)
|
|
|
|
EventContentResponse:
|
|
type: object
|
|
required:
|
|
- eventDraftId
|
|
- selectedImageUrl
|
|
- editedContent
|
|
properties:
|
|
eventDraftId:
|
|
type: string
|
|
format: uuid
|
|
selectedImageUrl:
|
|
type: string
|
|
format: uri
|
|
editedContent:
|
|
$ref: '#/components/schemas/EditedContent'
|
|
|
|
# Publish Schemas
|
|
PublishEventRequest:
|
|
type: object
|
|
required:
|
|
- selectedChannels
|
|
properties:
|
|
selectedChannels:
|
|
type: array
|
|
description: 배포 채널 목록 (최소 1개)
|
|
minItems: 1
|
|
items:
|
|
$ref: '#/components/schemas/DistributionChannel'
|
|
|
|
DistributionChannel:
|
|
type: object
|
|
required:
|
|
- channelType
|
|
properties:
|
|
channelType:
|
|
type: string
|
|
enum: [URINEIGHBOR_TV, RINGO_BIZ, GENIE_TV, INSTAGRAM, NAVER_BLOG, KAKAO_CHANNEL]
|
|
description: |
|
|
배포 채널 타입
|
|
- URINEIGHBOR_TV: 우리동네TV
|
|
- RINGO_BIZ: 링고비즈
|
|
- GENIE_TV: 지니TV
|
|
- INSTAGRAM: Instagram
|
|
- NAVER_BLOG: Naver Blog
|
|
- KAKAO_CHANNEL: Kakao Channel
|
|
settings:
|
|
type: object
|
|
description: 채널별 설정 (채널마다 다름)
|
|
additionalProperties: true
|
|
|
|
PublishEventResponse:
|
|
type: object
|
|
required:
|
|
- eventId
|
|
- status
|
|
- distributionResults
|
|
properties:
|
|
eventId:
|
|
type: string
|
|
format: uuid
|
|
description: 발행된 이벤트 ID
|
|
status:
|
|
type: string
|
|
enum: [ACTIVE]
|
|
description: 이벤트 상태
|
|
distributionResults:
|
|
type: array
|
|
description: 채널별 배포 결과
|
|
items:
|
|
$ref: '#/components/schemas/ChannelDistributionResult'
|
|
|
|
ChannelDistributionResult:
|
|
type: object
|
|
required:
|
|
- channelType
|
|
- status
|
|
properties:
|
|
channelType:
|
|
type: string
|
|
enum: [URINEIGHBOR_TV, RINGO_BIZ, GENIE_TV, INSTAGRAM, NAVER_BLOG, KAKAO_CHANNEL]
|
|
status:
|
|
type: string
|
|
enum: [SUCCESS, FAILED]
|
|
description: 배포 상태
|
|
distributionId:
|
|
type: string
|
|
description: 배포 ID (채널에서 발급)
|
|
estimatedReach:
|
|
type: integer
|
|
description: 예상 노출 수
|
|
error:
|
|
type: string
|
|
description: 에러 메시지 (FAILED 상태일 때)
|
|
|
|
# Event Management Schemas
|
|
EventDetailResponse:
|
|
type: object
|
|
required:
|
|
- event
|
|
- prizes
|
|
- distributionStatus
|
|
properties:
|
|
event:
|
|
$ref: '#/components/schemas/EventDetail'
|
|
prizes:
|
|
type: array
|
|
description: 경품 목록
|
|
items:
|
|
$ref: '#/components/schemas/Prize'
|
|
distributionStatus:
|
|
$ref: '#/components/schemas/DistributionStatus'
|
|
|
|
EventDetail:
|
|
type: object
|
|
required:
|
|
- eventId
|
|
- title
|
|
- objective
|
|
- status
|
|
- createdAt
|
|
properties:
|
|
eventId:
|
|
type: string
|
|
format: uuid
|
|
title:
|
|
type: string
|
|
maxLength: 100
|
|
objective:
|
|
type: string
|
|
enum: [NEW_CUSTOMER, REVISIT, SALES_INCREASE, BRAND_AWARENESS]
|
|
period:
|
|
$ref: '#/components/schemas/EventPeriod'
|
|
status:
|
|
type: string
|
|
enum: [DRAFT, APPROVED, ACTIVE, COMPLETED]
|
|
participationMethod:
|
|
type: string
|
|
description: 참여 방법
|
|
maxLength: 500
|
|
selectedImageUrl:
|
|
type: string
|
|
format: uri
|
|
description: 선택한 이미지 URL
|
|
editedContent:
|
|
$ref: '#/components/schemas/EditedContent'
|
|
createdAt:
|
|
type: string
|
|
format: date-time
|
|
publishedAt:
|
|
type: string
|
|
format: date-time
|
|
description: 발행일시
|
|
|
|
Prize:
|
|
type: object
|
|
required:
|
|
- prizeId
|
|
- prizeName
|
|
- quantity
|
|
properties:
|
|
prizeId:
|
|
type: string
|
|
format: uuid
|
|
prizeName:
|
|
type: string
|
|
description: 경품명
|
|
maxLength: 100
|
|
quantity:
|
|
type: integer
|
|
description: 수량
|
|
minimum: 1
|
|
|
|
DistributionStatus:
|
|
type: object
|
|
properties:
|
|
channels:
|
|
type: array
|
|
description: 배포된 채널 목록
|
|
items:
|
|
$ref: '#/components/schemas/ChannelStatus'
|
|
|
|
ChannelStatus:
|
|
type: object
|
|
required:
|
|
- channelType
|
|
- status
|
|
properties:
|
|
channelType:
|
|
type: string
|
|
enum: [URINEIGHBOR_TV, RINGO_BIZ, GENIE_TV, INSTAGRAM, NAVER_BLOG, KAKAO_CHANNEL]
|
|
status:
|
|
type: string
|
|
enum: [PENDING, DISTRIBUTING, ACTIVE, FAILED]
|
|
distributionId:
|
|
type: string
|
|
estimatedReach:
|
|
type: integer
|
|
actualReach:
|
|
type: integer
|
|
description: 실제 노출 수
|
|
|
|
EventListResponse:
|
|
type: object
|
|
required:
|
|
- events
|
|
- totalCount
|
|
- totalPages
|
|
- currentPage
|
|
properties:
|
|
events:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/EventListItem'
|
|
totalCount:
|
|
type: integer
|
|
description: 전체 이벤트 수
|
|
totalPages:
|
|
type: integer
|
|
description: 전체 페이지 수
|
|
currentPage:
|
|
type: integer
|
|
description: 현재 페이지 (0부터 시작)
|
|
|
|
EventListItem:
|
|
type: object
|
|
required:
|
|
- eventId
|
|
- title
|
|
- status
|
|
- createdAt
|
|
properties:
|
|
eventId:
|
|
type: string
|
|
format: uuid
|
|
title:
|
|
type: string
|
|
maxLength: 100
|
|
period:
|
|
$ref: '#/components/schemas/EventPeriod'
|
|
status:
|
|
type: string
|
|
enum: [DRAFT, APPROVED, ACTIVE, COMPLETED]
|
|
participantCount:
|
|
type: integer
|
|
description: 참여자 수
|
|
default: 0
|
|
roi:
|
|
type: number
|
|
format: double
|
|
description: 투자 대비 수익률 (%)
|
|
createdAt:
|
|
type: string
|
|
format: date-time
|
|
|
|
# Error Schemas
|
|
ErrorResponse:
|
|
type: object
|
|
required:
|
|
- error
|
|
- message
|
|
- timestamp
|
|
properties:
|
|
error:
|
|
type: string
|
|
description: 에러 코드
|
|
message:
|
|
type: string
|
|
description: 에러 메시지
|
|
timestamp:
|
|
type: string
|
|
format: date-time
|
|
description: 에러 발생 시각
|
|
details:
|
|
type: string
|
|
description: 상세 에러 정보
|
|
|
|
responses:
|
|
BadRequest:
|
|
description: 잘못된 요청
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
example:
|
|
error: BAD_REQUEST
|
|
message: 요청 파라미터가 유효하지 않습니다
|
|
timestamp: '2025-10-22T10:00:00Z'
|
|
|
|
Unauthorized:
|
|
description: 인증 실패
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
example:
|
|
error: UNAUTHORIZED
|
|
message: 인증 토큰이 유효하지 않습니다
|
|
timestamp: '2025-10-22T10:00:00Z'
|
|
|
|
Forbidden:
|
|
description: 권한 없음
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
example:
|
|
error: FORBIDDEN
|
|
message: 해당 리소스에 접근 권한이 없습니다
|
|
timestamp: '2025-10-22T10:00:00Z'
|
|
|
|
NotFound:
|
|
description: 리소스를 찾을 수 없음
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
example:
|
|
error: NOT_FOUND
|
|
message: 요청한 리소스를 찾을 수 없습니다
|
|
timestamp: '2025-10-22T10:00:00Z'
|
|
|
|
InternalServerError:
|
|
description: 서버 내부 오류
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
example:
|
|
error: INTERNAL_SERVER_ERROR
|
|
message: 서버 내부 오류가 발생했습니다
|
|
timestamp: '2025-10-22T10:00:00Z'
|