Glowb Dev Docs
SaaS APIProgress Table

GET /ai/progress-table/item/{id}

캠페인 진행 항목 조회

캠페인 진행 항목 조회

기업 대시보드용 캠페인 진행 항목을 조회합니다.

예비(reserved)도 노출됩니다. 첫 매칭 이후 신청자 숨김 모드(applicantHidden)에서도, 예비는 선정 불발 시 자동 승계 대상이므로 SELECTED/PROPOSAL 항목과 함께 계속 노출됩니다(관리자 노출 설정 adminVisible 과 무관). matchingStatusreserved인 항목이 예비이며, 화면에는 "예비"로 표시하세요.

응답에는 items 외에 dummyItems(모집 에이전트가 발굴한 데모 후보)가 함께 내려갑니다. items동일한 타입이라 같은 컴포넌트로 렌더하며, 데모임을 드러내는 표기를 넣으면 안 됩니다 — 기업 화면에서는 일반 신청자와 구분 없이 자연스럽게 보여야 합니다. ID는 1억 오프셋이 붙어 items와 겹치지 않습니다. 상세는 데모(목업) 후보 연동 가이드를 참고하세요.

기업 승인 전(INVALID_BUSINESS) 광고주도 본인 캠페인을 조회할 수 있습니다. 승인 전이어도 데이터는 정상 반환되며, 응답의 businessApproved 값으로 승인 여부를 분기하세요. 미승인(false) 시 프런트에서 CTA 자리에 "기업승인 진행중" 등을 노출하는 용도입니다. (타인 캠페인 조회는 여전히 403 FORBIDDEN)

HTTP 요청

GET /ai/progress-table/item/{id}
Authorization: Bearer {access_token}

Path Parameters

파라미터타입필수설명
idlong캠페인 ID

응답

성공 응답 (200 OK)

