{"version":"3.5.1","baseUrl":"https://caricature-api-rust.wizice.com","importantNotes":[{"severity":"critical","title":"t2i/i2i 상태 조회 엔드포인트 불일치","description":"t2i로 생성한 Job을 i2i 상태 엔드포인트로 조회하면 JOB_NOT_FOUND. 반드시 같은 타입의 엔드포인트 사용: t2i→/text-to-image/status, i2i→/caricature/status"},{"severity":"critical","title":"t2i는 storage_type: gcs를 무시","description":"Text-to-Image는 storage_type을 지정해도 항상 base64(imageData)로 반환. URL이 필요하면 base64를 별도 스토리지에 업로드 필요."},{"severity":"warning","title":"t2i/i2i 파라미터명 차이","description":"t2i: aspect_ratio (snake_case, JSON), i2i: aspectRatio (camelCase, FormData). t2i의 ttlHours는 반드시 숫자 타입(문자열 불가)."},{"severity":"info","title":"AI 워터마크 자동 삽입","description":"모든 생성 이미지에 우측 하단 AI 마크가 자동 삽입됩니다 (한국 AI 기본법 준수)."}],"authentication":[{"method":"API Key (Header)","header":"X-API-Key","description":"API 키를 헤더에 포함 (권장)","example":"X-API-Key: your-api-key"},{"method":"API Key (Bearer)","header":"Authorization","description":"Bearer 토큰 형식으로 전달","example":"Authorization: Bearer your-api-key"},{"method":"Cookie Auth","header":"Cookie","description":"테스트 페이지 전용. /test/login에서 로그인 후 자동 설정","example":"Cookie: test_auth=PASSWORD"}],"supportedModels":[{"model":"gemini-3-pro-image-preview","provider":"Google","modelType":"Text-to-Image, Image-to-Image","costPerRequest":"$0.12","status":"Active (2026 Latest)"},{"model":"gemini-2.5-flash-image","provider":"Google","modelType":"Text-to-Image, Image-to-Image","costPerRequest":"$0.039","status":"Active (Recommended)"},{"model":"gpt-image-1","provider":"OpenAI","modelType":"Text-to-Image","costPerRequest":"$0.04-0.08","status":"Active"},{"model":"imagen-3","provider":"Google","modelType":"Text-to-Image","costPerRequest":"$0.03","status":"Active"},{"model":"dall-e-3","provider":"OpenAI","modelType":"Text-to-Image","costPerRequest":"$0.04-0.08","status":"Active"},{"model":"claude-opus-4-6","provider":"Anthropic","modelType":"Text-to-Text","costPerRequest":"$5/$25 per MTok","status":"Active (2026 Latest)"},{"model":"claude-sonnet-4-6","provider":"Anthropic","modelType":"Text-to-Text","costPerRequest":"$3/$15 per MTok","status":"Active (Recommended)"},{"model":"claude-haiku-4-5-20251001","provider":"Anthropic","modelType":"Text-to-Text","costPerRequest":"$1/$5 per MTok","status":"Active"},{"model":"claude-opus-4-20250514","provider":"Anthropic","modelType":"Text-to-Text","costPerRequest":null,"status":"Legacy"},{"model":"claude-sonnet-4-20250514","provider":"Anthropic","modelType":"Text-to-Text","costPerRequest":null,"status":"Legacy"},{"model":"claude-3-7-sonnet-20250219","provider":"Anthropic","modelType":"Text-to-Text","costPerRequest":null,"status":"Active"},{"model":"claude-3-5-sonnet-20241022","provider":"Anthropic","modelType":"Text-to-Text","costPerRequest":null,"status":"Active"},{"model":"claude-3-5-haiku-20241022","provider":"Anthropic","modelType":"Text-to-Text","costPerRequest":null,"status":"Active"},{"model":"gemini-3-flash-preview","provider":"Google","modelType":"Text-to-Text, Vision Analysis","costPerRequest":"$0.075/$0.30 per MTok","status":"Active (2026 Latest)"},{"model":"gemini-2.5-flash","provider":"Google","modelType":"Text-to-Text, Vision Analysis","costPerRequest":null,"status":"Active"},{"model":"gemini-2.5-pro","provider":"Google","modelType":"Text-to-Text, Vision Analysis","costPerRequest":null,"status":"Active"},{"model":"gemini-1.5-flash","provider":"Google","modelType":"Text-to-Text","costPerRequest":null,"status":"Legacy"},{"model":"gemini-1.5-pro","provider":"Google","modelType":"Text-to-Text","costPerRequest":null,"status":"Legacy"},{"model":"gemini-3-flash-preview","provider":"Google","modelType":"Vision Analysis","costPerRequest":null,"status":"Active (2026 Latest, Recommended)"},{"model":"gpt-4o","provider":"OpenAI","modelType":"Vision Analysis","costPerRequest":null,"status":"Active"},{"model":"claude-sonnet-4-6","provider":"Anthropic","modelType":"Vision Analysis","costPerRequest":null,"status":"Active (2026 Latest)"}],"categories":["Text-to-Image","Image-to-Image","Gemini Text-to-Image (Legacy)","Text-to-Text","Image Analysis","Image Processing","QR Code","Receipt","Contour","e-KYC","Jobs & Logs","Admin"],"endpoints":[{"method":"POST","path":"/api/v1/text-to-image/generate","description":"텍스트로 이미지 생성","category":"Text-to-Image","authentication":"API Key (X-API-Key header)","requestParams":[{"name":"model","paramType":"json","required":true,"description":"AI 모델명","example":"gemini-2.5-flash-image"},{"name":"prompt","paramType":"json","required":true,"description":"이미지 설명 프롬프트","example":"A serene mountain landscape at sunset"},{"name":"aspect_ratio","paramType":"json","required":false,"description":"이미지 비율 (1:1, 16:9, 3:4 등)","example":"16:9"},{"name":"style","paramType":"json","required":false,"description":"추가 스타일 설명","example":"watercolor painting"},{"name":"storage_type","paramType":"json","required":false,"description":"저장 타입. firestore(base64) 또는 gcs(URL). 기본: firestore","example":"firestore"},{"name":"ttlHours","paramType":"json","required":false,"description":"이미지 유효 시간(시). 기본: 1","example":"24"}],"responseExample":"{\"jobId\": \"txt2img_20260207_abc123\", \"accessKey\": \"access_key_value\", \"status\": \"processing\", \"estimatedCost\": 0.039}"},{"method":"GET","path":"/api/v1/text-to-image/status/{job_id}","description":"텍스트-투-이미지 생성 상태 조회","category":"Text-to-Image","authentication":"X-API-Key header 또는 Authorization: Bearer {accessKey}","requestParams":[{"name":"job_id","paramType":"path","required":true,"description":"Job ID","example":"txt2img_20260207_abc123"}],"responseExample":"{\"jobId\": \"txt2img_20260207_abc123\", \"status\": \"completed\", \"imageUrl\": \"https://...\", \"processingTimeMs\": 3500, \"actualCost\": 0.039}"},{"method":"GET","path":"/api/v1/text-to-image/download/{job_id}","description":"생성된 이미지 직접 다운로드","category":"Text-to-Image","authentication":"X-API-Key header 또는 Authorization: Bearer {accessKey}","requestParams":[{"name":"job_id","paramType":"path","required":true,"description":"Job ID","example":"txt2img_20260207_abc123"}],"responseExample":"image/png binary"},{"method":"GET","path":"/api/v1/text-to-image/models","description":"사용 가능한 텍스트-투-이미지 모델 목록","category":"Text-to-Image","authentication":"API Key (X-API-Key header)","requestParams":[],"responseExample":"{\"models\": [{\"model\": \"gemini-2.5-flash-image\", \"provider\": \"google\", \"cost\": 0.039}]}"},{"method":"POST","path":"/api/v1/image-to-image/generate","description":"이미지 변환 생성 (Image-to-Image). 별칭: /api/v1/caricature/generate","category":"Image-to-Image","authentication":"API Key (X-API-Key header)","requestParams":[{"name":"image","paramType":"multipart","required":false,"description":"원본 이미지 파일 (image 또는 imageUrl 중 하나 필수)","example":null},{"name":"imageUrl","paramType":"multipart","required":false,"description":"원본 이미지 URL (image 또는 imageUrl 중 하나 필수)","example":"https://example.com/photo.jpg"},{"name":"model","paramType":"multipart","required":false,"description":"AI 모델. 기본: gemini-2.5-flash-image","example":"gemini-2.5-flash-image"},{"name":"prompt","paramType":"multipart","required":false,"description":"스타일 프롬프트","example":"cute caricature style"},{"name":"aspect_ratio","paramType":"multipart","required":false,"description":"출력 이미지 비율","example":"1:1"},{"name":"temperature","paramType":"multipart","required":false,"description":"생성 온도 (0.0~2.0). 낮을수록 보수적, 높을수록 창의적. 기본: 0.9","example":"0.9"},{"name":"ttlHours","paramType":"multipart","required":false,"description":"이미지 유효 시간(시)","example":"24"}],"responseExample":"{\"jobId\": \"caric_20260207_xyz789\", \"accessKey\": \"access_key_value\", \"status\": \"processing\"}"},{"method":"GET","path":"/api/v1/image-to-image/status/{job_id}","description":"Image-to-Image 생성 상태 조회. 별칭: /api/v1/caricature/status/{job_id}","category":"Image-to-Image","authentication":"X-API-Key header 또는 Authorization: Bearer {accessKey}","requestParams":[{"name":"job_id","paramType":"path","required":true,"description":"Job ID","example":"caric_20260207_xyz789"}],"responseExample":"{\"jobId\": \"caric_20260207_xyz789\", \"status\": \"completed\", \"imageUrl\": \"/api/v1/caricature/image?key=...\", \"processingTime\": 13.8, \"actualCost\": 0.039}"},{"method":"GET","path":"/api/v1/image-to-image/image","description":"Image-to-Image 결과 이미지 다운로드 (accessKey 인증). 별칭: /api/v1/caricature/image","category":"Image-to-Image","authentication":"Query parameter (accessKey)","requestParams":[{"name":"accessKey","paramType":"query","required":true,"description":"생성 시 반환된 accessKey","example":"access_key_value"}],"responseExample":"image/png binary"},{"method":"POST","path":"/api/v1/gemini/text-to-image","description":"동기식 텍스트-투-이미지 생성 (이미지 직접 반환, Legacy)","category":"Gemini Text-to-Image (Legacy)","authentication":"API Key (X-API-Key header)","requestParams":[{"name":"prompt","paramType":"json","required":true,"description":"이미지 설명 프롬프트","example":"A cute cat wearing a hat"},{"name":"model","paramType":"json","required":false,"description":"Gemini 모델. 기본: gemini-2.5-flash-image","example":"gemini-2.5-flash-image"},{"name":"aspect_ratio","paramType":"json","required":false,"description":"이미지 비율","example":"1:1"},{"name":"style","paramType":"json","required":false,"description":"추가 스타일 설명","example":"anime style"},{"name":"storage_type","paramType":"json","required":false,"description":"저장 타입. base64 또는 gcs. 기본: base64","example":"base64"}],"responseExample":"{\"success\": true, \"image\": \"base64_data...\", \"model\": \"gemini-2.5-flash-image\"}"},{"method":"POST","path":"/api/v1/text-to-text/generate","description":"텍스트 생성 (Claude, Gemini 모델 지원)","category":"Text-to-Text","authentication":"API Key (X-API-Key header)","requestParams":[{"name":"model","paramType":"json","required":true,"description":"AI 모델명","example":"claude-sonnet-4-6"},{"name":"prompt","paramType":"json","required":true,"description":"텍스트 프롬프트","example":"Write a haiku about coding"},{"name":"response_format","paramType":"json","required":false,"description":"응답 형식. text 또는 json. 기본: text","example":"text"},{"name":"max_tokens","paramType":"json","required":false,"description":"최대 토큰 수. 기본: 4096","example":"4096"},{"name":"temperature","paramType":"json","required":false,"description":"응답 다양성 (0.0~1.0). 기본: 0.7","example":"0.7"}],"responseExample":"{\"success\": true, \"model\": \"claude-sonnet-4-6\", \"provider\": \"claude\", \"text\": \"Lines of logic flow\\nBugs hide in the midnight code\\nTests bring clarity\", \"processing_time_ms\": 1200, \"usage\": {\"input_tokens\": 15, \"output_tokens\": 25}}"},{"method":"GET","path":"/api/v1/text-to-text/models","description":"사용 가능한 텍스트 생성 모델 목록","category":"Text-to-Text","authentication":"API Key (X-API-Key header)","requestParams":[],"responseExample":"{\"models\": [{\"model\": \"claude-sonnet-4-6\", \"provider\": \"claude\", \"description\": \"...\"}]}"},{"method":"POST","path":"/api/v1/analyze/image","description":"이미지 분석 (멀티모달 AI, 전처리 지원)","category":"Image Analysis","authentication":"API Key (X-API-Key header)","requestParams":[{"name":"image","paramType":"multipart","required":true,"description":"분석할 이미지 파일","example":null},{"name":"model","paramType":"multipart","required":false,"description":"AI 모델. 기본: gemini-3-flash-preview (2026 최신)","example":"gemini-3-flash-preview"},{"name":"prompt","paramType":"multipart","required":false,"description":"분석 요청 프롬프트","example":"이 이미지를 자세히 분석해주세요"},{"name":"temperature","paramType":"multipart","required":false,"description":"응답 다양성 (0.0~1.0). 기본: 0.7","example":"0.7"},{"name":"enablePreprocessing","paramType":"multipart","required":false,"description":"이미지 전처리 활성화","example":"true"},{"name":"preprocessingPreset","paramType":"multipart","required":false,"description":"전처리 프리셋: ocr, qr, enhance","example":"ocr"}],"responseExample":"{\"jobId\": \"analyze_xxx\", \"accessKey\": \"xxx\", \"status\": \"processing\"}"},{"method":"GET","path":"/api/v1/analyze/status/{job_id}","description":"이미지 분석 상태 조회","category":"Image Analysis","authentication":"X-API-Key header 또는 Authorization: Bearer {accessKey}","requestParams":[{"name":"job_id","paramType":"path","required":true,"description":"Job ID","example":"analyze_xxx"}],"responseExample":"{\"jobId\": \"analyze_xxx\", \"status\": \"completed\", \"result\": \"...\"}"},{"method":"POST","path":"/api/v1/image/remove-background","description":"배경 제거 (Chroma Key 기반 투명 PNG 생성). 동기 방식으로 즉시 결과 반환","category":"Image Processing","authentication":"API Key (X-API-Key header)","requestParams":[{"name":"imageUrl","paramType":"json","required":false,"description":"배경을 제거할 이미지 URL (imageUrl 또는 jobId 중 하나 필수)","example":"https://example.com/photo.jpg"},{"name":"jobId","paramType":"json","required":false,"description":"기존 Job ID로 이미지 참조 (imageUrl 대신 사용 가능)","example":"txt2img_20260207_abc123"},{"name":"method","paramType":"json","required":false,"description":"배경 제거 방식. 기본: chroma","example":"chroma"},{"name":"chromaKey.color","paramType":"json","required":true,"description":"제거할 배경색. Hex 코드(#FFFFFF) 또는 'auto'(자동 검출)","example":"auto"},{"name":"chromaKey.tolerance","paramType":"json","required":false,"description":"색상 허용 오차 (0-255). 미지정 시 이미지 분석으로 자동 계산","example":"30"},{"name":"edgeSmoothing","paramType":"json","required":false,"description":"경계 부드럽게 처리 (Feathering). 기본: true","example":"true"},{"name":"trimTransparent","paramType":"json","required":false,"description":"투명 영역 자동 트리밍 (크기 최적화). 기본: true","example":"true"},{"name":"storageType","paramType":"json","required":false,"description":"결과 저장 방식: gcs (URL 반환) 또는 firestore (base64). 기본: gcs","example":"gcs"},{"name":"ttlHours","paramType":"json","required":false,"description":"결과 이미지 유효 시간(시). 기본: 24","example":"24"}],"responseExample":"{\"success\": true, \"jobId\": \"bg_remove_abc123\", \"originalUrl\": \"https://...\", \"processedUrl\": \"https://storage.googleapis.com/.../bg_remove_abc123.png\", \"format\": \"PNG\", \"processingTime\": 1200, \"method\": \"chroma\", \"removedColor\": \"#FFFFFF\", \"transparentPixels\": 150000, \"fileSize\": 45000, \"originalDimensions\": [800, 600], \"trimmedDimensions\": [750, 580]}"},{"method":"GET","path":"/api/v1/qrcode/generate","description":"QR 코드 생성","category":"QR Code","authentication":"None","requestParams":[{"name":"data","paramType":"query","required":true,"description":"QR 코드에 인코딩할 데이터","example":"https://smileprint.app"},{"name":"size","paramType":"query","required":false,"description":"이미지 크기. 기본: 512x512","example":"512x512"},{"name":"format","paramType":"query","required":false,"description":"출력 포맷. 기본: png","example":"png"},{"name":"center_text","paramType":"query","required":false,"description":"중앙에 표시할 텍스트 (예: AI)","example":"AI"}],"responseExample":"image/png binary (1-bit 최적화)"},{"method":"POST","path":"/api/v1/qrcode/recognize","description":"QR 코드 인식 (이미지 전처리 지원)","category":"QR Code","authentication":"API Key (X-API-Key header)","requestParams":[{"name":"image","paramType":"multipart","required":true,"description":"QR 코드 이미지 파일","example":null},{"name":"enablePreprocessing","paramType":"multipart","required":false,"description":"전처리 활성화. 기본: true","example":"true"}],"responseExample":"{\"success\": true, \"data\": \"https://example.com\", \"method\": \"clahe+binary\", \"attempts\": 3}"},{"method":"POST","path":"/api/v1/receipt/optimize","description":"영수증 이미지 최적화 (OCR 개선)","category":"Receipt","authentication":"API Key (X-API-Key header)","requestParams":[{"name":"image","paramType":"multipart","required":true,"description":"영수증 이미지 파일","example":null}],"responseExample":"{\"jobId\": \"receipt_xxx\", \"accessKey\": \"xxx\", \"status\": \"processing\"}"},{"method":"GET","path":"/api/v1/receipt/status/{job_id}","description":"영수증 최적화 상태 조회","category":"Receipt","authentication":"API Key (X-API-Key header)","requestParams":[{"name":"job_id","paramType":"path","required":true,"description":"Job ID","example":"receipt_xxx"}],"responseExample":"{\"jobId\": \"receipt_xxx\", \"status\": \"completed\", \"result\": \"...\"}"},{"method":"POST","path":"/api/v1/contour/extract","description":"AI 윤곽선 추출","category":"Contour","authentication":"API Key (X-API-Key header)","requestParams":[{"name":"image","paramType":"multipart","required":true,"description":"윤곽선을 추출할 이미지 파일","example":null}],"responseExample":"image/png binary (윤곽선 이미지)"},{"method":"POST","path":"/api/v1/ekyc/verify","description":"통합 본인 인증 (OCR + 얼굴 비교 + 라이브니스, 병렬 처리)","category":"e-KYC","authentication":"API Key (X-API-Key header)","requestParams":[{"name":"masked_id_image","paramType":"multipart","required":true,"description":"신분증 이미지 (JPEG/PNG, max 10MB)","example":null},{"name":"face_image","paramType":"multipart","required":true,"description":"신분증 사진에서 추출한 얼굴 이미지 (JPEG/PNG, max 5MB)","example":null},{"name":"selfie_image","paramType":"multipart","required":true,"description":"셀피 이미지 (JPEG/PNG, max 10MB)","example":null},{"name":"id_card_type","paramType":"multipart","required":true,"description":"신분증 종류: resident_registration, driver_license, passport","example":"resident_registration"}],"responseExample":"{\"success\": true, \"verification_id\": \"ekyc_20260214_abc1234\", \"results\": {\"ocr\": {\"name\": \"홍길동\", \"birth_date\": \"1990-01-15\", \"confidence\": 0.95, \"suggestions\": []}, \"face_match\": {\"similarity\": 0.87, \"threshold\": 0.60, \"passed\": true}, \"liveness\": {\"score\": 0.92, \"threshold\": 0.50, \"passed\": true}}, \"overall_passed\": true, \"failure_reasons\": [], \"processing_time_ms\": 4500}"},{"method":"POST","path":"/api/v1/ekyc/face/compare","description":"두 얼굴 이미지 유사도 비교","category":"e-KYC","authentication":"API Key (X-API-Key header)","requestParams":[{"name":"image1","paramType":"multipart","required":true,"description":"기준 얼굴 이미지","example":null},{"name":"image2","paramType":"multipart","required":true,"description":"비교 대상 얼굴 이미지","example":null},{"name":"threshold","paramType":"multipart","required":false,"description":"판정 임계값 (0.0~1.0). 기본: 0.6","example":"0.6"}],"responseExample":"{\"similarity\": 0.85, \"threshold\": 0.60, \"passed\": true, \"face1_detected\": true, \"face2_detected\": true, \"processing_time_ms\": 2100}"},{"method":"POST","path":"/api/v1/ekyc/liveness/check","description":"라이브니스 검증 (실제 얼굴 vs 사진/화면 판별)","category":"e-KYC","authentication":"API Key (X-API-Key header)","requestParams":[{"name":"image","paramType":"multipart","required":true,"description":"셀피 이미지","example":null}],"responseExample":"{\"score\": 0.92, \"threshold\": 0.50, \"passed\": true, \"face_detected\": true, \"processing_time_ms\": 1800}"},{"method":"POST","path":"/api/v1/ekyc/image/quality-check","description":"이미지 품질 사전 검사 (밝기, 대비, 선명도 등)","category":"e-KYC","authentication":"API Key (X-API-Key header)","requestParams":[{"name":"image","paramType":"multipart","required":true,"description":"검사할 이미지 (JPEG/PNG, max 10MB)","example":null}],"responseExample":"{\"brightness\": 0.5, \"contrast\": 0.7, \"sharpness\": 0.8, \"overall_quality\": 0.75, \"passed\": true, \"suggestions\": [], \"processing_time_ms\": 1200}"},{"method":"POST","path":"/api/v1/ekyc/account/holder-name","description":"계좌번호로 예금주명 조회 (토스페이먼츠)","category":"e-KYC","authentication":"API Key (X-API-Key header)","requestParams":[{"name":"bankCode","paramType":"json","required":true,"description":"은행 코드 (004=KB국민, 088=신한, 020=우리, 081=하나 등)","example":"088"},{"name":"accountNumber","paramType":"json","required":true,"description":"계좌번호 (하이픈 없이, 최대 14자)","example":"110123456789"}],"responseExample":"{\"holderName\": \"홍길동\", \"processingTimeMs\": 350}"},{"method":"POST","path":"/api/v1/ekyc/account/validate","description":"계좌번호 유효성 확인 (토스페이먼츠)","category":"e-KYC","authentication":"API Key (X-API-Key header)","requestParams":[{"name":"bankCode","paramType":"json","required":true,"description":"은행 코드","example":"088"},{"name":"accountNumber","paramType":"json","required":true,"description":"계좌번호 (하이픈 없이, 최대 14자)","example":"110123456789"}],"responseExample":"{\"isValid\": true, \"processingTimeMs\": 280}"},{"method":"POST","path":"/api/v1/ekyc/account/verify","description":"예금주명(+식별자) 일치 확인 (토스페이먼츠)","category":"e-KYC","authentication":"API Key (X-API-Key header)","requestParams":[{"name":"bankCode","paramType":"json","required":true,"description":"은행 코드","example":"088"},{"name":"accountNumber","paramType":"json","required":true,"description":"계좌번호 (하이픈 없이)","example":"110123456789"},{"name":"holderName","paramType":"json","required":true,"description":"예금주명","example":"홍길동"},{"name":"identityNumber","paramType":"json","required":false,"description":"생년월일(YYMMDD) 또는 사업자번호. 포함 시 실명 확인까지 수행","example":"900115"}],"responseExample":"{\"isValid\": true, \"processingTimeMs\": 310}"},{"method":"POST","path":"/api/v1/ekyc/enhance","description":"신분증 AI 보정 (동기/비동기). 타일 분할 → Gemini 보정 → 블렌딩 합성. 민감영역은 블러 처리 후 원본 복원","category":"eKYC Enhance","authentication":"API Key (X-API-Key header)","requestParams":[{"name":"image","paramType":"file","required":true,"description":"투시 보정된 신분증 이미지 (JPG, 1280x807 권장)","example":null},{"name":"doc_type","paramType":"form","required":true,"description":"신분증 유형: jumin, alien, driver","example":"jumin"},{"name":"privacy_mode","paramType":"form","required":false,"description":"민감영역 처리 모드 (기본: juminMask)","example":"juminMask"},{"name":"privacy_regions","paramType":"form","required":false,"description":"민감영역 좌표 JSON. 미제공 시 doc_type별 기본 좌표 사용","example":"{\"regions\":[{\"field\":\"name\",\"x\":0.22,\"y\":0.20,\"w\":0.35,\"h\":0.12}]}"},{"name":"callback_url","paramType":"form","required":false,"description":"비동기 모드: 완료 시 POST 콜백 URL","example":null},{"name":"callback_meta","paramType":"form","required":false,"description":"콜백 시 그대로 반환할 메타데이터 JSON","example":null},{"name":"tenant_id","paramType":"form","required":false,"description":"소속 코드 (비용 추적용)","example":null}],"responseExample":"{\"success\": true, \"jobId\": \"ekyc-enhance-20260308_aBcDeFgH\", \"enhancedImageUrl\": \"https://...\", \"qualityBefore\": {\"brightness\": 0.45, \"contrast\": 0.22, \"sharpness\": 78.5, \"overallScore\": 0.68}, \"qualityAfter\": {\"brightness\": 0.52, \"contrast\": 0.35, \"sharpness\": 145.2, \"overallScore\": 0.91}, \"tilesProcessed\": 2, \"processingTimeMs\": 25000, \"estimatedCostUsd\": 0.24}"},{"method":"GET","path":"/api/v1/ekyc/enhance/status/{jobId}","description":"보정 상태 조회. progress: 0.0~1.0","category":"eKYC Enhance","authentication":"API Key (X-API-Key header)","requestParams":[{"name":"jobId","paramType":"path","required":true,"description":"보정 Job ID","example":"ekyc-enhance-20260308_aBcDeFgH"}],"responseExample":"{\"jobId\": \"ekyc-enhance-20260308_aBcDeFgH\", \"status\": \"completed\", \"progress\": 1.0, \"enhancedImageUrl\": \"https://...\", \"tilesProcessed\": 2, \"processingTimeMs\": 25000}"},{"method":"GET","path":"/api/v1/ekyc/enhance/image/{jobId}","description":"보정 결과 이미지 다운로드. 완료 시 200(JPEG), 처리 중 202, 실패 시 404. 1시간 유효","category":"eKYC Enhance","authentication":"API Key (X-API-Key header)","requestParams":[{"name":"jobId","paramType":"path","required":true,"description":"보정 Job ID","example":"ekyc-enhance-20260308_aBcDeFgH"}],"responseExample":"Binary JPEG image (Content-Type: image/jpeg)"},{"method":"POST","path":"/api/v1/ekyc/analyze-quality","description":"이미지 품질 분석 (밝기, 대비, 선명도). AI 보정 없이 품질만 측정","category":"eKYC Enhance","authentication":"API Key (X-API-Key header)","requestParams":[{"name":"image","paramType":"file","required":true,"description":"신분증 이미지 (JPG)","example":null}],"responseExample":"{\"brightness\": 0.52, \"contrast\": 0.28, \"sharpness\": 125.3, \"overallScore\": 0.78, \"isBlurry\": false, \"bucketKey\": \"B:med_C:med_S:high\", \"recommendations\": []}"},{"method":"POST","path":"/api/v1/ekyc/perspective-crop","description":"투시 보정 (카드 영역 크롭). 4꼭짓점 자동 감지 또는 수동 지정","category":"eKYC Enhance","authentication":"API Key (X-API-Key header)","requestParams":[{"name":"image","paramType":"file","required":true,"description":"촬영된 원본 이미지","example":null},{"name":"corners","paramType":"form","required":false,"description":"4꼭짓점 JSON [[x1,y1],[x2,y2],[x3,y3],[x4,y4]]. 없으면 자동 감지","example":null},{"name":"output_width","paramType":"form","required":false,"description":"출력 폭 (기본 1280)","example":"1280"},{"name":"output_height","paramType":"form","required":false,"description":"출력 높이 (기본 807)","example":"807"}],"responseExample":"{\"success\": true, \"detectedCorners\": [[548,1030],[2385,1030],[2396,2172],[571,2195]], \"cardType\": \"jumin\", \"confidence\": 0.92, \"rotationAngle\": 0.5, \"processingTimeMs\": 450}"},{"method":"POST","path":"/api/v1/ekyc/ocr","description":"신분증 OCR 텍스트 추출. 필드별 크롭 → 다중 전처리 → Tesseract","category":"eKYC Enhance","authentication":"API Key (X-API-Key header)","requestParams":[{"name":"image","paramType":"file","required":true,"description":"투시 보정된 신분증 이미지 (1280x807)","example":null},{"name":"doc_type","paramType":"form","required":true,"description":"신분증 유형: jumin, alien, driver","example":"jumin"},{"name":"fields","paramType":"form","required":false,"description":"추출할 필드 (콤마 구분). 기본: 전부","example":"name,jumin_full"}],"responseExample":"{\"docType\": \"jumin\", \"fields\": {\"name\": {\"text\": \"홍길동\", \"confidence\": 0.95, \"bbox\": [282,162,730,259]}, \"jumin_full\": {\"text\": \"900101-1234567\", \"confidence\": 0.88, \"bbox\": [282,258,794,355]}}, \"overallConfidence\": 0.89, \"processingTimeMs\": 1500}"},{"method":"POST","path":"/api/v1/ekyc/enhance-pipeline","description":"통합 파이프라인 (투시보정+품질분석+OCR+AI보정). 원본 이미지만 보내면 전체 처리","category":"eKYC Enhance","authentication":"API Key (X-API-Key header)","requestParams":[{"name":"image","paramType":"file","required":true,"description":"원본 또는 투시 보정 이미지","example":null},{"name":"doc_type","paramType":"form","required":false,"description":"신분증 유형. 없으면 자동 감지","example":"jumin"},{"name":"privacy_regions","paramType":"form","required":false,"description":"민감영역 좌표 JSON","example":null},{"name":"skip_ocr","paramType":"form","required":false,"description":"OCR 스킵 (기본 false)","example":"false"},{"name":"skip_enhance","paramType":"form","required":false,"description":"AI 보정 스킵 (기본 false)","example":"false"},{"name":"skip_crop","paramType":"form","required":false,"description":"투시 보정 스킵 (기본 false)","example":"true"},{"name":"callback_url","paramType":"form","required":false,"description":"비동기 콜백 URL","example":null}],"responseExample":"{\"success\": true, \"jobId\": \"ekyc-pipeline-20260308_aBcDeFgH\", \"steps\": {\"perspectiveCrop\": {\"success\": true}, \"qualityAnalysis\": {\"success\": true, \"before\": {\"overallScore\": 0.68}}, \"ocr\": {\"success\": true, \"overallConfidence\": 0.89}, \"enhance\": {\"success\": true, \"after\": {\"overallScore\": 0.91}}}, \"totalTimeMs\": 27000, \"estimatedCostUsd\": 0.24}"},{"method":"GET","path":"/api/v1/jobs","description":"Job 목록 조회","category":"Jobs & Logs","authentication":"Cookie (test_auth)","requestParams":[{"name":"job_id","paramType":"query","required":false,"description":"특정 Job ID 조회 (지정 시 단일 Job 반환)","example":"caric_20251118_pUD5ogl"},{"name":"limit","paramType":"query","required":false,"description":"최대 조회 개수. 기본: 100","example":"100"},{"name":"status","paramType":"query","required":false,"description":"상태 필터: processing, completed, failed","example":"completed"},{"name":"prompt","paramType":"query","required":false,"description":"프롬프트 텍스트 검색 (부분 일치)","example":"caricature"},{"name":"from","paramType":"query","required":false,"description":"시작 시간 (YYYY-MM-DDTHH:mm)","example":"2026-02-01T00:00"},{"name":"to","paramType":"query","required":false,"description":"종료 시간 (YYYY-MM-DDTHH:mm)","example":"2026-02-14T23:59"}],"responseExample":"{\"total\": 1, \"jobs\": [{\"id\": \"caric_xxx\", \"status\": \"completed\", \"model\": \"gemini-2.5-flash-image\", \"prompt\": \"...\", \"generatedAt\": \"2026-02-07T09:50:00Z\", \"imageUrl\": \"https://...\", \"processingTime\": 3.5, \"actualCost\": 0.039}]}"},{"method":"GET","path":"/api/v1/logs","description":"시스템 로그 조회","category":"Jobs & Logs","authentication":"Cookie (test_auth)","requestParams":[{"name":"limit","paramType":"query","required":false,"description":"최대 조회 개수","example":"50"}],"responseExample":"{\"total\": 1, \"logs\": [{\"timestamp\": \"...\", \"level\": \"info\", \"message\": \"...\"}]}"},{"method":"POST","path":"/api/v1/admin/keys","description":"새 API 키 생성","category":"Admin","authentication":"Cookie (test_auth)","requestParams":[{"name":"name","paramType":"json","required":true,"description":"API 키 이름","example":"my-app-key"},{"name":"description","paramType":"json","required":false,"description":"API 키 설명","example":"Production app key"}],"responseExample":"{\"id\": \"key_xxx\", \"key\": \"sk-xxx\", \"name\": \"my-app-key\", \"createdAt\": \"2026-02-07T00:00:00Z\"}"},{"method":"GET","path":"/api/v1/admin/keys","description":"모든 API 키 목록 조회","category":"Admin","authentication":"Cookie (test_auth)","requestParams":[],"responseExample":"{\"keys\": [{\"id\": \"key_xxx\", \"name\": \"my-app-key\", \"status\": \"active\", \"createdAt\": \"...\"}]}"},{"method":"DELETE","path":"/api/v1/admin/keys/{key_id}","description":"API 키 폐기","category":"Admin","authentication":"Cookie (test_auth)","requestParams":[{"name":"key_id","paramType":"path","required":true,"description":"폐기할 API 키 ID","example":"key_xxx"}],"responseExample":"{\"success\": true, \"message\": \"API key revoked\"}"},{"method":"POST","path":"/api/v1/admin/keys/{key_id}/regenerate","description":"API 키 재생성","category":"Admin","authentication":"Cookie (test_auth)","requestParams":[{"name":"key_id","paramType":"path","required":true,"description":"재생성할 API 키 ID","example":"key_xxx"}],"responseExample":"{\"id\": \"key_xxx\", \"key\": \"sk-new-xxx\", \"regeneratedAt\": \"2026-02-07T00:00:00Z\"}"},{"method":"GET","path":"/api/v1/admin/usage","description":"API 사용량 조회","category":"Admin","authentication":"Cookie (test_auth)","requestParams":[{"name":"key_id","paramType":"query","required":false,"description":"특정 API 키의 사용량만 조회","example":"key_xxx"},{"name":"from","paramType":"query","required":false,"description":"시작 시간 (YYYY-MM-DDTHH:mm)","example":"2026-02-01T00:00"},{"name":"to","paramType":"query","required":false,"description":"종료 시간 (YYYY-MM-DDTHH:mm)","example":"2026-02-14T23:59"}],"responseExample":"{\"usage\": [{\"date\": \"2026-02-07\", \"endpoint\": \"/api/v1/caricature/generate\", \"count\": 42, \"totalCost\": 1.638}]}"},{"method":"GET","path":"/api/v1/admin/usage/summary","description":"API 사용량 요약 통계","category":"Admin","authentication":"Cookie (test_auth)","requestParams":[],"responseExample":"{\"totalRequests\": 1234, \"totalCost\": 48.52, \"byEndpoint\": {\"caricature/generate\": 500, \"text-to-image/generate\": 300}}"},{"method":"GET","path":"/health","description":"서버 헬스체크","category":"System","authentication":"None","requestParams":[],"responseExample":"{\"status\": \"ok\"}"}],"errorCodes":[{"code":"INVALID_API_KEY","httpStatus":401,"description":"유효하지 않거나 누락된 API 키"},{"code":"INVALID_REQUEST","httpStatus":400,"description":"누락되거나 잘못된 파라미터"},{"code":"JOB_NOT_FOUND","httpStatus":404,"description":"Job ID를 찾을 수 없음"},{"code":"IMAGE_EXPIRED","httpStatus":410,"description":"이미지 TTL이 만료됨"},{"code":"AI_API_ERROR","httpStatus":502,"description":"업스트림 AI 프로바이더 오류"},{"code":"INTERNAL_ERROR","httpStatus":500,"description":"내부 서버 오류"}],"rateLimits":{"perMinute":60,"perDay":10000,"description":"API 키별 기본 Rate Limit. Admin API로 키별 커스텀 가능"}}