API 문서
ISO 27001SOC 2 CertifiedGDPR Compliant

AI 이미지 감지 API

애플리케이션에 TruthScan의 AI 이미지 감지 API를 통합하기 위한 전체 문서입니다.

코드 없이 시도하려면 FastAPI 엔드포인트를 방문하세요: https://detect-image.truthscan.com/docs

인증

TruthScan은 API 접근을 위해 API key를 사용합니다. API key는 개발자 포털 페이지 상단에서 확인할 수 있습니다.

TruthScan은 API key를 다음과 같은 JSON 본문에 포함해 서버로 보내기를 기대합니다(엔드포인트가 헤더 전용 인증만 문서화한 경우, 예: check-user-credits는 예외):

{
  "key": "YOUR API KEY GOES HERE"
}

YOUR API KEY GOES HERE를 개인 API key로 반드시 바꾸세요.

Rate Limits

API는 각 API key에 대해 분당 요청 예산을 적용합니다. 쓰기(write) 엔드포인트는 읽기(read) 엔드포인트보다 비용이 큽니다. 기본 한도는 분당 60회이며, 더 높은 한도가 필요하면 문의해 주세요.

엔드포인트 가중치

각 호출은 분당 예산에서 가중치만큼 차감됩니다:

엔드포인트유형가중치
POST /detect쓰기1
POST /bulk-upload쓰기1
GET /get-presigned-url읽기0.2
GET /check-user-credits읽기0.2
POST /heatmap/{id}읽기0.2
POST /preview/{id}읽기0.2
POST /query읽기제한 없음
GET /health읽기제한 없음

예: 분당 60 예산이면 쓰기 60회, 읽기 약 300회, 또는 가중치 합계가 분당 ≤ 60이 되는 어떤 조합이든 보낼 수 있습니다.

제한 응답 (HTTP 429)

분당 예산을 초과하면 API는 다음을 반환합니다:

HTTP/1.1 429 Too Many Requests
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 3
X-RateLimit-Retry-After: 3
Content-Type: application/json

{
  "error": "Too many requests"
}

Rate limit 응답 헤더

  • X-RateLimit-Limit — 분당 용량.
  • X-RateLimit-Remaining — 이 요청 이후 현재 분의 남은 호출 수.
  • X-RateLimit-Reset — (429일 때만) 다음 쓰기 요청을 보낼 수 있을 때까지의 초.
  • X-RateLimit-Retry-After — (429일 때만) X-RateLimit-Reset과 동일 값을 Retry-After 형식으로 제공.

권장 클라이언트 동작

  • 성공 응답의 X-RateLimit-Remaining을 보며 요청 속도를 조절하세요.
  • 429를 받으면 최소 X-RateLimit-Retry-After 초 동안 대기 후 재시도하세요. 지수 백오프 + jitter 사용을 권장합니다.
  • 배치 작업에는 여러 /detect 병렬 호출 대신 POST /bulk-upload(한 번에 최대 50장 처리)를 사용하세요.

AI 이미지 감지기

Detect (3단계 프로세스)

AI 이미지 감지 워크플로는 다음 단계로 구성됩니다:

  • Pre-signed 업로드 URL 받기
  • 이미지 업로드
  • 이미지 감지 요청 제출

1. Pre-signed 업로드 URL 받기

먼저 API에 pre-signed URL을 요청합니다. 이 URL로 이미지 파일을 스토리지 서버에 안전하게 업로드할 수 있습니다.

지원 파일 형식

JPG, JPEG, PNG, WebP, JFIF, HEIC, HEIF, AVIF, BMP, TIFF, TIF, GIF, SVG, PDF

파일명

pre-signed URL을 요청할 때 이미지 파일명에서 공백을 제거하세요.

PDF 파일의 경우 첫 번째 이미지만 감지됩니다(단일 파일 플로우).

일괄 업로드로 ZIP을 제출할 경우 이 엔드포인트에서 .zip 파일명을 사용하세요.

Query parameters

  • file_name (필수) — 원본 파일명; 서버가 정규화할 수 있습니다(공백 및 안전하지 않은 문자 조정). 일괄 업로드에는 .zip 확장자를 사용하세요.
  • expiration (선택) — pre-signed URL 유효 시간(초, 기본값: 3600).
GET https://detect-image.truthscan.com/get-presigned-url?file_name=example.jpg

요청 예시

curl -X GET 'https://detect-image.truthscan.com/get-presigned-url?file_name=example.jpg' \
--header 'apikey: YOUR API KEY GOES HERE'