{
  "status": 200,
  "code": null,
  "message": "캠페인 진행 상황 항목 조회가 완료되었습니다.",
  "data": {
    "step": "MATCHING",
    "items": [
      {
        "id": 1,
        "creator": "인플루언서A",
        "creatorEmail": "influencer_a@example.com",
        "influenceId": 12345,
        "profileImg": "https://s3.../profile.jpg",
        "creatorLink": "https://instagram.com/influencer_a",
        "trackingNumber": "1234567890",
        "courierCode": "kr.cjlogistics",
        "customCourierName": null,
        "shippedAt": "2026-05-26T18:02:53",
        "deliveredAt": "2026-05-27T13:56:22",
        "trackingDetail": "{\"lastEvent\":{...},\"events\":{\"edges\":[ ... ]}}",
        "uploadUrl": "https://instagram.com/p/xxx",
        "file": null,
        "aiCheckReady": true,
        "matchingStatus": "MATCHED",
        "deliveryStatus": "DELIVERED",
        "aiCheck": "APPROVED",
        "personCheck": "PENDING",
        "campaignResult": null,
        "recommendReason": "높은 참여율",
        "uploadStatus": "UPLOADED",
        "quotePrice": 100000,
        "currentPrice": 80000,
        "collaborationNote": "특별 요청 사항",
        "reviewInfo": {
          "hasNewSubmission": false,
          "reviews": [
            {
              "reviewRound": 1,
              "reviewId": 101,
              "status": "APPROVED",
              "hasNewSubmission": false,
              "submissionItems": []
            }
          ],
          "uploadApproved": true,
          "finalSubmission": null
        },
        "submissionTimeline": {
          "script": {
            "exists": true,
            "reviewRound": 1,
            "reviewStatus": "APPROVED",
            "submittedAt": "2026-06-09T14:20:00",
            "deadlines": {
              "submissionDeadline": "2026-06-10T23:59:59",
              "submissionOriginalDeadline": "2026-06-08T23:59:59",
              "submissionDeadlineConfirmed": true,
              "reviewDeadline": "2026-06-12T23:59:59",
              "feedbackDeadline": null
            },
            "items": [
              {
                "id": 9001,
                "itemType": "SCRIPT_VIDEO",
                "scriptIndex": 0,
                "currentVersion": 1,
                "status": "APPROVED",
                "isSubmitted": true,
                "submittedAt": "2026-06-09T14:20:00"
              }
            ],
            "events": [
              {
                "triggerType": "TRIGGER_SCRIPT_SUBMITTED",
                "label": "크리에이터 스크립트 제출/재제출 — 검수 마감 산정 (시트: 제출일+2영업일)",
                "phase": "SCRIPT_REVIEW_DEADLINE",
                "triggeredAt": "2026-06-09T14:20:00",
                "previousDeadline": null,
                "newDeadline": "2026-06-11T23:59:59"
              }
            ]
          },
          "video": {
            "exists": true,
            "reviewRound": 2,
            "reviewStatus": "REVIEWING",
            "submittedAt": "2026-06-16T09:00:00",
            "deadlines": {
              "submissionDeadline": "2026-06-15T23:59:59",
              "submissionOriginalDeadline": "2026-06-15T23:59:59",
              "submissionDeadlineConfirmed": true,
              "reviewDeadline": "2026-06-17T23:59:59",
              "feedbackDeadline": "2026-06-16T23:59:59"
            },
            "items": [
              {
                "id": 9100,
                "itemType": "VIDEO",
                "scriptIndex": null,
                "currentVersion": 2,
                "status": "REVIEWING",
                "isSubmitted": true,
                "submittedAt": "2026-06-16T09:00:00"
              }
            ],
            "events": [
              {
                "triggerType": "TRIGGER_VIDEO_SUBMITTED",
                "label": "크리에이터 영상 제출/재제출 — 검수 마감 산정 (시트: 재제출일+2영업일)",
                "phase": "CONTENT_REVIEW_DEADLINE",
                "triggeredAt": "2026-06-14T10:00:00",
                "previousDeadline": null,
                "newDeadline": "2026-06-16T23:59:59"
              },
              {
                "triggerType": "TRIGGER_3R_VIDEO_RESUBMIT_REQUEST",
                "label": "영상 재제출 요청 (Trigger 3 재제출 사이클, 광고주 요청)",
                "phase": "CONTENT_SUBMISSION_DEADLINE",
                "triggeredAt": "2026-06-15T11:00:00",
                "previousDeadline": "2026-06-15T23:59:59",
                "newDeadline": "2026-06-17T23:59:59"
              },
              {
                "triggerType": "TRIGGER_VIDEO_SUBMITTED",
                "label": "크리에이터 영상 제출/재제출 — 검수 마감 산정 (시트: 재제출일+2영업일)",
                "phase": "CONTENT_REVIEW_DEADLINE",
                "triggeredAt": "2026-06-16T09:00:00",
                "previousDeadline": "2026-06-16T23:59:59",
                "newDeadline": "2026-06-18T23:59:59"
              }
            ]
          },
          "upload": {
            "uploadDate": "2026-06-20T23:59:59",
            "uploadType": "OPTIMAL",
            "uploadDeadline": "2026-06-22T23:59:59",
            "deadline": null,
            "events": []
          },
          "finalSubmission": {
            "submittedAt": null,
            "finalSubmissionDeadline": "2026-06-22T23:59:59",
            "finalResubmissionDeadline": null,
            "settlementDeadline": null,
            "contentLink": null,
            "isSubmitted": false,
            "events": []
          }
        },
        "secondaryUsage": {
          "status": "ACTIVE",
          "months": 3,
          "startDate": "2026-01-11",
          "endDate": "2026-04-10",
          "remainingDays": 45,
          "expired": false
        },
        "followerCount": 50000,
        "avgViewCount": 10000,
        "rank": "A",
        "rankPrice": 100000,
        "adjustedEngagementRate": 4.6282,
        "recentPosts": [
          {
            "postId": "abc123",
            "postLink": "https://instagram.com/p/abc123",
            "mediaUrl": "https://video.cdninstagram.com/...",
            "mediaType": "VIDEO",
            "publishedAt": "2025-01-20T14:30:00Z"
          },
          {
            "postId": "def456",
            "postLink": "https://instagram.com/p/def456",
            "mediaUrl": "https://scontent.cdninstagram.com/...",
            "mediaType": "IMAGE",
            "publishedAt": "2025-01-18T10:00:00Z"
          }
        ],
        "contractId": 42,
        "contractStatus": "SIGNED",
        "selectedOptions": [
          {
            "optionId": 1,
            "title": "색상",
            "selected": [
              { "choiceId": 11, "value": "아이보리" }
            ]
          }
        ]
      }
    ],
    "dummyItems": [
      {
        "id": 100000012,
        "creator": "creator_jp_1",
        "profileImg": null,
        "creatorEmail": null,
        "influenceId": null,
        "creatorLink": "https://www.instagram.com/creator_jp_1/",
        "matchingStatus": "waiting",
        "flags": [],
        "followerCount": 12400,
        "avgViewCount": 8300,
        "recommendReason": "뷰티 카테고리 릴스 비중이 높고 ...",
        "rankPrice": 300000,
        "quotePrice": 300000,
        "currentPrice": 250000,
        "recentPosts": [],
        "trackingNumber": null,
        "deliveryStatus": null,
        "aiCheck": null,
        "personCheck": null,
        "uploadStatus": null
      }
    ],
    "isLegacy": false,
    "totalCount": 10,
    "eliminatedCount": 2,
    "eliminatedPercentage": 20.0,
    "campaignDetails": {
      "no": "123",
      "businessId": "business_001",
      "thumbnailImagePath": "https://s3.../thumbnail.jpg",
      "productImagePath": "https://s3.../product.jpg",
      "productImagePaths": ["https://s3.../product1.jpg"],
      "snsType": "INSTAGRAM",
      "contentFormat": "REEL",
      "category": "BEAUTY",
      "campaignType": "SEEDING",
      "campaignSubStep": "CREATOR_RECRUIT",
      "guidelineStatus": "COMPLETED",
      "productName": "상품명",
      "charge": "100000",
      "currency": "KRW",
      "recruitCount": "10",
      "recruitmentDays": 4,
      "recruitmentStartDate": "2024-01-01 00:00:00",
      "recruitmentEndDate": "2024-01-31 23:59:59",
      "campaignContractType": "STANDARD",
      "currentPriceRate": 80.0,
      "quotePriceRate": 125.0
    },
    "budgetSummary": {
      "totalBudget": 1000000,
      "usedCredit": 300000,
      "refundAmount": 700000,
      "lockedCount": 3,
      "status": "ACTIVE"
    },
    "guidelineCompletedAt": "2025-02-15T14:30:00",
    "campaignCompletedAt": "2025-03-20T18:45:10",
    "managers": [
      {
        "managerNo": 42,
        "name": "홍길동",
        "phone": "01000000000",
        "email": "manager@example.com",
        "isDefault": true
      }
    ],
    "businessApproved": false,
    "canEditGuideline": false,
    "regulationReviewEnabled": false
  }
}

