Glowb Dev Docs
SaaS APIProgress Table

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

캠페인 진행 항목 조회

캠페인 진행 항목 조회

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

기업 승인 전(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",
        "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
        },
        "followerCount": 50000,
        "avgViewCount": 10000,
        "rank": "A",
        "rankPrice": 100000,
        "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": "아이보리" }
            ]
          }
        ]
      }
    ],
    "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",
      "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"
    },
    "deficitLock": {
      "engaged": true,
      "amount": 300000,
      "status": "LOCKED",
      "threshold": 800000,
      "sumLockedNormal": 500000,
      "policyEnabled": true
    },
    "guidelineCompletedAt": "2025-02-15T14:30:00",
    "campaignCompletedAt": "2025-03-20T18:45:10",
    "managers": [
      {
        "managerNo": 42,
        "name": "홍길동",
        "phone": "01000000000",
        "email": "manager@example.com",
        "isDefault": true
      }
    ],
    "paymentStatus": "PAID",
    "businessApproved": false,
    "canEditGuideline": false
  }
}

Response 스키마

ProgressTableWithCampaignResponse

필드명타입설명
stepstring진행 단계 ("MATCHING" | "EXECUTING")
itemsProgressItemExceptBidPriceResponse[]진행 항목 목록
isLegacyboolean레거시 여부
totalCountint전체 항목 수
eliminatedCountint탈락 항목 수
eliminatedPercentagedouble탈락률 (%)
campaignDetailsCampaignFullResponseDto캠페인 상세 정보
budgetSummaryBudgetSummaryDto캠페인 예산 요약 (SaaS 캠페인만)
deficitLockDeficitLockResponseDto80% 부족분 lock 스냅샷. 모달 진입 전 FE 분기 처리용. 상세는 부족분 lock 조회 참조. SaaS 이전 캠페인은 engaged=false, policyEnabled=false
guidelineCompletedAtdatetime가이드라인 완성일. 가이드라인 미완성 시 null
campaignCompletedAtdatetime캠페인 완료일 (campaignSubStep = CAMPAIGN_COMPLETED 로 최초 전환된 시각). 아직 완료되지 않았거나 백필 대상이 아닌 레거시 건은 null
managersBusinessManagerResponseDto[]캠페인 담당자 목록(N:M, 동등). 담당자 미지정 시 빈 배열
paymentStatusstring | null결제 상태. UNPAID / PAYMENT_PENDING / PAID 또는 null (트래킹 대상 아님). 도출 규칙은 아래 참고
businessApprovedboolean캠페인 소유자(광고주)의 기업 승인(계약 체결) 여부. 계약 상태(contractSignStatus)가 SIGNED / EXCEPTION 이면 true, NONE / PENDING 이면 false. 용도는 상단 안내 참고
canEditGuidelineboolean광고주가 현재 가이드라인을 수정할 수 있는지 여부 (FE 수정 버튼 노출용). 모집 단계(CREATOR_RECRUIT/CREATOR_MATCHING)에서는 어드민이 수정 허용을 켠 경우에만 true (1회용: 광고주가 완성본을 한 번 저장하면 소진되어 다시 false, 어드민 재허용 필요). 콘텐츠 제작 단계 이후에는 false, 가이드라인 미생성 시 false

ProgressItemExceptBidPriceResponse

필드명타입설명
idlong항목 ID
creatorstring크리에이터 이름
creatorEmailstring크리에이터 이메일
influenceIdlong인플루언서 ID
profileImgstring프로필 이미지 URL
creatorLinkstring크리에이터 링크
trackingNumberstring운송장 번호
courierCodestring택배사 코드(kr.xxx) 또는 기타 한글명/OTHER. 미입력 시 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검수 정보
followerCountlong팔로워 수
avgViewCountlong평균 조회수
rankstring랭크 (A/B/C 등)
rankPriceint랭크별 가격
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로 반환

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입니다.

paymentStatus 도출 규칙

  • TB_CAMPAIGN_PAYMENT_VERIFICATION 행이 존재하면 그 행의 payment_status 값을 그대로 반환합니다.
    • admin 이 캠페인 단계 변경 API(PATCH /ai/admin/campaigns/{campaignNo}/step) 로 UNPAID / PAYMENT_PENDING / PAID 처리한 캠페인은 모두 행이 존재합니다.
  • 행이 없으면 null — 결제 트래킹 대상 아님 (CandyPay 정상 결제 흐름은 verification 행을 만들지 않음).

PAYMENT_PENDING 캠페인은 같은 응답에서 items 가 빈 배열로 반환됩니다 (영업 결제 대기 중 인원 노출 차단).

예산 관련 에러 응답

매칭 상태를 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)를 먼저 호출하세요.

API 테스트

On this page