응답 예시

{
  "status": "success",
  "presigned_url": "https://nyc3.digitaloceanspaces.com/ai-image-detector-dev/uploads/581d47c7-3ef4-42af-88d9-6dab6bf69389_20250611-121955_example.jpg...",
  "file_path": "uploads/example.jpg",
  "document_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
}

document_id는 이 업로드 요청에 대해 새로 생성된 UUID입니다(상관/로깅용). /detect 또는 /bulk-upload에 사용하는 id는 해당 엔드포인트를 제출할 때 부여되며, /detect에 선택적 id를 전달하지 않는 한 presign 단계의 id와 다를 수 있습니다.

2. 이미지 업로드

제공된 presigned_url로 PUT 요청하여 이미지를 업로드합니다. 이미지 형식에 맞게 Content-Type을 설정하세요.

파일명

업로드 시 이미지 파일명에서 공백을 제거하세요.

파일 확장자와 정확히 일치하도록 Content-Type 설정

  • image/jpeg: jpg, jpeg, jfif
  • image/png: png
  • image/webp: webp
  • image/heic: heic
  • image/heif: heif
  • image/avif: avif
  • image/bmp: bmp
  • image/tiff: tiff, tif
  • image/gif: gif
  • image/svg+xml: svg
  • application/pdf: pdf

흔한 실수

  • image/jpg는 잘못된 값입니다. image/jpeg를 사용하세요.
  • 파일과 헤더가 맞지 않게 하지 마세요(예: .png 파일에 image/jpeg).
  • 헤더를 바꾸면 확장자도 맞추고, 반대도 마찬가지입니다.
  • 요청/업로드 시 파일명에 공백을 넣지 마세요.

요청 예시

curl -X PUT 'https://nyc3.digitaloceanspaces.com/ai-image-detector-dev/uploads/581d47c7-3ef4-42af-88d9-6dab6bf69389_20250611-121955_example.jpg...' \
  --header 'Content-Type: image/jpeg' \
  --header 'x-amz-acl: private' \
  --data-binary '@example.jpg'

추가 업로드 예시(PNG, PDF, SVG)

curl -X PUT '<PRESIGNED_URL_FOR_example.png>' \
  --header 'Content-Type: image/png' \
  --header 'x-amz-acl: private' \
  --data-binary '@example.png'
curl -X PUT '<PRESIGNED_URL_FOR_example.pdf>' \
  --header 'Content-Type: application/pdf' \
  --header 'x-amz-acl: private' \
  --data-binary '@example.pdf'
curl -X PUT '<PRESIGNED_URL_FOR_example.svg>' \
  --header 'Content-Type: image/svg+xml' \
  --header 'x-amz-acl: private' \
  --data-binary '@example.svg'

파일 크기 제한

  • 최소 파일 크기: 1KB
  • 최대 파일 크기: 10MB

업로드 과정에서 파일 형식이 일관되게 유지되는지 확인하세요. 성공 시 HTTP 200을 반환합니다.

3. AI 감지를 위해 이미지 제출

업로드 후 이전 단계의 file_path를 참조하여 AI 감지를 요청합니다. PDF 업로드 시 첫 번째 이미지만 분석·감지됩니다.

POST https://detect-image.truthscan.com/detect

요청 예시

curl -X 'POST' \
  'https://detect-image.truthscan.com/detect' \
  -H 'accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{
  "key": "YOUR-API-KEY-GOES-HERE",
  "url": "https://ai-image-detector-prod.nyc3.digitaloceanspaces.com/<FILE_PATH>",
  "generate_preview": true
}'

FILE_PATH는 pre-signed URL 단계에서 반환된 경로를 의미합니다(예: uploads/...). 예시처럼 스토리지 호스트로 전체 URL을 구성하세요.

선택 파라미터

  • id: 선택 UUID 문자열. 생략 시 서버가 새 document id를 생성합니다. 제공 시 이미 존재하면 안 되며, 그렇지 않으면 API가 오류를 반환합니다.
  • generate_preview: true면 이미지 미리보기 URL 생성(기본: true). false면 미리보기 생략.
  • document_type: 문서 유형(기본: Image).
  • email: 처리용 이메일 주소.
  • generate_analysis_details: false면 상세 분석 생성 생략(기본: true).
  • generate_heatmap_overlayed: 히트맵 생성 시 히트맵 이미지 출력 방식(기본: true). true면 원본에 블렌딩한 표준 오버레이, false면 투명 RGBA 히트맵(JET 색상 맵 + 알파)으로 UI에서 합성 가능.
  • generate_heatmap_normalized: false면 활성화 맵에 사용되는 정규화 단계를 생략(기본: true). generate_heatmap_overlayed와 함께 히트맵 외형을 조절합니다.
  • model: 모델 또는 라우팅 힌트(기본: generic). generic, instance_id/model(예: my-instance-id/generic) 등. 잘못된 instance_id는 400으로 거부됩니다.
  • user_agent: 문서에 저장되는 선택 문자열(분석/지원용).

