SaaS API광고주 캠페인 초안
POST /ai/business/collab/draft
광고주 직접 캠페인 초안 생성
광고주 직접 캠페인 초안 생성
비즈니스(광고주) 사용자가 해피콜 이전 단계에서 캠페인 초안을 직접 생성합니다.
제목은 제품명을 보내면 [브랜드명] 제품명 캠페인, 보내지 않으면 [브랜드명] 캠페인 으로 자동 세팅됩니다. 수수료(feePolicyType / feeType / feeValue) 는 NULL 로 저장되어 관리자가 해피콜 후 채웁니다. category 는 필수이며, 미지정 시 400 BD_005 입니다.
이 경로로 만든 캠페인은 카테고리와 무관하게 항상 기업 주도 플로우(flowType = BUSINESS_DIRECT)로 확정됩니다. 이후 진행 단계와 프런트 판정 방법은 기업 주도 캠페인 플로우를 참고하세요.
생성 즉시 대시보드에 노출되며, 모집 일정은 now ~ now + 5일 로 기본 세팅된 뒤 이후 단계(EXCLUSION_SELECTION ~ SETTLEMENT) 는 CampaignPhase.durationDays 기준으로 cascade 로 자동 생성됩니다.
광고주에게는 별도 메일을 발송하지 않으며(프런트 팝업이 안내 처리), 영업팀에게 알림 메일 + 캠페인 알리미 슬랙 채널 알림이 자동 발송됩니다.
| 항목 | 값 |
|---|---|
| 메서드 | POST |
| 경로 | /ai/business/collab/draft |
| 인증 | 필요 (ROLE_BUSINESS) |
| Content-Type | multipart/form-data |
요청
POST /ai/business/collab/draft HTTP/1.1
Host: api.glowb.com
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...
Content-Type: multipart/form-datacurl -X POST "https://api.glowb.com/ai/business/collab/draft" \
-H "Authorization: Bearer {access_token}" \
-F "campaign_data=@draft.json;type=application/json" \
-F "detail_images=@product1.jpg" \
-F "detail_images=@product2.jpg" \
-F "guide_files=@guide.pdf"const formData = new FormData();
formData.append('campaign_data', new Blob([JSON.stringify({
category: 'BEAUTY',
modelType: 'STANDARD',
scriptReviewRequired: true,
managers: [
{ managerNo: 30 },
{ name: '홍길동', phone: '010-0000-0000', email: 'manager@example.com' }
],
productUrl: 'https://example.com/product/123',
productName: '핸드크림',
rewardType: 'BOTH',
deliveryType: 'DELIVERY',
productReturnRequired: false,
snsType: 'INSTAGRAM',
snsContentFormat: 'INSTAGRAM_REELS',
nation: 'KR',
creatorTargetCountry: 'KR',
budget: '1000000',
headcount: '3',
finalSubmissionTypes: ['CONTENT_LINK', 'PARTNERSHIP_CODE'],
comment: '4월 중순 라이브 일정이에요.',
commentAnonymous: false,
secondaryUsageOption: '["post_secondary","clean_version"]',
secondaryUsageMonths: 3
})], { type: 'application/json' }));
detailImageFiles.forEach((f) => formData.append('detail_images', f));
guideFiles.forEach((f) => formData.append('guide_files', f));
const response = await fetch('/ai/business/collab/draft', {
method: 'POST',
headers: { 'Authorization': `Bearer ${accessToken}` },
body: formData
});Request Parts
Prop
Type
campaign_data 스키마
Prop
Type
검수 유형 자동 매핑
scriptReviewRequired 와 SNS 플랫폼(Naver vs 그 외) 조합에 따라 Collab.firstReviewTypes / secondReviewTypes 가 자동 결정됩니다. (GuidelineV2Service.setReviewTypes 와 동일 로직)
| 조건 | firstReviewTypes | secondReviewTypes |
|---|---|---|
true + Naver | {SCRIPT_BLOG} | {SCRIPT_BLOG, PHOTO} |
true + 그 외 | {SCRIPT_VIDEO} | {VIDEO, CAPTION, HASHTAG} |
false + Naver | {} | {SCRIPT_BLOG, PHOTO} |
false + 그 외 | {} | {VIDEO, CAPTION, HASHTAG} |
응답
성공 응답 (201 Created)
{
"status": 201,
"code": null,
"message": "캠페인 초안이 생성되었습니다.",
"data": {
"campaignNo": 2309,
"title": "[facebook] 핸드크림 캠페인",
"managers": [
{ "managerNo": 30, "name": "홍길동", "phone": "010-0000-0000", "email": "manager@example.com", "isDefault": true }
]
}
}에러 응답
| 상태 코드 | code | 설명 |
|---|---|---|
400 | CAMPAIGN_CATEGORY_INVALID | 유효하지 않은 카테고리 값(args.category). 카테고리를 비우면 기본값으로 저장됩니다 |
400 | CAMPAIGN_CREATOR_TARGET_COUNTRY_INVALID | 크리에이터 타겟 국가 값이 국가 코드(ISO 3166-1 alpha-2)로 환원되지 않음(args.country) |
400 | BUSINESS_MANAGER_FIELD_TOO_LONG | managers[] 항목의 담당자 정보가 길이 제한 초과. args.field=name·phone·email, args.maxLength=100·50·100. 예전에는 DATABASE_ERROR로 실패했습니다 |
401 | AUTH_TOKEN_REQUIRED | 인증 실패 |
403 | AUTH_FORBIDDEN | ROLE_BUSINESS 권한 부족 |
404 | INVALID_BUSINESS_USER | 기업 정보를 찾을 수 없음 |
500 | FILE_UPLOAD_FAILED | 이미지 업로드 실패 |