Response 스키마

ProgressTableWithCampaignResponse

필드명타입설명
stepstring진행 단계 ("MATCHING" | "EXECUTING")
itemsProgressItemExceptBidPriceResponse[]진행 항목 목록
dummyItemsProgressItemExceptBidPriceResponse[]데모(목업) 후보 목록. items와 동일한 타입이라 같은 컴포넌트로 렌더한다. followerCount·avgViewCount·recommendReason·rankPrice·quotePrice·currentPrice·recentPosts가 실제 신청과 동일하게 채워진다(비어 있지 않다). 진행상태(배송·검수·업로드)와 profileImgnull. 데모임을 드러내는 표기 금지items와 구분 없이 자연스럽게 노출한다. 담긴 데모가 없으면 빈 배열. 연동 가이드
isLegacyboolean레거시 여부
totalCountint전체 항목 수
eliminatedCountint탈락 항목 수
eliminatedPercentagedouble탈락률 (%)
campaignDetailsCampaignFullResponseDto캠페인 상세 정보. [일정 통일 Jay 2026-07-24] recruitmentDays(모집 영업일, 1-10 / 미설정 시 null) 포함 — 아래 Callout 참고
budgetSummaryBudgetSummaryDto캠페인 예산 요약 (SaaS 캠페인만)
guidelineCompletedAtdatetime가이드라인 완성일. 가이드라인 미완성 시 null
campaignCompletedAtdatetime캠페인 완료일 (campaignSubStep = CAMPAIGN_COMPLETED 로 최초 전환된 시각). 아직 완료되지 않았거나 백필 대상이 아닌 레거시 건은 null

campaignDetails.recruitmentDays 는 가이드라인 미리보기의 "예상 일정" 모달용이다 (Jay 2026-07-24)