응답 예시

{
    "id": "77565038-9e3d-4e6a-8c80-e20785be5ee9",
    "status": "pending"
}

응답에는 감지 상태 추적용 고유 이미지 ID가 포함됩니다.

감지 상태 및 결과 조회

상태 확인과 결과를 가져오려면 이미지 ID로 /query 엔드포인트를 사용하세요.

인증: 요청 본문에는 id만 포함되며 이 호출에는 API key를 보내지 않습니다. UUID를 아는 누구나 결과를 폴링할 수 있으므로, 점수 공개를 제한하려면 document ID를 민감 정보로 취급하세요.

POST https://detect-image.truthscan.com/query

요청 예시

curl -X 'POST' \
  'https://detect-image.truthscan.com/query' \
  -H 'accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{
  "id": "IMAGE-ID-GOES-HERE"
}'

응답 예시

{
    "id": "00fee5ff-a55b-42fb-b7c7-d14f05ae0769",
    "status": "done",
    "result": 90.2371538185235,
    "result_details": {
        "is_valid": true,
        "detection_step": 3,
        "final_result": "AI Generated",
        "metadata": [
            "No Information Detected for Real/AI",
            "Could not find anything from ExifTool and Pillow metadata"
        ],
        "metadata_basic_source": "null",
        "ocr": [
            "OCR did not detect AI",
            0.0
        ],
        "ml_model": [
            "AI Generated",
            90.2371538185235
        ],
        "confidence": 90.2371538185235,
        "heatmap_status": "ready",
        "heatmap_url": "https://ai-image-detector-prod.nyc3.digitaloceanspaces.com/uploads/....",
        "analysis_results_status": "pending",
        "analysis_results": null,
        "warnings": [
            { "type": "blur_dark", "label": "Blurred" },
            { "type": "watermark", "label": "Gemini", "confidence": 0.95 },
            { "type": "screen_recapture", "label": "screen", "metrics": { "is_screen": false }, "confidence": 99.99 }
        ]
    },
    "preview_url": "https://ai-image-detector-prod.nyc3.digitaloceanspaces.com/previews/..."
}

응답 예시(/query, 조직에 secure URL이 켜진 경우)

{
    "id": "00fee5ff-a55b-42fb-b7c7-d14f05ae0769",
    "status": "done",
    "result": 90.2371538185235,
    "result_details": {
        "is_valid": true,
        "detection_step": 3,
        "final_result": "AI Generated",
        "confidence": 90.2371538185235,
        "heatmap_status": "ready",
        "heatmap_url": "https://ai-image-detect.undetectable.ai/heatmap/00fee5ff-a55b-42fb-b7c7-d14f05ae0769",
        "analysis_results_status": "ready",
        "analysis_results": null
    },
    "preview_url": "https://ai-image-detect.undetectable.ai/preview/00fee5ff-a55b-42fb-b7c7-d14f05ae0769"
}

분석 결과가 준비된 경우의 응답 예시

{
    "id": "00fee5ff-a55b-42fb-b7c7-d14f05ae0769",
    "status": "done",
    "result": 90.2371538185235,
    "result_details": {
        "heatmap_status": "ready",
        "heatmap_url": "https://ai-image-detector-prod.nyc3.digitaloceanspaces.com/uploads/....",
        "analysis_results_status": "ready",
        "analysis_results": {
            "imageTags": ["person", "portrait", "outdoor", "vineyard", "smiling"],
            "agreement": "strong",
            "confidence": 92,
            "keyIndicators": [
                "Unnaturally smooth skin texture",
                "Consistent lighting anomalies"
            ],
            "detailedReasoning": "The image shows clear signs of AI generation with unnaturally smooth textures and consistent lighting patterns not typical of real photography.",
            "visualPatterns": ["Uniform noise pattern typical of diffusion models"],
            "recommendations": [
                "Cross-reference with original source if available",
                "Check for metadata inconsistencies",
                "Compare with known AI generation patterns"
            ]
        }
    },
    "preview_url": "https://ai-image-detector-prod.nyc3.digitaloceanspaces.com/previews/..."
}

