Resolución API
Normaliza cualquier forma de escribir un código y obtén variantes, fuentes, tarjeta, procedencia y streams.
/resolve dice qué es un código y qué dice cada fuente. /movie devuelve el
primer proveedor que responde; estos endpoints consultan todas las fuentes y conservan las
discrepancias.
Úsalos para normalizar abp002, ABP-002 o ABP-2, listar todas las fuentes de un título, o
una tarjeta para compartir o un mapa de streams en una llamada.
| Endpoint | Devuelve | Por 1000 llamadas |
|---|---|---|
GET /resolve | Código canónico, variantes, fuentes, enlace, tarjeta en línea | $1.20 |
POST /resolve/batch | Encontrado o no encontrado para hasta 100 códigos | $0.40 por grupo iniciado de 10 códigos únicos |
GET /resolve/compare | Dos títulos lado a lado | $0.40 |
GET /resolve/provenance | Fuente y confianza por campo | $0.40 |
GET /resolve/streams | Disponibilidad de stream, muestra y magnet | $0.40 |
GET /resolve
Normaliza cualquier forma a un código canónico y devuelve todo lo asociado: variantes,
fuentes, un enlace a /movie y una tarjeta de 1200×630.
| Parámetro | Tipo | Obligatorio | Significado |
|---|---|---|---|
q | string | sí | El código o la forma de escribirlo que hay que resolver. Al menos 2 caracteres. |
format | png, jpg o svg | no | Codificación de la tarjeta. Predeterminado 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,…"
}
}La tarjeta va en card.dataUri, así que la respuesta es grande: unos 1,1 MB con png
(predeterminado), 900 KB con svg y 180 KB con jpg. Elige jpg cuando importe el tamaño:
un raster con pérdida unas seis veces más pequeño que png. La carga base64 está recortada en
el ejemplo; dataUri es un URI data: completo, para un <img src>.
| Campo | Significado |
|---|---|
input | La cadena que enviaste, sin cambios. |
code | El código canónico. |
variants | Cada forma de escribir que identifica el mismo título, de la más canónica a la menos. |
sources | Ids públicos de las fuentes que listan el título. |
contentIdGuess | Id de contenido de DMM cuando el índice de la tienda lo tiene; si no, null. |
link | Ruta de la API para el mismo título, /movie?q=<code>. Es relativa a https://api.javinfo.dev y necesita tu cabecera x-javinfo-key. |
card | La tarjeta de 1200×630 como URI de datos, o null. |
found | true en un 200. Un fallo es un 404. |
shareSlug | Slug con suma de comprobación para el código canónico. |
La tarjeta muestra el código, el título en inglés (acortado o el código si no hay), hasta tres
nombres del reparto y el estudio, hasta cuatro etiquetas de género y, cuando se conocen,
valoración, duración, fecha de lanzamiento y magnets. Una insignia STREAMABLE marca el
stream. La carátula va a la derecha sobre una copia desenfocada de la portada. Es null si no
hay render: trátala como opcional y conserva los metadatos.
Un código sin coincidencias es 404, no una tarjeta vacía:
{
"defined": false,
"code": "NOT_FOUND",
"status": 404,
"message": "no title found for \"ZZZZ-99999\""
}POST /resolve/batch
Comprueba hasta 100 códigos en una solicitud: limpia la lista de un usuario o coteja tu catálogo sin 100 llamadas secuenciales.
| Campo del cuerpo | Tipo | Obligatorio | Significado |
|---|---|---|---|
codes | array de strings | sí | De 1 a 100 cadenas no vacías. |
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 }
]
}Un fallo es found: false dentro de un 200 normal, no un 404; code lleva la mejor
suposición canónica. count son los códigos tras deduplicar; found, cuántos acertaron.
Los códigos se recortan y deduplican antes de contar. "ABP-002" y " ABP-002 " ocupan una
ranura y aparecen una vez en results. La coincidencia es exacta tras el recorte: abp-002 y
ABP-002 son dos ranuras.
Un array codes vacío, más de 100 códigos o una cadena vacía son un 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"
}
]
}
}La misma forma cubre los demás fallos, con otra entrada en issues.
GET /resolve/compare
Dos títulos lado a lado: ficha básica de cada uno, campos compartidos y puntuación de similitud.
| Parámetro | Tipo | Obligatorio | Significado |
|---|---|---|---|
a | string | sí | Primer código. Al menos 2 caracteres. |
b | string | sí | Segundo código. Al menos 2 caracteres. |
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
}Cada lado tiene la forma de /resolve, sin tarjeta. sources lista las fuentes que
coinciden; contentIdGuess es el id de contenido de DMM cuando el índice de la tienda lo
tiene, igual que en /resolve.
shared contiene la intersección sin distinguir mayúsculas de actresses y categories;
maker solo se rellena si ambos títulos llevan exactamente la misma cadena de maker.
similarity es una mezcla de 0 a 1, sobre todo actrices compartidas (0.34) y categorías
(0.26), más el mismo maker (0.1), duración (0.06) y cercanía de fecha (0.06), redondeada a 3
decimales. Si falta un código, ese lado es found: false, shared queda vacío y similarity
es 0. Nunca 404.
GET /resolve/provenance
Muestra la fuente de cada campo, cuánto confía la API en ella y qué dijeron las demás.
| Parámetro | Tipo | Obligatorio | Significado |
|---|---|---|---|
q | string | sí | El código o la forma de escribirlo que hay que resolver. Al menos 2 caracteres. |
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 cubre title, titleJa, releaseDate, runtimeMins, maker, label, series,
categories, actresses, cover y rating.
Los escalares van a la fuente de mayor peso; arrays como categories y actresses se unen,
no se reemplazan. candidates lista cada fuente que ofreció un valor, mejor primero, así que
las discrepancias quedan visibles.
confidence es el peso ganador dividido por el mejor de la respuesta: 1 para la fuente
principal, menos para el resto. Pesos, de mayor a menor: tiendas 1, javdatabase 0.85,
javlibrary 0.8, javbus 0.7, missav 0.6, sextb 0.55. sources va alfabético;
candidates, por confianza.
Código desconocido: 404 con el cuerpo de GET /resolve.
GET /resolve/streams
Devuelve dónde ver o descargar un título: streams HLS, muestras, imanes, subtítulos y tamaño de galería.
| Parámetro | Tipo | Obligatorio | Significado |
|---|---|---|---|
q | string | sí | El código o la forma de escribirlo que hay que resolver. Al menos 2 caracteres. |
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 responde en una línea: hls con stream, si no magnet con imanes, si no sample
con solo muestra o tráiler, si no none.
availability añade detalle:
| Campo | Significado |
|---|---|
magnets | Infohashes de imán distintos en todas las fuentes. |
stream | Hay un master HLS presente. |
sample | Hay un clip de muestra o un tráiler presente. |
trailer | Un tráiler específicamente. |
gallery | Número de imágenes de la galería de la fuente elegida para medios. |
subtitles | Idiomas de subtítulos detectados en los metadatos. Hoy solo zh está etiquetado. |
uncensored | Los metadatos marcan el título como sin censura. |
score | Completitud de 0 a 1: imanes 0.35, stream 0.35, muestra 0.15, galería 0.1, subtítulos 0.05. |
streams es {master, variants} con HLS, si no null. master es la lista para el
reproductor; variants, las listas por resolución. sampleUrl es el clip de muestra si
existe; galleryCount, el mayor visto entre fuentes.
Código desconocido: 404 con el cuerpo de GET /resolve.
Coste
Solo se cobra un 200 nuevo. Aciertos de caché (X-Cache: HIT), respuestas 4xx y respuestas
degradadas (X-Degraded) gratis. Resolve, compare y provenance cachean 1 hora; streams, 15
minutos. Batch no cachea.
GET /resolve cuesta $1.20 por 1000 llamadas porque genera la tarjeta; los demás endpoints, $0.40
por 1000 llamadas.
Batch factura los códigos que quedan tras recortar y deduplicar, en grupos iniciados de 10:
| Códigos únicos | Por 1000 llamadas |
|---|---|
| 1–10 | $0.40 |
| 11–20 | $0.80 |
| 21–30 | $1.20 |
| 100 | $4.00 |
Códigos de estado
| Endpoint | Códigos |
|---|---|
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 |
Un q de menos de 2 caracteres, un format desconocido y los fallos de batch de arriba son
400.
Errores comunes
Sin clave o con clave incorrecta: 401, con cuerpos distintos.
# 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 significa que el saldo está por debajo del precio de la llamada. No se cobra nada;
Retry-After: 3600 es una pista para clientes automatizados.
{
"defined": false,
"code": "PAYMENT_REQUIRED",
"status": 402,
"message": "insufficient balance"
}429 es el tope por cuenta y minuto; Retry-After da los segundos de espera.
{ "error": "rate limit exceeded" }Cuenta: Límites de tasa y facturación y Errores.
Referencia generada: /docs/api/discovery/resolve.