이 모달은 가이드 완성 에 뜨는 화면이라 /ai/campaign-schedules/{campaignNo}listOpenAt / recruitmentEndAt 이 아직 null 이고, 애초에 그 API 를 호출하지 않는다 (progress-table 만 호출). 그래서 날짜가 아니라 일수를 여기서 내려준다.

프론트는 가이드라인 완성 후 {recruitmentDays} 영업일 이내 로 렌더한다. 기존의 nation === "KR" ? 5 : 7 캘린더일 하드코딩은 2026-05-22 에 폐기된 옛 백엔드 규칙이 프론트에 남아 있던 것이므로 제거한다.

null 이면 관리자가 아직 고르지 않은 상태다. 일정 산정의 기본값 4영업일은 CampaignScheduleService 의 책임이며, 응답 DTO 는 임의로 4 를 채우지 않는다 (실제로 4 를 고른 것과 미설정을 화면이 구분할 수 있어야 한다).

가이드 완성 실제 날짜가 필요한 화면은 캠페인 일정 조회 APIlistOpenAt 을 쓸 것.

| managers | BusinessManagerResponseDto[] | 캠페인 담당자 목록(N:M, 동등). 담당자 미지정 시 빈 배열 | | businessApproved | boolean | 캠페인 소유자(광고주)의 기업 승인(계약 체결) 여부. 계약 상태(contractSignStatus)가 SIGNED / EXCEPTION 이면 true, NONE / PENDING 이면 false. 용도는 상단 안내 참고 | | canEditGuideline | boolean | 광고주가 현재 가이드라인을 수정할 수 있는지 여부 (FE 수정 버튼 노출용). 모집 단계(CREATOR_RECRUIT/CREATOR_MATCHING)에서는 어드민이 수정 허용을 켠 경우에만 true (1회용: 광고주가 완성본을 한 번 저장하면 소진되어 다시 false, 어드민 재허용 필요). 콘텐츠 제작 단계 이후에는 false, 가이드라인 미생성 시 false | | regulationReviewEnabled | boolean | 약기법(일본 광고규정) 검수 사용 여부 (FE 약기법 UI 노출 분기용). 어드민이 캠페인별로 켜는 opt-in 플래그이며, 가이드라인 미생성 시 false. 켜져 있으면 가이드라인 완성·제출물 제출·광고주 피드백 제출 시 약기법 검수가 자동 실행된다. 약기법 검수 개요 |

ProgressItemExceptBidPriceResponse

필드명타입설명
idlong항목 ID
creatorstring크리에이터 이름
creatorEmailstring크리에이터 이메일
influenceIdlong인플루언서 ID
profileImgstring프로필 이미지 URL
creatorLinkstring크리에이터 링크
trackingNumberstring운송장 번호
courierCodestring택배사 코드(kr.xxx) 또는 기타 한글명/OTHER. 미입력 시 null
customCourierNamestring기타 택배사 자유입력명. 지원 택배사(kr.*)면 null. 목록 다운로드(엑셀)의 택배사명 컬럼은 이 값을 사용
shippedAtstring배송 시작(집화) 시각. 추적 전/불가 시 null
deliveredAtstring배송 완료 시각. 완료 전 null
trackingDetailstring(JSON)배송조회 전체 응답(타임라인). 미조회 시 null. 구조는 배송 상세조회 문서 참고
uploadUrlstring업로드 URL
filestring파일 URL
aiCheckReadybooleanAI 체크 준비 상태
matchingStatusstring매칭 상태
deliveryStatusstring배송 상태
aiCheckstringAI 검수 상태
personCheckstring담당자 검수 상태
campaignResultstring캠페인 결과 URL
recommendReasonstring추천 이유
uploadStatusstring업로드 상태
quotePricelong견적 가격
currentPricelong현재 가격
collaborationNotestring협업 노트
reviewInfoReviewInfo검수 정보 (기존, 유지)
submissionTimelineSubmissionTimeline[TASK-081] 콘텐츠 제출 일정 4그룹(스크립트/영상/업로드/최종제출물). 각 그룹의 마감일·제출일·제출기록(언제 제출/재제출/검수했는지 이벤트 타임라인). 아래 SubmissionTimeline 참고
secondaryUsageSecondaryUsageInfo2차 활용 기간 표기(기업 대시보드). 최종제출물 "모두 제출 완료"일 ~ N개월(90일 아닌 개월수 기준). 아래 SecondaryUsage 참고
followerCountlong팔로워 수
avgViewCountlong평균 조회수
rankstring랭크 (A/B/C 등)
rankPriceint랭크별 가격
adjustedEngagementRatedouble보정 참여율(%). PostgreSQL influencer_profile.adjusted_engagement_rate 원본값. 미산정 계정은 null. 아래 보정 참여율 참고
recentPostsPostMediaDto[]최근 게시물 미디어 (최대 3개)
contractIdlong전자계약서 ID (계약서 미발송 시 null)
contractStatusstring전자계약 상태 (DRAFT, SENT, OPENED, FILLED, OTP_VERIFIED, SIGNED). 계약서 미발송 시 null
selectedOptionsarray캠페인 제공 옵션 — 크리에이터가 선택한 값 (그룹별로 묶음). 옵션 정의는 GET /ai/campaign/{collabNo}/provided-options, 정책은 캠페인 제공 옵션 개요 참고. 옵션 미정의/미선택 시 빈 배열