결과 필드

  • is_valid: 이미지 파일 유효 여부(true/false).
  • detection_step: 감지가 완료된 단계: 1 = 메타데이터만, 2 = 메타데이터+ocr, 3 = 메타데이터+ocr+ml_model.
  • final_result: Overall determination (예: "AI Generated", "Real", "Digitally Edited", "AI Edited").
  • confidence: 감지 신뢰도 점수.
  • metadata: ExifTool과 Pillow로 추출한 이미지 메타데이터.
  • metadata_basic_source: 특정 모바일 카메라, AI 도구 생성, 사진 편집 소프트웨어 수정 등 출처 힌트(가능한 경우).
  • ocr: 역사적 필드명 ocr 아래 워터마크 감지 결과. 두 요소 배열 [label, score]: label은 감지된 워터마크 클래스(예: "Gemini") 또는 "OCR did not detect AI"; score는 0–100(불확실 시 0). label이 있으면 warnings에 요약됨.
  • ml_model: 머신러닝 모델 결과.
  • warnings: 선택 경고 객체 배열(blur_dark, watermark, screen_recapture 등). 비어 있거나 생략될 수 있음.
  • preview_url: generate_preview가 true일 때 미리보기 URL. 직접 스토리지이거나 secure URL 시 https://<api-host>/preview/<document_id> 형태일 수 있음.
  • heatmap_status: pending, ready, failed. 히트맵 생성은 비동기입니다.
  • heatmap_url: heatmap_status가 ready일 때 히트맵. generate_heatmap_overlayed에 따라 외형이 달라짐. 직접 스토리지 또는 https://<api-host>/heatmap/<document_id>(secure 시 POST /heatmap/{id}와 key 사용).
  • analysis_results_status: pending, ready, skipped, failed, analyzing. generate_analysis_details가 false면 생략 또는 null.
  • analysis_results: 활성화 시 상세 서술 분석; 아래 Analysis Result Explanation 참고.

Analysis Result Explanation

analysis_results가 준비되면 일반적으로 agreement(strong | moderate | weak | disagreement), imageTags(최대 5개 짧은 태그), confidence(0–100), keyIndicators, detailedReasoning, visualPatterns, recommendations를 포함합니다.

참고

  • 히트맵 생성은 비동기입니다. heatmap_status와 heatmap_url을 위해 /query를 폴링하세요.
  • generate_analysis_details=false가 아니면 상세 분석도 비동기입니다. analysis_results_status와 analysis_results를 폴링하세요.
  • Secure URL: 활성화 시 heatmap_url과 preview_url이 API 호스트를 사용할 수 있으며, key로 POST /heatmap/{id}, POST /preview/{id}로 가져오세요(Secure heatmap and preview assets 참고).
  • 메인 점수가 준비된 뒤에도 완료 시점까지 /query를 다시 호출해 히트맵과 analysis_results를 받으세요.

히트맵 및 오버레이 동작

heatmap_url의 파일은 /detect(또는 /bulk-upload)의 generate_heatmap_overlayed, generate_heatmap_normalized를 반영합니다: 기본 오버레이(true)는 일반 이미지에 히트맵을 덮은 형태이고, false는 합성용 투명 PNG가 일반적입니다.

예: result ~90.24, final_result AI Generated, detection_step 3이면 메타데이터, OCR, ML 모델까지 전체 파이프라인이 완료된 것입니다.

Analysis Results (비동기 심층 분석)

/detect에서 generate_analysis_details가 true이면 상세 분석은 메인 점수 이후에 완료될 수 있습니다. analysis_results_status가 ready(또는 skipped/failed)가 될 때까지 /query를 폴링하세요.

1. 초기 결과가 분석보다 먼저 준비될 수 있음

핵심 감지(result, final_result, confidence)는 analysis_results_status가 아직 pending인 동안에도 완료될 수 있습니다.

{
    "id": "00fee5ff-a55b-42fb-b7c7-d14f05ae0769",
    "status": "done",
    "result": 90.2371538185235,
    "result_details": {
        "is_valid": true,
        "detection_step": 3,
        "final_result": "AI Generated",
        "confidence": 90.2371538185235,
        "analysis_results_status": "pending",
        "analysis_results": null
    }
}

권장 대응

