Progress Table API
캠페인 진행 상황 관리 API
Progress Table API
캠페인 진행 상황 관리 API입니다.
Base URL: /ai/progress-table
인증 정보
| 항목 | 값 |
|---|---|
| 인증 필요 | 일부 필요 |
| 인증 방식 | JWT Bearer Token |
엔드포인트 목록
진행 항목 관리
| 메서드 | 경로 | 설명 | 인증 |
|---|---|---|---|
POST | /ai/progress-table/items/admin | 진행 항목 생성 | 불필요 |
GET | /ai/progress-table/item/{id} | 캠페인 진행 항목 조회 | 필요 |
GET | /ai/progress-table/items/{id} | 특정 항목 조회 | 불필요 |
DELETE | /ai/progress-table/items/{id} | 항목 삭제 | 불필요 |
매칭 상태
| 메서드 | 경로 | 설명 | 인증 |
|---|---|---|---|
PUT | /ai/progress-table/items/{id}/user/matching-status | 사용자 매칭 상태 변경 | 불필요 |
PUT | /ai/progress-table/items/{id}/admin/matching-status | 관리자 매칭 상태 변경 | 불필요 |
PUT | /ai/progress-table/items/bulk/user/matching-status | 사용자 대량 매칭 상태 | 필요 |
PUT | /ai/progress-table/items/bulk/admin/matching-status | 관리자 대량 매칭 상태 | 불필요 |
POST | /ai/progress-table/items/bulk/proposal-with-charge | 예산 자동 충전 + 제안 일괄 처리 | 필요 |
검수 관리
| 메서드 | 경로 | 설명 | 인증 |
|---|---|---|---|
PUT | /ai/progress-table/items/bulk/admin/ai-check | AI 체크 상태 대량 업데이트 | 불필요 |
PUT | /ai/progress-table/items/bulk/user/ai-check | 사용자 AI 체크 상태 대량 업데이트 | 필요 |
PUT | /ai/progress-table/items/bulk/user/person-check | 기업 최종 검수 대량 업데이트 | 필요 |
PUT | /ai/progress-table/items/{id}/ai-check-ready | AI 체크 준비 상태 업데이트 | 불필요 |
PUT | /ai/progress-table/reviews/bulk | 벌크 1차/2차 검수 처리 | 불필요 |
배송 관리
| 메서드 | 경로 | 설명 | 인증 |
|---|---|---|---|
PUT | /ai/progress-table/items/{id}/delivery-status | 배송 상태 업데이트 | 불필요 |
PUT | /ai/progress-table/items/{id}/tracking-number | 추적 번호 업데이트 | 불필요 |
PUT | /ai/progress-table/application/delivery/tracking | 운송장 번호 저장/수정 | 필요 |
PUT | /ai/progress-table/application/delivery/status/bulk | 배송 상태 일괄 변경 | 필요 |
GET | /ai/progress-table/application/{applicationId}/delivery | 배송 정보 조회 | 불필요 |
GET | /ai/progress-table/collab/{collabNo}/delivery-addresses | 선정된 인플루언서 배송지 목록 | 필요 |
기타
| 메서드 | 경로 | 설명 | 인증 |
|---|---|---|---|
PUT | /ai/progress-table/items/{id}/admin/upload-url | 업로드 URL 업데이트 | 불필요 |
PUT | /ai/progress-table/items/{id}/admin/campaign-result | 캠페인 결과 URL 업데이트 | 불필요 |
PUT | /ai/progress-table/items/{id}/admin/campaign-result-status | 캠페인 결과 상태 업데이트 | 불필요 |
PUT | /ai/progress-table/items/{id}/bid-price | 입찰 가격 업데이트 | 불필요 |
PATCH | /ai/progress-table/note/{id} | 협업 노트 업데이트 | 필요 |
POST | /ai/progress-table/item/please-redo | 재요청 | 필요 |
POST | /ai/progress-table/final-submissions/bulk | 벌크 최종 제출물 조회 | 불필요 |
API 상세
진행 항목 생성
새로운 진행 상황 항목을 생성합니다.
HTTP 요청
POST /ai/progress-table/items/admin
Content-Type: application/jsonRequest Body
{
"collabNo": 123,
"influenceId": "user123",
"applicationId": 456,
"matchingStatus": "PENDING"
}응답
성공 응답 (201 Created)
{
"status": 201,
"code": null,
"message": "새로운 진행 상황 항목이 생성되었습니다.",
"data": {
"id": 1,
"collabNo": 123,
"matchingStatus": "PENDING"
}
}캠페인 진행 항목 조회
기업 대시보드용 캠페인 진행 항목을 조회합니다.
HTTP 요청
GET /ai/progress-table/item/{id}
Authorization: Bearer {access_token}Path Parameters
| 파라미터 | 타입 | 필수 | 설명 |
|---|---|---|---|
id | long | 예 | 캠페인 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",
"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"
}
]
}
],
"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"
},
"budgetSummary": {
"totalBudget": 1000000,
"usedCredit": 300000,
"refundAmount": 700000,
"lockedCount": 3,
"status": "ACTIVE"
}
}
}Response 스키마
ProgressTableWithCampaignResponse
| 필드명 | 타입 | 설명 |
|---|---|---|
step | string | 진행 단계 ("MATCHING" | "EXECUTING") |
items | ProgressItemExceptBidPriceResponse[] | 진행 항목 목록 |
isLegacy | boolean | 레거시 여부 |
totalCount | int | 전체 항목 수 |
eliminatedCount | int | 탈락 항목 수 |
eliminatedPercentage | double | 탈락률 (%) |
campaignDetails | CampaignFullResponseDto | 캠페인 상세 정보 |
budgetSummary | BudgetSummaryDto | 캠페인 예산 요약 (SaaS 캠페인만) |
ProgressItemExceptBidPriceResponse
| 필드명 | 타입 | 설명 |
|---|---|---|
id | long | 항목 ID |
creator | string | 크리에이터 이름 |
creatorEmail | string | 크리에이터 이메일 |
influenceId | long | 인플루언서 ID |
profileImg | string | 프로필 이미지 URL |
creatorLink | string | 크리에이터 링크 |
trackingNumber | string | 운송장 번호 |
uploadUrl | string | 업로드 URL |
file | string | 파일 URL |
aiCheckReady | boolean | AI 체크 준비 상태 |
matchingStatus | string | 매칭 상태 |
deliveryStatus | string | 배송 상태 |
aiCheck | string | AI 검수 상태 |
personCheck | string | 담당자 검수 상태 |
campaignResult | string | 캠페인 결과 URL |
recommendReason | string | 추천 이유 |
uploadStatus | string | 업로드 상태 |
quotePrice | long | 견적 가격 |
currentPrice | long | 현재 가격 |
collaborationNote | string | 협업 노트 |
reviewInfo | ReviewInfo | 검수 정보 |
followerCount | long | 팔로워 수 |
avgViewCount | long | 평균 조회수 |
rank | string | 랭크 (A/B/C 등) |
rankPrice | int | 랭크별 가격 |
recentPosts | PostMediaDto[] | 최근 게시물 미디어 (최대 3개) |
PostMediaDto
| 필드명 | 타입 | 설명 |
|---|---|---|
postId | string | 게시물 ID |
postLink | string | 게시물 링크 |
mediaUrl | string | 미디어 URL (video_url 또는 images 중 첫 번째) |
mediaType | string | 미디어 타입 (VIDEO 또는 IMAGE) |
publishedAt | datetime | 게시일 |
recentPosts는 PostgreSQL의 post 테이블에서 조회됩니다.
video_url이 있으면mediaType: VIDEO로 반환video_url이 없으면images의 첫 번째 이미지를mediaType: IMAGE로 반환
BudgetSummaryDto (SaaS 캠페인만 반환)
| 필드명 | 타입 | 설명 |
|---|---|---|
totalBudget | int | 캠페인 총 예산 (CAMPAIGN_DEPOSIT 합계) |
usedCredit | int | 사용(LOCKED) 금액 합계 |
refundAmount | int | 환급 가능 금액 (totalBudget - usedCredit) |
lockedCount | long | 잠금된 건수 |
status | string | 상태 ("ACTIVE") |
budgetSummary는 SaaS 캠페인(collabNo >= saasNum)에서만 반환됩니다.
레거시 캠페인은 null이 반환됩니다.
예산 관련 에러 응답
매칭 상태를 PROPOSAL로 변경할 때 예산 검증 실패 시 발생하는 에러입니다.
| 상태 코드 | 에러 코드 | 설명 |
|---|---|---|
| 400 | NEED_CAMPAIGN_DEPOSIT | 캠페인 예산이 부족합니다. 추가 입금이 필요합니다. |
| 400 | INSUFFICIENT_GLOBAL_CREDIT | 기업 크레딧이 부족합니다. 크레딧을 충전해주세요. |
| 403 | PROPOSAL_STATUS_CHANGE_NOT_ALLOWED | 제안 상태의 크리에이터는 기업에서 상태를 변경할 수 없습니다. 관리자에게 문의해주세요. |
| 404 | BUDGET_NOT_FOUND | 캠페인 예산 정보를 찾을 수 없습니다. |
| 400 | BUDGET_ALREADY_LOCKED | 이미 예산이 예약되어 있습니다. |
| 400 | BUDGET_ALREADY_UNLOCKED | 이미 예산이 취소되었습니다. |
NEED_CAMPAIGN_DEPOSIT 발생 시: 캠페인 예산 추가 입금 API (POST /ai/payments/collab/confirm)를 호출하세요.
INSUFFICIENT_GLOBAL_CREDIT 발생 시: 크레딧 충전 API (POST /ai/payments/credit/confirm)를 먼저 호출하세요.
사용자 매칭 상태 변경
사용자가 매칭 상태를 변경합니다.
HTTP 요청
PUT /ai/progress-table/items/{id}/user/matching-status?matchingStatus={status}Path Parameters
| 파라미터 | 타입 | 필수 | 설명 |
|---|---|---|---|
id | long | 예 | 진행 항목 ID |
Query Parameters
| 파라미터 | 타입 | 필수 | 설명 |
|---|---|---|---|
matchingStatus | string | 예 | 매칭 상태 |
매칭 상태
| 상태 | 설명 |
|---|---|
PENDING | 대기 중 |
MATCHED | 매칭됨 |
REJECTED | 거절됨 |
COMPLETED | 완료 |
대량 매칭 상태 업데이트 (사용자)
여러 항목의 매칭 상태를 한번에 업데이트합니다.
HTTP 요청
PUT /ai/progress-table/items/bulk/user/matching-status
Authorization: Bearer {access_token}
Content-Type: application/jsonRequest Body
{
"itemIds": [1, 2, 3, 4, 5],
"matchingStatus": "MATCHED"
}응답
성공 응답 (200 OK)
{
"status": 200,
"code": null,
"message": "대량 매칭 상태 업데이트가 완료되었습니다.",
"data": [1, 2, 3, 4, 5]
}예산 자동 충전 + 제안 일괄 처리
캠페인 예산이 부족한 경우 글로벌 크레딧에서 자동으로 충전한 후, 선택된 인플루언서들의 상태를 PROPOSAL로 변경하고 예산을 LOCK합니다.
처리 흐름
- 선택된 Application들의 총 필요 금액 계산
- 캠페인 가용 예산 확인
- 예산 부족 시 글로벌 크레딧에서 캠페인 예산으로 자동 충전 (
forceCharge=true인 경우) - 각 Application에 대해 예산 LOCK + 상태 PROPOSAL로 변경
- 상세 트래킹 정보 반환
HTTP 요청
POST /ai/progress-table/items/bulk/proposal-with-charge
Authorization: Bearer {access_token}
Content-Type: application/jsonRequest Body
{
"collabId": 123,
"itemIds": [1, 2, 3],
"forceCharge": true
}Request Body 스키마
| 필드명 | 타입 | 필수 | 설명 |
|---|---|---|---|
collabId | long | 예 | 캠페인 ID (collabNo) |
itemIds | array<long> | 예 | CampaignApplication ID 목록 |
forceCharge | boolean | 아니오 | 예산 부족 시 자동 충전 여부 (기본: true) |
응답
성공 응답 (200 OK)
{
"status": 200,
"code": null,
"message": "3명의 크리에이터에게 제안을 보냈습니다.",
"data": {
"success": true,
"message": "3명의 크리에이터에게 제안을 보냈습니다.",
"totalRequested": 3,
"totalProcessed": 3,
"totalAmount": 1500000,
"budgetBefore": 500000,
"budgetAfter": 0,
"chargedAmount": 1000000,
"globalCreditBefore": 5000000,
"globalCreditAfter": 4000000,
"processedItems": [
{
"applicationId": 1,
"influenceName": "인플루언서A",
"amount": 500000,
"success": true
},
{
"applicationId": 2,
"influenceName": "인플루언서B",
"amount": 500000,
"success": true
},
{
"applicationId": 3,
"influenceName": "인플루언서C",
"amount": 500000,
"success": true
}
],
"failedItems": null
}
}Response Body 스키마
| 필드명 | 타입 | 설명 |
|---|---|---|
success | boolean | 처리 성공 여부 |
message | string | 결과 메시지 |
errorCode | string | 실패 시 에러 코드 |
totalRequested | int | 요청된 총 인원수 |
totalProcessed | int | 성공적으로 처리된 인원수 |
totalAmount | int | 총 차감 금액 |
budgetBefore | int | 처리 전 캠페인 가용 예산 |
budgetAfter | int | 처리 후 캠페인 가용 예산 |
chargedAmount | int | 글로벌 크레딧에서 충전한 금액 (0이면 충전 없음) |
globalCreditBefore | int | 처리 전 글로벌 크레딧 |
globalCreditAfter | int | 처리 후 글로벌 크레딧 |
processedItems | array | 성공한 항목별 처리 결과 |
failedItems | array | 실패 항목 (부분 실패 시) |
ProposalItemResult 스키마
| 필드명 | 타입 | 설명 |
|---|---|---|
applicationId | long | Application ID |
influenceName | string | 인플루언서 이름 |
amount | int | 차감 금액 |
success | boolean | 처리 성공 여부 |
errorMessage | string | 실패 시 에러 메시지 |
에러 응답
| 상태 코드 | 에러 코드 | 설명 |
|---|---|---|
| 400 | LEGACY_CAMPAIGN | 레거시 캠페인은 이 기능을 사용할 수 없습니다 |
| 400 | NO_APPLICATIONS | 처리할 신청 항목이 없습니다 |
| 400 | NO_ELIGIBLE_ITEMS | 처리 가능한 항목이 없습니다 |
| 400 | BUDGET_001 | 캠페인 예산이 부족합니다 (forceCharge=false일 때) |
| 400 | BUDGET_002 | 기업 크레딧이 부족합니다 |
자동 충전이 발생하는 경우
chargedAmount > 0이면 글로벌 크레딧에서 캠페인 예산으로 자동 이체가 발생한 것입니다.
이 경우 CreditTransaction 테이블에 CAMPAIGN_DEPOSIT 타입으로 기록됩니다.
예산 관리 정책
- 크리에이터 제안 시 예산 LOCK은
CampaignBudget테이블에서만 관리됩니다 CreditTransaction은 글로벌 크레딧 ↔ 캠페인 예산 간 이동 시에만 기록됩니다- 제안 취소(UNLOCK) 시에도
CreditTransaction은 기록되지 않습니다
벌크 1차/2차 검수 처리
여러 신청자의 검수 상태를 한번에 승인/반려 처리합니다.
- 1차 검수 승인 시: 2차 검수 라운드 생성 + Phase를 SECOND_REVIEW로 변경
- 2차 검수 승인 시: 업로드 허용 + Phase를 UPLOAD_SETTLEMENT로 변경
- 반려 시: 재제출 상태로 변경 (Phase 유지)
HTTP 요청
PUT /ai/progress-table/reviews/bulk
Content-Type: application/jsonRequest Body
{
"applicationIds": [1, 2, 3],
"action": "APPROVE",
"reviewRound": 1
}action 옵션
| 액션 | 설명 |
|---|---|
APPROVE | 승인 |
REJECT | 반려 |
운송장 번호 저장/수정
applicationId로 배송 정보를 저장하거나 수정합니다.
HTTP 요청
PUT /ai/progress-table/application/delivery/tracking
Authorization: Bearer {access_token}
Content-Type: application/jsonRequest Body
{
"applicationId": 123,
"courier": "CJ대한통운",
"trackingNumber": "1234567890"
}배송 상태 일괄 변경
여러 신청의 배송 상태를 일괄 변경합니다.
HTTP 요청
PUT /ai/progress-table/application/delivery/status/bulk
Authorization: Bearer {access_token}
Content-Type: application/jsonRequest Body
{
"applicationIds": [1, 2, 3],
"deliveryStatus": "SHIPPED"
}배송 상태
| 상태 | 설명 |
|---|---|
beforeDelivery | 배송 전 |
shipping | 배송 중 |
delivered | 배송 완료 |
선정된 인플루언서 배송지 목록 조회
캠페인에서 선정된 인플루언서들의 배송지 정보를 조회합니다. 다운로드용입니다.
HTTP 요청
GET /ai/progress-table/collab/{collabNo}/delivery-addresses
Authorization: Bearer {access_token}협업 노트 업데이트
진행 항목의 협업 노트를 업데이트합니다.
HTTP 요청
PATCH /ai/progress-table/note/{id}
Authorization: Bearer {access_token}
Content-Type: application/jsonRequest Body
{
"collaborationNote": "특별 요청 사항: 제품 클로즈업 추가 필요"
}재요청
콘텐츠 재제출을 요청합니다.
HTTP 요청
POST /ai/progress-table/item/please-redo
Authorization: Bearer {access_token}
Content-Type: application/jsonRequest Body
{
"itemIds": [1, 2, 3],
"rejectReason": "영상 품질 미달"
}사용 예시
대량 매칭 상태 업데이트
curl -X PUT https://api.glowb.io/ai/progress-table/items/bulk/user/matching-status \
-H "Authorization: Bearer {token}" \
-H "Content-Type: application/json" \
-d '{
"itemIds": [1, 2, 3],
"matchingStatus": "MATCHED"
}'벌크 검수 처리
curl -X PUT https://api.glowb.io/ai/progress-table/reviews/bulk \
-H "Content-Type: application/json" \
-d '{
"applicationIds": [1, 2, 3],
"action": "APPROVE",
"reviewRound": 1
}'