PostMediaDto

필드명타입설명
postIdstring게시물 ID
postLinkstring게시물 링크
mediaUrlstring미디어 URL (video_url 또는 images 중 첫 번째)
mediaTypestring미디어 타입 (VIDEO 또는 IMAGE)
publishedAtdatetime게시일

recentPosts는 PostgreSQL의 post 테이블에서 조회됩니다.

  • video_url이 있으면 mediaType: VIDEO로 반환
  • video_url이 없으면 images의 첫 번째 이미지를 mediaType: IMAGE로 반환

보정 참여율

adjustedEngagementRate는 크롤링 PostgreSQL의 influencer_profile.adjusted_engagement_rate 값을 반올림 없이 그대로 내려줍니다.

  • 단위: 퍼센트(%). 예를 들어 4.6282는 4.6282% 를 뜻합니다.
  • 조회 기준: is_current = true 인 프로필을 sns_account_link 로 매칭합니다.
  • 데이터 소스 예외: followerCount/avgViewCount는 Instagram OAuth 연동 데이터(SocialAccount)가 있으면 그쪽을 우선합니다. 반면 adjustedEngagementRate는 크롤링 PostgreSQL 에만 존재하는 값이라 연동 여부와 무관하게 항상 PostgreSQL 프로필에서 채웁니다.
  • null 인 경우: 매칭되는 프로필이 없거나, 프로필은 있어도 참여율이 아직 산정되지 않은 계정. 전체 프로필 중 약 1/3 만 값이 채워져 있으므로 프런트는 null 처리를 반드시 넣어야 합니다.

BusinessManagerResponseDto

필드명타입설명
managerNolong담당자 번호
namestring담당자 이름
phonestring담당자 연락처
emailstring담당자 이메일
isDefaultboolean기본 담당자 여부

BudgetSummaryDto (SaaS 캠페인만 반환)

필드명타입설명
totalBudgetint캠페인 총 예산 (CAMPAIGN_DEPOSIT 합계)
usedCreditint사용(LOCKED) 금액 합계
refundAmountint환급 가능 금액 (totalBudget - usedCredit)
lockedCountlong잠금된 건수
statusstring상태 ("ACTIVE")

budgetSummary는 SaaS 캠페인(collabNo >= saasNum)에서만 반환됩니다. 레거시 캠페인은 null이 반환됩니다.

[TASK-071 2026-05-26] guidelineCompletedAt 출처 변경:

  • 주 출처: MongoDB GuidelineDocument.completedAt (v1/v2/v4 publish 시 자동 set, 운영자 정정 가능)
  • Fallback (legacy): 위 값이 없으면 Collab.recruitment_start_date
  • 가이드라인 상태가 COMPLETED 가 아니면 fallback 도 시도하지 않고 null 반환

campaignCompletedAtTB_COLLAB.campaign_completed_at 컬럼 값입니다.

  • PATCH /ai/admin/campaigns/{campaignNo}/substep?substep=CAMPAIGN_COMPLETED 를 호출해 최초로 CAMPAIGN_COMPLETED 상태가 되는 순간 서버 시각(LocalDateTime.now())으로 기록됩니다.
  • 이미 값이 있으면 재호출해도 덮어쓰지 않습니다 (최초 완료 시각 유지).
  • 기존 완료 캠페인은 FinalSubmission.submitted_at 중 MAX 값으로 일회성 백필되어 있습니다. 최종 제출물이 전혀 없는 레거시 완료 건은 null입니다.

