GET /ai/influence/contents/ai-review/result/script/{reviewId}
스크립트 AI 검수 결과 조회 (셀프 요청)
스크립트 AI 검수 결과 조회 (셀프 요청)
크리에이터가 수동 요청한 스크립트 AI 검수의 최신 결과를 조회합니다. 본인 신청 건만 조회할 수 있습니다.
HTTP 요청
GET /ai/influence/contents/ai-review/result/script/{reviewId}
Authorization: Bearer {access_token}Path Parameters
| 파라미터 | 타입 | 필수 | 설명 |
|---|---|---|---|
reviewId | long | 예 | 검수 라운드 ID |
응답
성공 응답 (200 OK)
{
"status": 200,
"code": null,
"message": "검수 결과 조회 완료",
"data": {
"collabNo": 1234,
"applicationId": 5678,
"reviewId": 910,
"contentType": "SCRIPT_VIDEO",
"overallStatus": "PARTIAL",
"checkedAt": "2026-06-20T10:30:00Z",
"contentDetailResult": {
"categoryCode": "BEAUTY",
"basicShots": {
"beginning": [
{
"code": "HOOK",
"expected": {
"scene": "[장면] 자기 전 세면대 앞에서 턱선을 만지며 고민하는 모습으로 시작해 주세요. ※ 앞 3초 안에 제품 또는 사용 장면이 보이도록 해주세요.",
"example_comment": "[예시 멘트] 사진 찍을 때마다 각도만 재던 사람인데, 요즘은 이거 하나로 끝내요."
},
"result": {
"status": "PASS",
"confidence": 0.90,
"evidence": [
{
"type": "script_text",
"sceneIndex": 0,
"description": "피부 고민 토로하며 훅 시작",
"text": "요즘 피부가 너무 건조해서 고민이었는데요"
}
],
"comment": "가이드라인의 훅 요구사항에 맞게 피부 고민을 제시하고 있음"
}
}
]
}
},
"marketingInfoResult": { "requiredPoints": [], "optionalPoints": [] },
"cautionResult": [],
"errors": [],
"meta": {
"modelVersion": "gemini2",
"processingTimeMs": 45000
}
}
}응답 필드 (data)
| 필드 | 타입 | 설명 |
|---|---|---|
collabNo | long | 캠페인 번호 |
applicationId | long | 신청 ID |
reviewId | long | 검수 라운드 ID |
contentType | string | SCRIPT_VIDEO |
overallStatus | string | 종합 결과. PASS | FAIL | PARTIAL | ERROR (아래 산정 규칙) |
checkedAt | datetime | 검수 완료 시각 (ISO 8601, UTC) |
contentDetailResult | object | 필수 장면 검수 결과 |
marketingInfoResult | object | 필수·선택 소구포인트 검수 결과 |
cautionResult | array<object> | 주의사항 위반 검수 (없으면 빈 배열) |
errors | array<string> | 검수를 정상 수행하지 못한 사유. 비어 있지 않으면 overallStatus가 ERROR 이고 개별 항목 결과는 신뢰할 수 없습니다 |
meta | object | 모델·처리시간 |
regulationRiskResults | object | 규정 검수 결과 (아래 규정 검수 결과 참고) |
submissionVersion | integer | 이 결과가 검수한 제출 버전 |
reviewState | string | COMPLETED | IN_PROGRESS |
overallStatus 산정 규칙
| 값 | 조건 |
|---|---|
ERROR | errors[] 가 비어 있지 않음 — 다른 판정보다 우선 |
FAIL | 집계 대상 중 FAIL 이 하나 이상 |
PARTIAL | FAIL 은 없고 UNCERTAIN 이 하나 이상 |
PASS | 집계 대상이 전부 PASS |
집계 대상은 contentDetailResult.basicShots(beginning·middle·ending 전부) + contentDetailResult.additionalOptions + marketingInfoResult.requiredPoints 입니다.
optionalPoints(선택 소구포인트)는 overallStatus 에 영향을 주지 않습니다. 선택 항목이라 집계에서 제외됩니다 — 개별 항목이 FAIL 이어도 종합은 PASS 가 될 수 있습니다.
contentDetailResult
| 필드 | 타입 | 설명 |
|---|---|---|
categoryCode | string | 카테고리 코드 (예: BEAUTY). 판별 실패 시 빈 문자열 |
basicShots.beginning | array<object> | 도입부 필수 장면 결과 |
basicShots.middle | array<object> | 본문 필수 장면 결과 |
basicShots.ending | array<object> | 마무리 필수 장면 결과 |
additionalOptions | array<object> | 나레이션·BGM 등 추가 옵션 판정. code + result 구조이며 overallStatus 집계에 포함됩니다 |
각 장면 항목(basicShots.{section}[])의 구조:
| 필드 | 타입 | 설명 |
|---|---|---|
code | string | 장면 코드 (HOOK, TEXTURE_SHOT, USAGE_SHOT, TIP_SHOT, PURCHASE_GUIDE_END 등) |
expected.scene | string | 가이드라인의 장면 지시문 원문. [장면] … / ※ … 형식이 그대로 들어갑니다 |
expected.example_comment | string | 가이드라인의 예시 멘트. 없으면 빈 문자열 |
result.status | string | PASS | FAIL | UNCERTAIN |
result.confidence | number | 판정 신뢰도 0.0 ~ 1.0 |
result.evidence | array<object> | 판단 근거 (아래) |
result.comment | string | 판단 코멘트 |
expected 는 빈 객체가 아닙니다. 가이드라인 원문이 그대로 실려 오므로 화면에 "요구사항"으로 그대로 노출할 수 있습니다. 다만 [장면]·[예시 멘트]·※ 같은 마커가 포함된 원문이라 표시 전에 가공이 필요할 수 있습니다.
evidence[] — 스크립트
| 필드 | 타입 | 설명 |
|---|---|---|
type | string | script_text (스크립트 본문 인용) |
sceneIndex | integer | 근거가 위치한 장면 인덱스 (0부터) |
description | string | 근거 설명 |
text | string | 실제 스크립트 인용문 |
영상 검수(/result/video/{itemId})의 evidence 는 스키마가 다릅니다. 영상은 sceneIndex 대신 timeRange(초 단위)를 쓰고 type 값도 frame·speech·subtitle·ocr 입니다. 두 응답을 같은 렌더러로 처리하려면 분기가 필요합니다.
marketingInfoResult
| 필드 | 타입 | 설명 |
|---|---|---|
requiredPoints[] | array<object> | 필수 소구포인트별 결과. overallStatus 집계 포함 |
optionalPoints[] | array<object> | 선택 소구포인트별 결과. 집계 제외 |
{points}[].text | string | 소구포인트 원문 |
{points}[].result.status | string | PASS | FAIL | UNCERTAIN |
{points}[].result.matchType | string | EXACT | PARAPHRASE | NOT_FOUND |
{points}[].result.matchedText | string | 매칭된 문구. 없으면 빈 문자열 또는 null |
{points}[].result.evidence | array<object> | 판단 근거 (위 evidence[] 와 동일 구조) |
{points}[].result.comment | string | 판단 코멘트 |
cautionResult[]
| 필드 | 타입 | 설명 |
|---|---|---|
text | string | 주의사항 항목 원문 |
result.status | string | PASS(위반 없음) | FAIL(위반) | UNCERTAIN |
result.evidence | array<object> | 위반 근거 (위반 시) |
result.comment | string | 판단 코멘트 |
주의사항은 계약 조건 안내문이라 대부분 PASS 로 내려옵니다. overallStatus 집계에는 포함되지 않습니다.
meta
| 필드 | 타입 | 설명 |
|---|---|---|
modelVersion | string | 사용 모델 (gemini2 = Gemini 2.5 Flash) |
processingTimeMs | number | 처리 소요 시간 (ms) |
규정 검수 결과
캠페인에 규정 검수가 켜져 있으면 위 응답에 규정 검수 블록이 함께 내려갑니다.
크리에이터 조회는 한국 캠페인에서만 규정 결과를 반환합니다. 캠페인 국가(TB_COLLAB.nation)를 정규화한 값이 KR일 때만 regulationRiskResult·regulationRiskResults가 내려가고, 그 외 국가(JP·US 등)이거나 국가가 비어 있으면 두 키가 응답에서 빠집니다(필드 자체가 없음). 대한민국·한국 같은 한글 표기도 KR로 인정됩니다.
어드민·기업용 경로는 국가와 무관하게 항상 규정 결과를 내려보냅니다. 단 그 경로를 크리에이터 롤로 호출하면 롤 기준으로 제거됩니다.
| 필드 | 타입 | 설명 |
|---|---|---|
regulationRiskResults | object | 정책별 결과 블록. 실행한 정책의 키만 존재합니다 |
regulationRiskResult | object | (deprecated) 약기법 결과만 담기는 단일 키. Meta 결과는 여기 실리지 않습니다 |
submissionVersion | integer | 이 결과가 검수한 제출 버전 |
reviewState | string | COMPLETED | IN_PROGRESS |
어떤 정책이 실행되나
| 정책 | 키 | 활성 조건 |
|---|---|---|
| 약기법(일본 광고규정) | yakkiho | 관리자 토글 (TB_COLLAB.regulation_review_enabled) |
| Meta 광고정책 | metaAds | 인스타그램 캠페인이면 자동 — 토글 없음 |
| TikTok 광고정책 | tiktokAds | 틱톡 캠페인이면 자동 — 토글 없음 |
축들은 서로 독립입니다. 약기법이 꺼져 있는 한국 인스타그램 캠페인이면 metaAds만 단독으로 내려오고, 인스타·틱톡 멀티 SNS 캠페인이면 metaAds와 tiktokAds가 함께 내려옵니다. 정책이 하나도 켜져 있지 않으면 regulationRiskResults 필드 자체가 없습니다.
tiktokAds 블록
TikTok 광고정책 결과입니다. Meta 와 구조가 거의 같지만 다음 필드가 없습니다 — rule_id, priority, action, verification_required, verification_context_key. 없다고 결과를 버리거나 파싱에 실패하면 안 됩니다.
대신 TikTok 에만 있는 것:
| 필드 | 설명 |
|---|---|
review_scope.industry | 요청으로 받은 규제 업종. 현재 백엔드는 이 값을 보내지 않으므로 항상 null 입니다 |
_meta.evidence_bundles | 판정에 인용된 코퍼스 검색 묶음(bundle_id, bundle_title). 공식 정책명이 아니므로 화면에 표시하지 않습니다 |
값 목록도 Meta 와 다릅니다.
violations[].type:금지콘텐츠,제한업종,과장기만,차별안전,청소년보호,연령제한,국가제한,타게팅제한,허가서류,협찬고지,랜딩페이지,계정자격,지식재산권,기타requirements[].type:age_restricted,market_restricted,certification_required,disclosure_required,targeting_restricted,advertiser_eligibility_required,landing_page_required,other
status 산정 규칙과 언어 계약(KR 은 fix 한국어 · fix_ko 빈 문자열)은 Meta 와 동일합니다. 화면 표시는 policy_title 을 정책명으로 쓰고, 없을 때만 policy_document → basis 순으로 대체합니다.
metaAds 응답 구조
{
"regulationRiskResults": {
"metaAds": {
"status": "high",
"summary": "개인속성 관련 위험이 확인되었습니다.",
"violations": [
{
"kind": "expression",
"scene": 1,
"part": "narration",
"location": "장면 1 나레이션",
"text": "You are obese",
"text_ko": "당신은 비만입니다",
"type": "개인속성",
"risk": "high",
"rule_id": "META_PERSONAL_ATTRIBUTES_ASSERTION",
"priority": 10,
"action": "remove_or_rewrite",
"basis": "Privacy Violations and Personal Attributes",
"policy_title": "Privacy Violations and Personal Attributes",
"policy_document": "Privacy Violations and Personal Attributes",
"basis_source_id": "licies-ad-standards-objectionable-content-privacy-violations-personal-attributes-e496adf8ca07",
"basis_section": "Privacy Violations and Personal Attributes",
"basis_excerpt_en": "ads must not contain content that asserts or implies personal attributes.",
"reason": "이용자의 신체 상태를 직접 단정합니다.",
"fix": "Support your wellness goals",
"fix_ko": "웰니스 목표를 지원하세요",
"verification_required": false,
"verification_context_key": null,
"source_url": "https://transparency.meta.com/policies/ad-standards/objectionable-content/privacy-violations-personal-attributes"
}
],
"requirements": [
{
"type": "age_restricted",
"status": "unknown",
"rule_id": "META_HEALTH_WEIGHT_18_PLUS",
"priority": 30,
"action": "restrict_audience_age",
"basis": "Health and Wellness",
"basis_section": "Health and Wellness",
"basis_excerpt_en": "must be targeted to people at least 18 years or older",
"reason": "해당 건강·웰니스 광고에 최소 연령 조건이 적용됩니다.",
"required_action": "타게팅 최소 연령을 정책 요건에 맞게 조정하세요.",
"source_url": "https://transparency.meta.com/policies/ad-standards/restricted-goods-services/health-wellness/"
}
],
"review_scope": {
"content_type": "SCRIPT",
"market_country": "KR",
"target_min_age": 18
},
"corpus_version": "2119a41249213ad9",
"_meta": {
"judge": "gemini",
"control_rule_count": 39,
"source_count": 72,
"chunk_count": 404
}
}
},
"submissionVersion": 2,
"reviewState": "COMPLETED"
}최상위 필드
| 필드 | 타입 | 설명 |
|---|---|---|
status | string | high(높은 위험) | low(주의 필요) | pass(위반 없음). 재검수 중이면 IN_PROGRESS |
summary | string | 위반 유형 최대 3개를 묶은 한 문장 요약 |
violations | array | 광고 소재 자체의 정책 위반 |
requirements | array | 문구 수정으로 해결되지 않는 집행·설정·자격 요건 (약기법에는 없는 Meta 전용) |
review_scope | object | 이번 판정에 사용된 문맥 (content_type, market_country, target_min_age) |
corpus_version | string | 판정에 사용된 Meta 원문 코퍼스 버전 |
_meta | object | 판정 엔진 메타데이터 (모델, 규칙·원문·청크 수) |
violations[]
| 필드 | 타입 | 설명 |
|---|---|---|
kind | string | expression(원문에 실재하는 연속 문자열 → 하이라이트용) | item(누락·전체 방향성 문제) |
scene | integer | 위반이 발생한 장면 번호. 숫자로 특정할 수 없으면 null |
part | string | 장면 내 위치 — subtitle | narration | videoScene |
location | string | 화면 표시용 설명 (예: 장면 1 나레이션). 실제 위치 기준은 scene + part |
text | string | 위반 원문 |
text_ko | string | 한국어 해석. text가 한국어이거나 kind=item이면 빈 문자열 |
type | string | 위반 유형 (아래 목록) |
risk | string | high | low |
rule_id | string | 연결된 Meta 구조화 규칙 ID |
priority | integer | 조치 순서 — 10 소재 삭제·수정, 20 승인·설정·고지·자격, 30 연령 제한 |
action | string | 표준 조치 코드 (예: remove_or_rewrite) |
basis / policy_title / policy_document | string | Meta 공식 원문 문서명. 화면 표시는 policy_title |
basis_section | string | 인용 근거가 위치한 원문 소제목. 주 정책명으로 쓰지 않습니다 |
basis_excerpt_en | string | 공식 원문 영문 인용문 |
basis_source_id | string | 내부 추적용 원문 ID |
reason | string | 위반 사유. 국가와 무관하게 항상 한국어 |
fix | string | 수정 제안. 언어는 market_country 기준 (아래 주의 참고) |
fix_ko | string | fix의 한국어 해석. KR 캠페인에서는 빈 문자열 |
verification_required | boolean | 외부 사실 확인 전에는 위반을 확정할 수 없는 항목인지 |
verification_context_key | string | 확인에 필요한 캠페인 컨텍스트 필드명 |
source_url | string | Meta 공식 정책 원문 URL |
type 값: 금지콘텐츠, 개인속성, 건강웰니스, 과장기만, 연령제한, 타게팅제한, 승인필요, 협찬고지, 자격요건, 형식제한, 지식재산권, 기타
requirements[]
광고 문구를 고쳐도 해결되지 않는 집행·설정·자격 요건입니다. 약기법 응답에는 없는 Meta 전용 블록입니다.
| 필드 | 타입 | 설명 |
|---|---|---|
type | string | age_restricted, market_restricted, authorization_required, special_ad_category_required, disclosure_required, eligibility_required, other |
status | string | met(충족) | unmet(명시적 미충족) | unknown(설정값이 없어 확인 불가) |
rule_id / priority / action | — | violations[]와 동일한 제어 필드 |
basis / basis_section / basis_excerpt_en / source_url | string | 근거 원문 |
reason | string | 요건이 적용되는 이유 (한국어) |
required_action | string | 필요한 조치 (한국어) |
status 산정 규칙
| 값 | 조건 |
|---|---|
high | risk=high 위반이 있거나 status=unmet 요건이 있음 |
low | low 위반만 있거나 status=unknown 요건만 있음 |
pass | 위반이 없고 적용 요건도 모두 충족됐거나 없음 |
한국(KR) 캠페인은 fix_ko가 빈 문자열입니다. 수정 제안 언어는 market_country 기준으로 고정됩니다 — KR은 fix가 한국어이고 fix_ko는 비어 있으며, JP는 fix가 일본어이고 fix_ko에 한국어 해석이 들어갑니다(그 외 국가·미지정은 fix가 영어). 프론트가 fix_ko만 렌더하면 한국 캠페인에서 수정안이 빈칸으로 보입니다. fix_ko || fix 폴백이 필요합니다.
reason, required_action은 국가와 무관하게 항상 한국어입니다.
requirements[].status가 unknown인 것은 위반 확정이 아니라 "설정 확인 필요" 입니다. 타게팅 연령·특별 광고 카테고리 등은 캠페인에서 전송하지 않는 값이라 unknown으로 남습니다. 이 때문에 위반이 하나도 없어도 status가 pass가 아닌 low로 내려갈 수 있습니다. 버그가 아닙니다.
yakkiho 블록
약기법 결과는 같은 자리에 regulationRiskResults.yakkiho로 들어갑니다. 구조는 Meta와 대부분 같지만 requirements, rule_id, priority, action, verification_*, review_scope, corpus_version이 없고, basis가 영문 정책명이 아니라 한국어 법령·조항입니다. 자세한 내용은 규정 검수 가이드를 참고하세요.
재검수 중에는 IN_PROGRESS
재제출로 재검수가 도는 동안에는 직전 완료 결과를 그대로 주지 않습니다. 저장된 결과의 submissionVersion이 현재 제출 버전과 다르면 재검수 중으로 판단합니다.
{
"submissionVersion": 1,
"reviewState": "IN_PROGRESS",
"regulationRiskResults": {
"yakkiho": { "status": "IN_PROGRESS" },
"metaAds": { "status": "IN_PROGRESS" }
}
}재검수 중이면 각 정책의 status도 함께 IN_PROGRESS 로 내려가고, 이전 버전의 위반 내용은 응답에서 제외됩니다. 프론트가 status만 보고도 로딩 처리를 할 수 있어야 하기 때문입니다.
submissionVersion 필드가 아예 없는 과거 결과는 판단 근거가 없으므로 COMPLETED로 서빙합니다.
그 밖의 응답
검수 결과 없음 (200 OK)
검수가 아직 진행 중이거나 요청 이력이 없는 경우 data는 null입니다.
{
"status": 200,
"code": null,
"message": "검수 결과가 없습니다.",
"data": null
}에러 응답
| 상태 코드 | 설명 |
|---|---|
403 | 본인 신청이 아님 (소유권 검증 실패) |
404 | 검수 라운드를 찾을 수 없음 |
이 엔드포인트는 본인 신청의 셀프 요청 결과만 반환합니다. 소유권 검증이 적용되며, 타인의 결과는 조회할 수 없습니다.