핵심 필드는 즉시 사용하고, analysis_results가 필요하면 계속 폴링하세요.

2. 폴링 유지

같은 id로 /query를 호출하여 analysis_results_status가 pending에서 바뀔 때까지 기다리세요.

curl -X 'POST' \
  'https://detect-image.truthscan.com/query' \
  -H 'accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{
  "id": "00fee5ff-a55b-42fb-b7c7-d14f05ae0769"
}'

3. 분석 완료

analysis_results_status가 ready이면 analysis_results에 agreement, imageTags, confidence, keyIndicators, detailedReasoning, visualPatterns, recommendations가 포함됩니다.

{
    "id": "00fee5ff-a55b-42fb-b7c7-d14f05ae0769",
    "status": "done",
    "result": 90.2371538185235,
    "result_details": {
        "is_valid": true,
        "detection_step": 3,
        "final_result": "AI Generated",
        "confidence": 90.2371538185235,
        "heatmap_status": "ready",
        "heatmap_url": "https://ai-image-detector-prod.nyc3.digitaloceanspaces.com/uploads/....",
        "analysis_results_status": "done",
        "analysis_results": {
            "imageTags": [
                "person",
                "portrait",
                "outdoor",
                "vineyard",
                "smiling"
            ],
            "agreement": "strong",
            "confidence": 92,
            "keyIndicators": [
                "Unnaturally smooth skin texture",
                "Consistent lighting anomalies"
            ],
            "detailedReasoning": "The image shows clear signs of AI generation with unnaturally smooth textures and consistent lighting patterns not typical of real photography.",
            "visualPatterns": [
                "Uniform noise pattern typical of diffusion models"
            ],
            "recommendations": [
                "Cross-reference with original source if available",
                "Check for metadata inconsistencies",
                "Compare with known AI generation patterns"
            ]
        }
    },
    "preview_url": "https://ai-image-detector-prod.nyc3.digitaloceanspaces.com/previews/..."
}

분석을 사용할 수 없을 때

analysis_results_status가 skipped, failed이거나 없거나 generate_analysis_details가 false이면 핵심 감지 결과를 최종으로 취급하세요.

{
    "status": "done",
    "result": 12.5,
    "result_details": {
        "analysis_results_status": "skipped",
        "analysis_results": null
    }
}

Analysis Results Fields

  • analysis_results_status: pending | ready | skipped | failed | analyzing
  • analysis_results.agreement: strong | moderate | weak | disagreement
  • analysis_results.imageTags: 짧은 설명 태그
  • analysis_results.confidence: 0–100
  • analysis_results.keyIndicators: 구체적 단서
  • analysis_results.detailedReasoning: 짧은 설명
  • analysis_results.visualPatterns: 넓은 패턴
  • analysis_results.recommendations: 다음 단계

Bulk Upload (ZIP)

ZIP으로 여러 이미지를 한 번에 제출합니다. 단일 이미지와 동일한 흐름: presign(ZIP 이름) → PUT ZIP → POST /bulk-upload → /query 폴링.

1. Pre-signed 업로드 URL 받기 (ZIP)

get-presigned-url에 .zip 파일명(예: images.zip)으로 요청합니다.

GET https://detect-image.truthscan.com/get-presigned-url?file_name=images.zip

요청 예시

curl -X GET 'https://detect-image.truthscan.com/get-presigned-url?file_name=images.zip' \
--header 'apikey: YOUR API KEY GOES HERE'

2. ZIP 업로드

presigned URL로 PUT하며 Content-Type: application/zip.

curl -X PUT '<PRESIGNED_URL_FOR_images.zip>' \
  --header 'Content-Type: application/zip' \
  --header 'x-amz-acl: private' \
  --data-binary '@images.zip'

ZIP 제한

  • ZIP 최대 크기: 100MB
  • 일괄당 최대 이미지 수: 50
  • 이미지당: 최소 1KB, 최대 10MB

ZIP 내부 지원 형식

JPG, JPEG, PNG, WebP, JFIF, HEIC, HEIF, AVIF, BMP, TIFF, TIF, GIF, SVG

ZIP 내부 PDF는 지원하지 않으며 건너뜁니다.

SVG는 감지 전 PNG로 변환됩니다.

3. ZIP 일괄 감지 제출

POST /bulk-upload에 key와 업로드된 ZIP 경로를 가리키는 url을 전달합니다.