예산 관련 에러 응답

매칭 상태를 PROPOSAL로 변경할 때 예산 검증 실패 시 발생하는 에러입니다.

상태 코드에러 코드설명
400NEED_CAMPAIGN_DEPOSIT캠페인 예산이 부족합니다. 추가 입금이 필요합니다.
400INSUFFICIENT_GLOBAL_CREDIT기업 크레딧이 부족합니다. 크레딧을 충전해주세요.
403PROPOSAL_STATUS_CHANGE_NOT_ALLOWED제안 상태의 크리에이터는 기업에서 상태를 변경할 수 없습니다. 관리자에게 문의해주세요.
404BUDGET_NOT_FOUND캠페인 예산 정보를 찾을 수 없습니다.
400BUDGET_ALREADY_LOCKED이미 예산이 예약되어 있습니다.
400BUDGET_ALREADY_UNLOCKED이미 예산이 취소되었습니다.

NEED_CAMPAIGN_DEPOSIT 발생 시: 캠페인 예산 추가 입금 API (POST /ai/payments/collab/confirm)를 호출하세요.

INSUFFICIENT_GLOBAL_CREDIT 발생 시: 크레딧 충전 API (POST /ai/payments/credit/confirm)를 먼저 호출하세요.

SubmissionTimeline

[TASK-081] 콘텐츠 제출 일정을 4그룹으로 묶어 내려줍니다. 데드라인 / 제출일 / 제출기록(이벤트 타임라인)을 한 번에 표시하기 위한 블록입니다. 기존 reviewInfo는 그대로 유지되며 이 블록이 추가됩니다.

그룹대상
스크립트script2회검수(대본검수) 캠페인만 존재. 1회검수 캠페인은 null
영상video영상/제작물 검수
업로드upload업로드일자·업로드타입·업로드 데드라인
최종제출물finalSubmission최종제출물(콘텐츠 링크/파일)·재제출 마감·정산

그룹 객체 (script / video) — SubmissionPhaseGroup

필드타입설명
existsboolean그룹 존재 여부
reviewRoundint1=스크립트, 2=영상
reviewStatusstring해당 라운드 검수 상태 (PENDING, REVIEWING, APPROVED, REJECTED). 없으면 null
submittedAtLocalDateTime제출일(최신 제출 시각). 미제출 시 null
deadlinesGroupDeadlines마감 세트 (아래)
itemsSubmissionItemSnapshot[]현재(최신 버전) 제출물 목록
eventsTimelineEvent[]제출/재제출/검수 이벤트 타임라인 (시각 오름차순)

GroupDeadlines

필드타입설명
submissionDeadlineLocalDateTime제출 마감
submissionOriginalDeadlineLocalDateTime최초 제출 마감(불변, 참조용)
submissionDeadlineConfirmedboolean트리거 발동으로 확정됐는지. false면 임시(placeholder) 마감
reviewDeadlineLocalDateTime검수 마감(기업쪽). 없으면 null
feedbackDeadlineLocalDateTime피드백 반영 마감(재제출 발생 시). 없으면 null

uploadUploadGroup

필드타입설명
uploadDateLocalDateTime업로드일자 (업로드 허용일)
uploadTypestring업로드타입 (OPTIMAL, CANDIDATE, ASAP 등)
uploadDeadlineLocalDateTime[태스크21] 업로드/최종제출물 제출 마감 = 업로드 허용일 + 2일(ASAP/OPTIMAL), CANDIDATE는 고른 날 그대로. 업로드 단계(영상검수 승인) 도달 전이면 null. 아래 deadline(재제출 마감)과 별개
deadlineLocalDateTime업로드 데드라인 (= 최종제출물 재제출 마감과 동일 값). 없으면 null
eventsTimelineEvent[]업로드 관련 이벤트 타임라인

finalSubmissionFinalSubmissionGroup

