GET /ai/submit-link/{token}
링크 컨텍스트 조회 (무인증)
링크 컨텍스트 조회
토큰을 검증하고, 해당 신청의 제출 컨텍스트(캠페인 번호, 검수 라운드 목록, 필수 해시태그, 최종 제출물 현황)를 반환합니다. 링크 진입 시 가장 먼저 호출합니다.
무인증 엔드포인트 — JWT 없이 토큰만으로 접근합니다. (/ai/submit-link/**는 permitAll)
HTTP 요청
GET /ai/submit-link/{token}Path Parameters
| 파라미터 | 타입 | 필수 | 설명 |
|---|---|---|---|
token | string | 예 | 발급받은 제출 링크 토큰 |
응답
성공 응답 (200 OK)
{
"status": 200,
"code": null,
"message": "조회 완료",
"data": {
"applicationId": 100,
"campaignNo": 1588,
"reviewRounds": [
{ "reviewId": 50, "reviewRound": 1, "status": "REVIEWING", "itemTypes": ["SCRIPT_VIDEO"] },
{ "reviewId": 51, "reviewRound": 2, "status": "PENDING", "itemTypes": ["VIDEO", "CAPTION", "HASHTAG"] }
],
"requiredHashtags": ["#BODIANCE", "#トーンアップクリーム", "#時短メイク"],
"finalSubmission": {
"id": null,
"applicationId": 100,
"contentLink": null,
"partnershipCode": null,
"cleanFilePath": null,
"finalFilePath": null,
"isSubmitted": false,
"submittedAt": null,
"requiredTypes": ["CONTENT_LINK", "FINAL_FILE"],
"hasReRequest": false,
"reRequestPending": false,
"reRequestItems": null,
"reRequestTypes": null,
"reRequestedAt": null,
"settlementMailScheduledDate": null,
"uploadDateType": null,
"uploadDate": null,
"candidateDates": null
}
}
}Response Body 스키마
| 필드명 | 타입 | 설명 |
|---|---|---|
applicationId | long | 제출 대상 캠페인 신청 ID |
campaignNo | int | 캠페인 번호. 가이드라인 열람 링크 /{locale}/guideline/{campaignNo} 에 사용(비로그인 열람 가능) |
reviewRounds | array | 신청의 검수 라운드 목록 |
reviewRounds[].reviewId | long | 검수 라운드 ID (완료 콜백에 사용) |
reviewRounds[].reviewRound | int | 검수 차수 (1=1차, 2=2차) |
reviewRounds[].status | string | 검수 상태 |
reviewRounds[].itemTypes | string[] | 해당 라운드에 실제로 존재하는 제출항목 타입 목록(중복 제거). 예: ["SCRIPT_VIDEO"], ["VIDEO","CAPTION","HASHTAG"] |
requiredHashtags | string[] | 캠페인 필수 해시태그. 캠페인 키워드를 #태그 배열로 정규화한 값(콤마·공백 구분 모두 처리, 중복 제거). 없으면 [] |
finalSubmission | object | 최종 제출물 현황. 정식 크리에이터 앱의 GET /influence/contents/{applicationId}/final-submission 응답 data와 같은 구조 |
finalSubmission.requiredTypes | string[] | 캠페인이 요구하는 최종 제출물 타입(CONTENT_LINK/PARTNERSHIP_CODE/CLEAN_FILE/FINAL_FILE). 캠페인 설정이 없으면 4종 전부 |
finalSubmission.contentLink 등 4개 | string | 기존 제출값(contentLink/partnershipCode/cleanFilePath/finalFilePath). 미제출이면 null |
finalSubmission.isSubmitted | boolean | 최종 제출 완료 여부 |
finalSubmission.hasReRequest | boolean | 재요청 기록이 있는지. 재제출을 마친 뒤에도 true로 남는다(이력) — 화면 분기에는 reRequestPending을 쓴다 |
finalSubmission.reRequestPending | boolean | 재요청 대기 중인지 — 재요청 뒤 아직 재제출하지 않았으면 true(재요청 시각이 제출 시각보다 늦음) |
finalSubmission.reRequestItems | array | 재요청 항목(type/reason/displayName). 없으면 null |
finalSubmission.reRequestTypes | string[] | 재요청 사유 코드 목록(CONTENT_LINK_WRONG, FILE_1080P, OTHER 등). 입력 칸 이름(requiredTypes의 값)이 아니다 — 아래 변환표로 칸을 구한다. 없으면 null |
스크립트/영상 단계 구분은 reviewRound 번호가 아니라 itemTypes로 판별하세요.
스크립트 단계에서는 1차 라운드만 내려오고(2차는 1차 통과 후 생성) 영상 전용 캠페인에서는 영상이 1차로 생성되기도 하므로, reviewRound === 1로 스크립트/영상을 추정하면 오판합니다. itemTypes에 스크립트 타입(SCRIPT_VIDEO/SCRIPT_BLOG)이 있으면 스크립트 입력, 없으면(VIDEO/PHOTO/CAPTION/HASHTAG) 콘텐츠 제출 화면으로 분기하세요.
SCRIPT_BLOG는 블로그 1·2차 양쪽에 등장할 수 있어 서버는 단계를 단정하지 않고 "그 라운드에 존재하는 타입 목록"만 그대로 내려줍니다.
최종 제출 화면은 finalSubmission.requiredTypes에 있는 항목만 노출하고, 전부 채워야 제출하도록 막으세요.
서버는 요구 여부·누락을 검증하지 않고 받은 값을 그대로 저장합니다(정식 앱과 동일 — 검증은 화면에서).
재요청 대기 중(reRequestPending)이면 아래 재요청 사유 → 입력 칸 변환표로 열 칸을 구해 그 칸만 열어 둡니다.
최종제출은 POST /ai/submit-link/{token}/complete/final을 호출합니다.
재요청 사유 → 입력 칸 변환
reRequestTypes는 재요청 사유라서 requiredTypes(입력 칸)와 값이 다릅니다. 그대로 비교하면 한 번도 일치하지 않아 항상 전체 칸이 열립니다.
사유별로 아래 칸을 모은 뒤 requiredTypes와 겹치는 칸만 엽니다. 정식 크리에이터 앱의 REREQUEST_TO_FIELD_MAP과 같은 규칙입니다.
| 재요청 사유 코드 | 열 칸 |
|---|---|
CONTENT_LINK_WRONG | CONTENT_LINK |
PARTNERSHIP_CODE_WRONG | PARTNERSHIP_CODE |
CLEAN_FILE_NARRATION, CLEAN_FILE_REMOVE_EDIT | CLEAN_FILE |
FINAL_FILE_UPDATE | FINAL_FILE |
FILE_1080P, MUSIC_COPYRIGHT_FREE | CLEAN_FILE, FINAL_FILE |
BRAND_TAG_PERSON, BRAND_TAG_CAPTION, SPONSORED_LABEL, COLLABORATOR, PRODUCT_LINK_SHARE, REQUIRED_HASHTAG (게시물 수정 사유) | CONTENT_LINK |
OTHER | requiredTypes 전부 |
- 응답에는 위 표의 사유 코드만 옵니다. 옛 형식으로 저장된 재요청(
["CLEAN_FILE"]같은 칸 이름)도 서버가 사유 코드로 바꿔 내려줍니다(CONTENT_LINK→CONTENT_LINK_WRONG,PARTNERSHIP_CODE→PARTNERSHIP_CODE_WRONG,CLEAN_FILE→CLEAN_FILE_REMOVE_EDIT,FINAL_FILE→FINAL_FILE_UPDATE). - 예: 사유
FILE_1080P인데 캠페인이 최종본을 요구하지 않으면(requiredTypes에FINAL_FILE없음)CLEAN_FILE만 엽니다. - 열지 않은 칸은 기존 제출값이 유지되므로 보내지 않아도 됩니다(서버는
null인 필드를 덮어쓰지 않음). - 재제출해도 재요청 기록(
reRequestTypes·reRequestedAt)은 이력으로 남고reRequestPending만false가 됩니다 — 최종제출물 완료 콜백 참고.
가이드라인 확인 링크는 campaignNo로 만드세요. 크리에이터 앱 가이드라인 열람 페이지
/{locale}/guideline/{campaignNo} 는 로그인 없이 열리며(GET /ai/collab/{campaignNo}/full 은 선택 인증),
매직링크 사용자도 그대로 볼 수 있습니다.
영상 제출 해시태그 칸은 requiredHashtags로 미리 채우세요. 필수 해시태그가 있으면 칸이 비어 있어도
HASHTAG 항목을 전송해야 검수 화면에 필수 해시태그가 남습니다.
에러 응답
| 상황 | 상태 코드 | 메시지 |
|---|---|---|
| 토큰 없음 | 400 | 유효하지 않은 링크입니다. |
| 만료/사용됨/비활성 | 400 | 만료되었거나 사용할 수 없는 링크입니다. |