선택 파라미터

  • generate_preview: true면 이미지별 미리보기 URL 생성(기본: false).
  • generate_analysis_details: true면 상세 분석 생성(기본: false).
  • generate_heatmap_overlayed: /detect와 동일(오버레이 vs 투명 RGBA 히트맵).
  • generate_heatmap_normalized: /detect와 동일(기본: true).
  • model: 모델 도메인: generic, instance_id/model 형식.

요청 예시

curl -X 'POST' \
  'https://detect-image.truthscan.com/bulk-upload' \
  -H 'accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{
  "key": "YOUR-API-KEY-GOES-HERE",
  "url": "https://ai-image-detector-prod.nyc3.digitaloceanspaces.com/<FILE_PATH>",
  "generate_preview": false,
  "generate_analysis_details": false,
  "model": "generic"
}'

응답 예시

{
    "id": "77565038-9e3d-4e6a-8c80-e20785be5ee9",
    "status": "pending",
    "expected_count": 12
}

id, status pending, expected_count(ZIP에서 분석할 이미지 수)를 반환합니다.

ZIP 일괄 결과 갱신 방식

  • 제출 직후 처리 시작 전까지 status는 pending, 이후 analyzing.
  • results에 이미지별 항목; 완료 전까지 result와 result_details가 null일 수 있음.
  • 히트맵·상세 분석은 result_details 안에서 아직 pending일 수 있음.
  • results의 모든 이미지가 끝나면 전체 status는 done. 배치 실패 시 failed.
  • ZIP 완료 전에도 /query로 부분 결과를 볼 수 있음.

4. Bulk Upload 결과 조회

POST /query에 /bulk-upload에서 받은 id. 단일 이미지와 동일 엔드포인트; id가 단일인지 ZIP 배치인지에 따라 응답 형태가 달라집니다.

curl -X 'POST' \
  'https://detect-image.truthscan.com/query' \
  -H 'accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{
  "id": "77565038-9e3d-4e6a-8c80-e20785be5ee9"
}'

응답 예시(아직 처리 중)

{
  "id": "3b81fb24-dd23-40e7-ae95-82f823f44098",
  "status": "analyzing",
  "results": [
    {
      "id": "4600c7e5-00ec-469d-9117-ff20e0f1c1fa",
      "status": "done",
      "result": 44.0006,
      "result_details": {},
      "filename": "photo1.jpg",
      "preview_url": null
    },
    {
      "id": "2f770c89-352a-4d53-b6a3-a2147ca2c0ae",
      "status": "pending",
      "result": null,
      "result_details": null,
      "filename": "photo2.jpg",
      "preview_url": null
    }
  ],
  "skipped": []
}

응답 필드 (bulk ZIP)

  • id — 일괄 요청 id.
  • status — pending, 이후 analyzing, done 또는 failed.
  • results — 분석 중인 이미지별 항목(id, status, result, result_details, filename, preview_url 등).
  • skipped — 분석하지 않은 파일(지원하지 않는 형식, 크기 등)로 status failed와 result_details에 사유.

과금: 성공적으로 분석된 이미지에만 크레딧이 사용됩니다. SVG 변환 실패·건너뛴 파일은 과금되지 않습니다.

Secure heatmap and preview assets

/query의 heatmap_url 또는 preview_url이 객체 스토리지가 아닌 API 호스트를 가리키면, POST와 key로 바이트를 가져옵니다.

POST /heatmap/{id}

POST /preview/{id}

Request body JSON: { "key": "YOUR-API-KEY-GOES-HERE" }

Heatmap 응답(HTTP 상태 및 Content-Type 확인)

  • 200 + binary (image/png 등) — 히트맵 파일 사용 가능. X-Heatmap-Status 설정 가능.
  • 202 + JSON — heatmap_status pending; /query 폴링 후 재시도.
  • 200 + JSON — 제공할 히트맵 없음(선택 기능, 실패 등); 서버 오류 아님.
  • 500 + JSON — 저장된 heatmap_url은 있으나 스토리지에서 다운로드 실패; 나중에 재시도.
  • 404 + JSON — document id 없음.
  • 403 + JSON — API key가 해당 문서 소유가 아님.

Preview: POST /preview/{id}는 원시 미리보기 바이트를 반환합니다. 미리보기가 없으면(generate_preview false) JSON과 함께 404.

예시

curl -X POST 'https://detect-image.truthscan.com/heatmap/00fee5ff-a55b-42fb-b7c7-d14f05ae0769' \
  -H 'Content-Type: application/json' \
  -d '{"key":"YOUR-API-KEY-GOES-HERE"}' \
  --output heatmap.png