필드타입설명
submittedAtLocalDateTime최종제출물 제출 시각
finalSubmissionDeadlineLocalDateTime[태스크21] 최종제출물 제출 마감 (= upload.uploadDeadline과 동일 값, 업로드 허용일 + 2일). 업로드 단계 도달 전이면 null. finalResubmissionDeadline(재제출 마감)과 별개
finalResubmissionDeadlineLocalDateTime재제출 마감(재요청 시). 없으면 null
settlementDeadlineLocalDateTime정산 마감(업로드 완료 후). 없으면 null
contentLinkstring업로드한 콘텐츠 링크
isSubmittedboolean최종제출 여부
eventsTimelineEvent[]최종제출/재요청/정산 이벤트 타임라인

SubmissionItemSnapshot (현재 제출물)

필드타입설명
idlong제출물 ID
itemTypestringSCRIPT_VIDEO, SCRIPT_BLOG, VIDEO, PHOTO, CAPTION, HASHTAG
scriptIndexint복수 스크립트 슬롯 구분 (비스크립트면 null)
currentVersionint현재 버전 번호
statusstring제출물 검수 상태
isSubmittedboolean제출 완료 여부
submittedAtLocalDateTime현재 버전 제출 시각

TimelineEvent (제출기록 = 언제 무슨 일이 있었는지)

TB_TRIGGER_LOG 기반의 append-only 이벤트입니다. triggeredAt실제 이벤트가 일어난 시각(제출/재제출요청/검수완료 등)입니다. 재제출이 여러 번이면 같은 그룹의 events에 여러 행이 시각순으로 누적됩니다.

필드타입설명
triggerTypestring트리거 종류 (예: TRIGGER_SCRIPT_SUBMITTED, TRIGGER_VIDEO_SUBMITTED, TRIGGER_3R_VIDEO_RESUBMIT_REQUEST, TRIGGER_2_SCRIPT_REVIEW_DONE)
labelstring트리거 한국어 설명
phasestring갱신된 일정 단계 (ApplicationSchedulePhase)
triggeredAtLocalDateTime이벤트 발생 시각 (= 제출/재제출/검수 시점)
previousDeadlineLocalDateTime이 이벤트 직전 마감일
newDeadlineLocalDateTime이 이벤트로 갱신된 마감일

그룹 분류 규칙: ContentReview.reviewRound(1=스크립트, 2=영상) 기준입니다. eventsphase로 그룹에 매핑되며, 라운드가 공유하는 FEEDBACK_DEADLINEtriggerType으로 분리됩니다. 스크립트 검수가 없는 1회검수 캠페인은 scriptnull입니다.

events는 일정(마감)에 영향을 준 트리거만 기록합니다(순수 임시저장은 제외). 실제 제출/재제출/검수승인은 모두 기록됩니다. 버전별 파일 내용은 items(현재 버전)와 reviewInfo를 함께 참고하세요.

SecondaryUsage

기업 대시보드에서 크리에이터별 2차 활용 기간을 표기(카운트다운 → 만료)하기 위한 블록입니다. 시작일은 해당 크리에이터가 최종제출물을 모두 제출 완료한 날이며, 종료일은 시작일 + N개월 − 1일입니다 (90일 카운팅이 아니라 개월수 기준. 예: 시작 1/11, 3개월 → 만료 4/10). 기간은 최초 제출 완료 시점에 확정되며, 이후 재제출이나 캠페인 개월수 변경에도 바뀌지 않습니다.

필드타입설명
statusstringNONE(2차활용 없음, 0개월) | PERMANENT(영구, -1) | NOT_STARTED(최종제출 전) | ACTIVE(진행중) | EXPIRED(만료)
monthsint2차 활용 개월수. -1=영구, 0=없음
startDatedate2차 활용 시작일(= 최종제출 완료일). NONE/PERMANENT/NOT_STARTED이면 null
endDatedate만료일(포함 마지막 날, = 시작일 + N개월 − 1일). 영구/없음/미제출이면 null
remainingDayslong오늘부터 만료일까지 남은 일수(만료 후 음수). 해당 없으면 null. D-{remainingDays} 표기용
expiredboolean만료 여부(오늘 > 만료일)

프런트는 이 값으로 2차활용 기간: {startDate}~{endDate} ({months}개월) + D-{remainingDays}(만료 시 "2차활용 만료")를 렌더합니다. remainingDays는 서버 기준일(KST)로 계산됩니다.

API 테스트

On this page