해석 API
어떤 코드든 정규화하고 변형, 소스, 공유 카드, 출처, 스트림을 받으세요.
/resolve는 이 코드와 우리가 실제로 아는 것을 답합니다: /movie는 응답한 첫
제공업체만 반환하지만, 이 엔드포인트들은 모든 소스를 보고 의견 차이를 남깁니다.
abp002, ABP-002, ABP-2 붙여넣기, 모든 소스, 공유 카드와 스트림 맵에 쓰세요.
| 엔드포인트 | 반환 | 1,000회 호출당 |
|---|---|---|
GET /resolve | 정규 코드, 변형, 소스, 링크, 인라인 카드 | $1.20 |
POST /resolve/batch | 최대 100개 코드의 발견 여부 | 고유 코드 10개 단위로 시작된 그룹당 $0.40 |
GET /resolve/compare | 두 작품 나란히 비교 | $0.40 |
GET /resolve/provenance | 필드별 소스와 신뢰도 | $0.40 |
GET /resolve/streams | 스트림, 샘플, 마그넷 가용성 | $0.40 |
GET /resolve
표기를 정규 코드로 바꾸고 모든 변형, 소스, /movie 링크, 1200×630 카드를 반환합니다.
| 매개변수 | 타입 | 필수 | 의미 |
|---|---|---|---|
q | string | 예 | 해석할 코드 또는 표기. 최소 2자. |
format | png, jpg 또는 svg | 아니요 | 카드 인코딩. 기본값은 png. |
curl -s 'https://api.javinfo.dev/resolve?q=abp002&format=jpg' \
-H "x-javinfo-key: jvi_your_key_here"{
"input": "abp002",
"code": "ABP-002",
"shareSlug": "85150B9G60S0M",
"found": true,
"variants": ["ABP-002", "ABP002"], // 7 total
"contentIdGuess": "118abp00002",
"sources": ["fanza", "javdatabase"], // 6 total
"link": "/movie?q=ABP-002",
"card": {
"format": "jpg",
"mime": "image/jpeg",
"dataUri": "data:image/jpeg;base64,…"
}
}카드는 card.dataUri에 인라인되어 응답이 큽니다. 한 작품의 전체 응답은 png 약 1.1 MB,
svg 약 900 KB, jpg 약 180 KB였습니다. 크기가 중요하면 png보다 약 6배 작은 손실
압축 jpg를 고르세요. 예시의 base64는 잘랐습니다. dataUri는 완전한 data: URI로
<img src>에 바로 쓸 수 있습니다.
| 필드 | 의미 |
|---|---|
input | 보낸 문자열 그대로. |
code | 정규 코드. |
variants | 같은 작품을 가리키는 모든 표기, 정규에 가까운 순서. |
sources | 작품을 실은 소스의 공개 id. |
contentIdGuess | 스토어프론트 인덱스에 있으면 DMM 콘텐츠 id, 없으면 null. |
link | 같은 작품의 API 경로, /movie?q=<code>. https://api.javinfo.dev 기준 상대 경로이며 x-javinfo-key 헤더가 필요합니다. |
card | data URI 형식의 1200×630 카드, 또는 null. |
found | 200이면 true. 없으면 404. |
shareSlug | 정규 코드에 대한 체크섬 slug. |
카드에는 코드, 영어 제목(길면 줄이고 없으면 코드), 최대 세 명의 출연진과 스튜디오, 장르 칩
최대 네 개, 알려진 경우 평점, 러닝타임, 출시일, 마그넷 수가 표시됩니다. 스트림이 있으면
STREAMABLE 배지가 붙고, 오른쪽 재킷 뒤로 커버를 흐리게 깝니다. 렌더링할 수 없으면
null이므로 선택 사항으로 다루고 메타데이터는 유지하세요.
아무것도 일치하지 않는 코드는 빈 카드가 아니라 404입니다:
{
"defined": false,
"code": "NOT_FOUND",
"status": 404,
"message": "no title found for \"ZZZZ-99999\""
}POST /resolve/batch
한 요청으로 최대 100개 코드를 확인합니다. 목록 정리나 카탈로그 대조에 쓰세요.
| 본문 필드 | 타입 | 필수 | 의미 |
|---|---|---|---|
codes | string 배열 | 예 | 비어 있지 않은 문자열 1~100개. |
curl -s -X POST 'https://api.javinfo.dev/resolve/batch' \
-H "x-javinfo-key: jvi_your_key_here" \
-H 'content-type: application/json' \
-d '{"codes":["ABP-002","beb001","ZZZZ-99999"]}'{
"count": 3,
"found": 2,
"results": [
{ "input": "ABP-002", "code": "ABP-002", "found": true },
{ "input": "beb001", "code": "BEB-001", "found": true },
{ "input": "ZZZZ-99999", "code": "ZZZZ-99999", "found": false }
]
}찾지 못한 코드는 404가 아니라 정상 200 안의 found: false입니다. code에는 가장 나은
정규 추측값이 들어갑니다. count는 중복 제거 후 코드 수, found는 적중 수입니다.
코드는 세기 전에 앞뒤 공백을 제거하고 중복을 없앱니다. "ABP-002"와 " ABP-002 "는 한
자리로 results에 한 번 나옵니다. 일치는 공백 제거 후 정확히 하므로 abp-002와
ABP-002는 두 자리입니다.
빈 codes 배열, 100개를 넘는 코드, 빈 문자열은 400입니다:
{
"defined": false,
"code": "BAD_REQUEST",
"status": 400,
"message": "Input validation failed",
"data": {
"issues": [
{
"origin": "array",
"code": "too_small",
"minimum": 1,
"inclusive": true,
"path": ["codes"],
"message": "Too small: expected array to have >=1 items"
}
]
}
}같은 형태가 다른 검증 실패를 포괄하고 issues만 다릅니다.
GET /resolve/compare
두 작품의 핵심 카드, 공유 필드, 유사도 점수를 나란히 놓습니다.
| 매개변수 | 타입 | 필수 | 의미 |
|---|---|---|---|
a | string | 예 | 첫 번째 코드. 최소 2자. |
b | string | 예 | 두 번째 코드. 최소 2자. |
curl -s 'https://api.javinfo.dev/resolve/compare?a=SSIS-001&b=ABP-002' \
-H "x-javinfo-key: jvi_your_key_here"{
"a": {
"input": "SSIS-001",
"code": "SSIS-001",
"shareSlug": "AD9MJMSD60R32E",
"found": true,
"variants": [
"SSIS-001",
"SSIS001",
"…"
],
"contentIdGuess": "ssis00001",
"sources": [
"fanza",
"javdatabase",
"javlibrary",
"javbus",
"missav",
"sextb"
],
"link": "/movie?q=SSIS-001"
},
"b": {
"input": "ABP-002",
"code": "ABP-002",
"shareSlug": "85150B9G60S0M",
"found": true,
"variants": [
"ABP-002",
"ABP002",
"…"
],
"contentIdGuess": "118abp00002",
"sources": [
"fanza",
"javdatabase",
"javlibrary",
"javbus",
"missav",
"sextb"
],
"link": "/movie?q=ABP-002"
},
"shared": {
"actresses": [],
"categories": [],
"maker": null
},
"similarity": 0.05
}각 쪽은 카드를 뺀 /resolve와 같은 형태이고 sources와 contentIdGuess도 /resolve와
같습니다.
shared에는 actresses와 categories의 대소문자 무시 교집합이 들어가고, maker는
제작사 문자열이 정확히 같을 때만 채워집니다.
similarity는 0~1 혼합값으로, 공유 출연자(0.34)와 카테고리(0.26)가 중심이고 같은
제작사(0.1), 재생 시간(0.06), 출시일 근접성(0.06)이 더해져 소수점 셋째 자리에서
반올림됩니다. 어느 코드든 찾지 못하면 그쪽은 found: false, shared는 비고 similarity는
0입니다. 이 엔드포인트는 절대 404를 반환하지 않습니다.
GET /resolve/provenance
각 필드의 출처, API의 소스 신뢰도, 다른 소스의 주장을 보여 줍니다.
| 매개변수 | 타입 | 필수 | 의미 |
|---|---|---|---|
q | string | 예 | 해석할 코드 또는 표기. 최소 2자. |
curl -s 'https://api.javinfo.dev/resolve/provenance?q=ABP-002' \
-H "x-javinfo-key: jvi_your_key_here"{
"code": "ABP-002",
"found": true,
"sources": ["fanza", "javbus"], // 6 total, alphabetical
"fields": {
"title": {
"value": "NEW TOKYO Style 01 - Aikarin",
"source": "fanza",
"confidence": 1,
"candidates": [ // 6 total, trust order
{ "source": "fanza", "value": "NEW TOKYO Style 01 - Aikarin" },
{ "source": "javdatabase", "value": "NEW TOKYO Style 01 - Aikarin" }
]
},
"titleJa": {
"value": "NEW TOKYO流儀 01 あいかりん",
"source": "javlibrary",
"confidence": 0.8,
"candidates": [ // 4 total
{ "source": "javlibrary", "value": "NEW TOKYO流儀 01 あいかりん" },
{ "source": "javbus", "value": "NEW TOKYO流儀 01 あいかりん" }
]
},
"rating": {
"value": 8.1,
"source": "javlibrary",
"confidence": 0.8,
"candidates": [{ "source": "javlibrary", "value": 8.1 }]
}
// releaseDate, runtimeMins, maker, label, series, categories,
// actresses and cover follow the same shape
},
"data": {
"title": "NEW TOKYO Style 01 - Aikarin",
"titleJa": "NEW TOKYO流儀 01 あいかりん",
"rating": 8.1
// the merged value for every field above
}
}fields는 title, titleJa, releaseDate, runtimeMins, maker, label, series,
categories, actresses, cover, rating을 포괄합니다.
스칼라는 최고 가중치 소스에서 가져옵니다. categories와 actresses 같은 배열은 소스 간
합집합이며 대체하지 않습니다. candidates는 값을 제시한 모든 소스를 가장 나은 순서로
나열해 의견 차이를 보여 줍니다.
confidence는 승리한 소스 가중치를 이 응답 최고 가중치로 나눈 값입니다. 최상위 소스는 1이고
나머지는 더 낮습니다. 가중치는 스토어프론트 1, javdatabase 0.85, javlibrary 0.8, javbus
0.7, missav 0.6, sextb 0.55 순입니다. sources는 알파벳순, candidates는 신뢰
순서입니다.
알 수 없는 코드는 GET /resolve와 같은 본문의 404입니다.
GET /resolve/streams
시청·다운로드 경로를 반환합니다: HLS 스트림, 샘플, 마그넷, 자막, 갤러리 크기.
| 매개변수 | 타입 | 필수 | 의미 |
|---|---|---|---|
q | string | 예 | 해석할 코드 또는 표기. 최소 2자. |
curl -s 'https://api.javinfo.dev/resolve/streams?q=ABP-002' \
-H "x-javinfo-key: jvi_your_key_here"{
"code": "ABP-002",
"found": true,
"playback": "hls",
"availability": {
"magnets": 47,
"stream": true,
"sample": false,
"trailer": false,
"gallery": 0,
"subtitles": [],
"uncensored": false,
"score": 0.7
},
"streams": {
"master": "https://surrit.com/c511196b-b4f8-47bf-a6b0-64ba625fc2a4/playlist.m3u8",
"variants": [
"https://surrit.com/c511196b-b4f8-47bf-a6b0-64ba625fc2a4/1280x720/video.m3u8",
"https://surrit.com/c511196b-b4f8-47bf-a6b0-64ba625fc2a4/842x480/video.m3u8"
]
},
"sampleUrl": null,
"galleryCount": 106,
"sources": ["fanza", "javdatabase"] // 6 total
}playback은 한 줄 답변입니다. 스트림이 있으면 hls, 마그넷이 있으면 magnet, 샘플이나
예고편만 있으면 sample, 그 밖에는 none입니다.
availability 세부 정보:
| 필드 | 의미 |
|---|---|
magnets | 모든 소스에 걸친 서로 다른 마그넷 정보 해시. |
stream | HLS 마스터가 있음. |
sample | 샘플 클립이나 예고편이 있음. |
trailer | 예고편만 해당. |
gallery | 미디어용으로 선택한 소스의 갤러리 이미지 수. |
subtitles | 메타데이터에서 감지한 자막 언어. 현재는 zh만 태그됨. |
uncensored | 메타데이터가 작품을 무검열로 표시함. |
score | 0~1 완전성: 마그넷 0.35, 스트림 0.35, 샘플 0.15, 갤러리 0.1, 자막 0.05. |
streams는 HLS가 있으면 {master, variants}, 없으면 null입니다. master는 플레이어에
넘길 재생 목록, variants는 해상도별 재생 목록입니다. sampleUrl은 샘플 클립 주소,
galleryCount는 소스 전반에서 본 가장 큰 갤러리 수입니다.
알 수 없는 코드는 GET /resolve와 같은 본문의 404입니다.
비용
새 200만 청구됩니다. 캐시 적중(X-Cache: HIT), 4xx 응답, 성능 저하
답변(X-Degraded)은 무료입니다. /resolve, compare, provenance는 1시간, streams는
15분 캐시하며 Batch는 캐시하지 않습니다.
GET /resolve는 카드를 렌더링하므로 1,000회 호출당 $1.20입니다. 다른 resolve 엔드포인트는
1,000회 호출당 $0.40입니다.
Batch는 공백 제거와 중복 제거 후 코드를 10개 단위 그룹으로 묶어 가격을 매깁니다:
| 고유 코드 | 1,000회 호출당 |
|---|---|
| 1–10 | $0.40 |
| 11–20 | $0.80 |
| 21–30 | $1.20 |
| 100 | $4.00 |
상태 코드
| 엔드포인트 | 코드 |
|---|---|
GET /resolve | 200, 400, 401, 402, 404, 429 |
POST /resolve/batch | 200, 400, 401, 402, 429 |
GET /resolve/compare | 200, 400, 401, 402, 429 |
GET /resolve/provenance | 200, 400, 401, 402, 404, 429 |
GET /resolve/streams | 200, 400, 401, 402, 404, 429 |
2자 미만 q, 알 수 없는 format, 위 batch 본문 실패는 400입니다.
모든 엔드포인트가 반환할 수 있는 오류
키가 없는 경우와 잘못된 키 모두 401이며 본문이 다릅니다.
# No key
curl -s 'https://api.javinfo.dev/resolve?q=ABP-002'{
"defined": false,
"code": "UNAUTHORIZED",
"status": 401,
"message": "Unauthorized"
}# Bad key
curl -s 'https://api.javinfo.dev/resolve?q=ABP-002' \
-H "x-javinfo-key: jvi_not_a_real_key"{ "error": "invalid api key" }402는 잔액이 호출 가격보다 낮다는 뜻입니다. 청구되지 않고 자동화 클라이언트용 힌트로
Retry-After: 3600이 붙습니다.
{
"defined": false,
"code": "PAYMENT_REQUIRED",
"status": 402,
"message": "insufficient balance"
}429는 계정당 분당 상한입니다. Retry-After에 기다릴 초 수가 담깁니다.
{ "error": "rate limit exceeded" }속도 제한 및 요금과 오류를 참조하세요. 작업별 참조는
/docs/api/discovery/resolve에 있습니다.