curl -X POST 'https://detect-image.truthscan.com/preview/00fee5ff-a55b-42fb-b7c7-d14f05ae0769' \
  -H 'Content-Type: application/json' \
  -d '{"key":"YOUR-API-KEY-GOES-HERE"}' \
  --output preview.png

내부: 조직 사용량 Stripe 동기화 (job secret)

신뢰할 수 있는 백엔드 작업 전용이며 일반 API 고객용이 아닙니다. 헤더 x-job-secret이 서버 JOB_SECRET과 일치해야 합니다. 지정 기간 TruthScan 조직 사용량을 Stripe에 미터링 동기화합니다.

POST /organizations/{org_id}/usage/sync-to-stripe

Headers: x-job-secret: <JOB_SECRET>

Body JSON: start_date, end_date, Stripe 미터 idempotency용 선택 idempotency_id.

success, organization_id, total_documents, value_sent_to_stripe, report_date, message 반환. 조직이 미터링이 아니거나 stripe_customer_id 필요 시 없으면 400; 비밀 401; 조직 없음 404; Stripe/설정 오류 500.

사용자 크레딧 확인

이 엔드포인트는 헤더로 사용자 apikey를 받아 크레딧 정보를 반환합니다.

GET https://detect-image.truthscan.com/check-user-credits

요청 예시

curl -X 'GET' \
  'https://detect-image.truthscan.com/check-user-credits' \
  -H 'apikey: YOUR API KEY GOES HERE' \
  -H 'accept: application/json' \
  -H 'Content-Type: application/json'

응답 예시

{
    "baseCredits": 10000,
    "boostCredits": 1000,
    "credits": 11000
}

외부 연동에서는 credits 필드만 채워집니다.

헬스 체크

API 서버의 상태를 확인합니다.

GET https://detect-image.truthscan.com/health

요청 예시

curl -X 'GET' \
  'https://detect-image.truthscan.com/health' \
  -H 'accept: application/json'

응답 예시

{
    "status": "healthy"
}

"healthy" 응답은 서비스가 정상 동작 중임을 의미합니다.

오류

대부분의 오류는 API로 잘못된 파라미터를 보냈을 때 발생합니다. 각 호출을 다시 확인하고 제공된 예시를 참고하세요.

사용하는 일반 오류 코드는 REST 표준을 따릅니다:

오류 코드의미
400Bad Request — 요청이 유효하지 않습니다.
401Unauthorized — 잘못된 job secret(내부 사용 엔드포인트) 또는 유사 인증 실패.
403Forbidden — API key가 유효하지 않거나 접근이 거부되었거나 작업에 필요한 크레딧이 부족합니다.
404Not Found — 지정한 리소스가 없습니다.
405Method Not Allowed — 허용되지 않은 메서드로 리소스에 접근했습니다.
406Not Acceptable — JSON이 아닌 형식을 요청했습니다.
410Gone — 이 엔드포인트의 리소스가 제거되었습니다.
422Invalid Request Body — 요청 본문 형식이 잘못되었거나 유효하지 않거나 필수 파라미터가 누락되었습니다.
429Too Many Requests — API key별 rate limit을 초과했습니다(Rate Limits 참조). 본문은 {"error":"Too many requests"}이며, X-RateLimit-Retry-After 헤더가 재시도까지 대기할 초를 알려줍니다.
500Internal Server Error — 서버 문제가 발생했습니다. 나중에 다시 시도하세요.
503Service Unavailable — 유지보수로 일시 중단되었습니다. 나중에 다시 시도하세요.

일반적인 문제와 해결

인증 문제

"User verification failed" (403)

원인: 유효하지 않거나 만료된 API key

해결:

  1. API key가 정확한지 확인
  2. 계정에서 API key가 활성인지 확인
  3. API key 재발급 시도

"Not enough credits" (403)

원인: 이미지 처리에 필요한 크레딧 부족

해결:

  1. /check-user-credits로 남은 크레딧 확인
  2. 필요 시 추가 크레딧 구매

입력 검증 문제

"Input URL cannot be empty" (400)

원인: 빈 URL 또는 유효하지 않은 URL 제출

해결:

  1. url 입력이 비어 있지 않은지 확인
  2. 이미지 이름의 앞뒤 공백 제거
  3. URL 인코딩이 올바른지 확인

"Input email is empty" (400)

원인: URL 처리에 필요한 이메일 누락

해결:

  1. URL 제출 시 유효한 이메일 주소 제공
  2. 이메일 형식 확인

"Unsupported image type" (400)

원인: 지원하지 않는 파일 형식

해결:

  1. 지원 형식으로 변환(JPG, PNG, WebP, HEIC, HEIF, AVIF, BMP, TIFF, GIF, SVG, PDF)
  2. 파일 확장자가 올바른지 확인

"File size is too small" (400)

원인: 이미지가 최소 크기 미만

해결:

  1. 더 큰 이미지 사용(최소 1KB)
  2. 업로드 중 손상 여부 확인

"File size exceeds limit" (400)

원인: 이미지가 최대 크기 초과

해결:

  1. 압축 또는 리사이즈(API 오류 메시지에 MB 단위 제한이 표시됨)
  2. 다른 이미지 형식 사용

"Invalid file type" (400)

원인: 파일 유형 검증 실패

해결:

  1. 유효한 이미지 형식인지 확인
  2. 파일이 손상되지 않았는지 확인
  3. MIME 타입이 확장자와 일치하는지 확인

처리 문제

이미지 상태 "failed"

원인: 다양한 이유로 처리 실패

해결:

  1. URL이 지원 형식인지 확인
  2. 이미지 파일이 유효하고 손상되지 않았는지 확인
  3. 크기 요건 충족 여부 확인
  4. 문제가 지속되면 지원팀에 문의

"User not found"

원인: 유효하지 않은 사용자 ID

해결:

  1. 사용자 ID가 올바른지 확인
  2. 계정이 활성인지 확인
  3. 필요 시 재인증

"File metadata could not be fetched" (500)

원인: 업로드된 파일에 접근할 수 없음

해결:

  1. 파일이 성공적으로 업로드되었는지 확인
  2. 파일 URL에 접근 가능한지 확인
  3. 파일을 다시 업로드 시도

업로드 문제

"Image upload failed" (403/400)

원인: 유효하지 않거나 만료된 pre-signed URL, 또는 스토리지 서버 문제

해결:

  1. pre-signed URL을 받은 직후 사용
  2. Content-Type이 파일 형식과 일치하는지 확인
  3. 업로드 전 파일명에서 공백 제거
  4. 필요 시 새 pre-signed URL 발급

"Invalid pre-signed URL" (400)

원인: 공백이 있는 파일명 또는 만료/손상된 pre-signed URL

해결:

  1. pre-signed URL 요청 전 파일명에서 공백 제거
  2. 영문자, 숫자, 하이픈, 밑줄 사용
  3. 필요 시 새 pre-signed URL 발급

일괄 업로드 문제

"URL must point to a ZIP file" (400)

원인: /bulk-upload에 전달한 URL이 ZIP을 가리키지 않음

해결:

  1. get-presigned-url?file_name=images.zip(또는 다른 .zip 이름) 사용
  2. 유효한 ZIP을 presigned URL에 업로드
  3. bulk-upload 요청의 url이 해당 업로드 ZIP을 가리키는지 확인

"ZIP file too large" (400)

원인: ZIP이 최대 크기(100MB) 초과

해결:

  1. 이미지 수를 줄이거나 압축
  2. 여러 번 일괄 업로드로 분할

"Too many files" (400)

원인: ZIP에 유효한 이미지가 50개 초과

해결:

  1. ZIP당 50장 이하로
  2. 여러 번 일괄 업로드로 분할

"No valid images found in ZIP" (400)

원인: ZIP의 모든 파일이 건너뛰어짐(지원하지 않는 형식, 너무 작음, 잘못된 경로 등)

해결:

  1. 지원 형식 사용(JPG, PNG, WebP, HEIC, HEIF, AVIF, BMP, TIFF, TIF, GIF, SVG)
  2. 일괄 업로드에서는 PDF 미지원
  3. 각 이미지 최소 1KB, 최대 10MB
  4. 숨김 파일(이름이 .) 및 경로 조작(..) 피하기

"Document is not a bulk upload (image-zip) result" (400)

원인: id가 해당 업로드 유형과 맞지 않음(단일 이미지 vs ZIP 배치)

해결:

  1. 단일 이미지 제출에는 /detect의 id 사용
  2. ZIP 제출에는 /bulk-upload의 id 사용

도움이 필요하신가요?

API 사용에 대한 자세한 정보나 기술 지원이 필요하면 문의해 주세요.

API 자주 묻는 질문

TruthScan AI 이미지 감지 API에 대한 가장 흔한 질문과 답변입니다.