API de detección de imágenes con IA
Documentación completa para integrar la API de detección de imágenes con IA de TruthScan en sus aplicaciones.
Pruébelo sin código visitando nuestro endpoint FastAPI: https://detect-image.truthscan.com/docs
¿Prefiere una biblioteca de cliente? Use nuestros SDKs oficiales en lugar de llamar directamente a la API REST. Ver Documentación de SDKs de Cliente
Pricing & credits
Each successful image detection consumes credits. Bulk ZIP uploads bill only images that complete analysis; skipped or failed files are not charged.
Check your balance with GET /check-user-credits. View pricing plans
Autenticación
TruthScan utiliza claves de API para permitir el acceso. Puede obtener su clave en la parte superior de la página del portal para desarrolladores.
TruthScan espera que la clave de API se incluya en las solicitudes al servidor en un cuerpo JSON como el siguiente (salvo que un endpoint documente solo autenticación por cabecera, p. ej. check-user-credits):
{
"key": "YOUR API KEY GOES HERE"
}Debe sustituir YOUR API KEY GOES HERE por su clave de API personal.
Límites de velocidad
La API aplica un cupo de solicitudes por minuto para cada clave de API. Los endpoints de escritura cuestan más que los de lectura. El cupo por defecto es de 60 solicitudes por minuto — contáctenos si necesita un cupo mayor.
Pesos por endpoint
Cada llamada descuenta su peso de su cupo por minuto:
| Endpoint | Tipo | Peso |
|---|---|---|
| POST /detect | Escritura | 1 |
| POST /bulk-upload | Escritura | 1 |
| GET /get-presigned-url | Lectura | 0.2 |
| GET /check-user-credits | Lectura | 0.2 |
| POST /heatmap/{id} | Lectura | 0.2 |
| POST /preview/{id} | Lectura | 0.2 |
| POST /query | Lectura | Sin límite |
| GET /health | Lectura | Sin límite |
Ejemplo: con un cupo de 60/minuto puede enviar hasta 60 llamadas de escritura, hasta ~300 llamadas de lectura, o cualquier mezcla cuyo total ponderado se mantenga ≤ 60 por minuto.
Respuesta limitada (HTTP 429)
Cuando supera su cupo por minuto, la API devuelve:
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"
}Cabeceras de respuesta de rate limit
- X-RateLimit-Limit — su cupo por minuto.
- X-RateLimit-Remaining — llamadas restantes en el minuto en curso (tras esta solicitud).
- X-RateLimit-Reset — (solo en 429) segundos hasta que pueda enviar otra solicitud de escritura.
- X-RateLimit-Retry-After — (solo en 429) mismo valor que X-RateLimit-Reset, al estilo Retry-After.
Comportamiento recomendado del cliente
- Vigile X-RateLimit-Remaining en respuestas correctas para regular el ritmo de sus solicitudes.
- Ante un 429, espere al menos X-RateLimit-Retry-After segundos antes de reintentar — use backoff exponencial con jitter.
- Para lotes prefiera POST /bulk-upload (una llamada procesa hasta 50 imágenes) en lugar de muchas /detect en paralelo.
Detector de imágenes con IA
Detect (proceso en 3 pasos)
El flujo de detección de imágenes con IA consta de los siguientes pasos:
- Obtener una URL de carga preautorizada
- Subir la imagen
- Enviar la imagen para la detección
1. Obtener una URL de carga preautorizada
Empiece solicitando una URL preautorizada a la API. Esta URL permite subir el archivo de imagen de forma segura al servidor de almacenamiento.
Formatos de archivo admitidos
JPG, JPEG, PNG, WebP, JFIF, HEIC, HEIF, AVIF, BMP, TIFF, TIF, GIF, SVG, PDF
Nombre de archivo
Elimine los espacios del nombre del archivo de imagen al solicitar una URL preautorizada.
En archivos PDF solo se detectará la primera imagen (flujo de un solo archivo).
Use un nombre de archivo .zip en este endpoint cuando vaya a enviar un ZIP mediante carga masiva.
Parámetros de consulta
- file_name (obligatorio) — Nombre de archivo original; el servidor puede normalizarlo (se ajustan espacios y caracteres no seguros). Use la extensión .zip para carga masiva.
- expiration (opcional) — Duración de la URL preautorizada en segundos (predeterminado: 3600).
GET https://detect-image.truthscan.com/get-presigned-url?file_name=example.jpgEjemplo de solicitud
curl -X GET 'https://detect-image.truthscan.com/get-presigned-url?file_name=example.jpg' \
--header 'apikey: YOUR API KEY GOES HERE'Ejemplo de respuesta
{
"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 es un UUID nuevo generado para esta solicitud de carga (para correlación y registro). El id que use para /detect o /bulk-upload se asigna al enviar esos endpoints salvo que pase un id opcional en /detect.
Respuestas HTTP
Encabezado requerido: apikey: YOUR-API-KEY-GOES-HERE
| Estado | Cuerpo | Cuándo |
|---|---|---|
| 200 | JSON: status, presigned_url, file_path, document_id | Éxito |
| 400 | {"error": "..."} | Tipo de archivo no admitido / parámetros incorrectos |
| 403 | {"error": "..."} | Clave API no válida |
| 404 | {"error": "..."} | Falló la validación de la clave TruthScan |
| 500 | {"error": "..."} | Error del servidor |
2. Subir la imagen
Use la presigned_url proporcionada para subir la imagen mediante una solicitud PUT. Asegúrese de establecer el Content-Type correcto según el formato de la imagen.
Nombre de archivo
Elimine los espacios del nombre del archivo de imagen al subirla.
Establezca Content-Type para que coincida exactamente con la extensión del archivo
- 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
Errores habituales que debe evitar
- No use image/jpg (incorrecto). Use image/jpeg.
- No desajuste archivo y cabecera (p. ej., archivo .png con image/jpeg).
- No cambie la extensión sin actualizar la cabecera (ni al revés).
- No incluya espacios en los nombres de archivo al solicitar o subir.
Ejemplo de solicitud
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'Ejemplos adicionales de carga (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'Límites de tamaño de archivo
- Tamaño mínimo: 1 KB
- Tamaño máximo: 10 MB
Asegúrese de que el formato del archivo se mantenga coherente durante la subida. Una subida correcta devuelve HTTP 200.
Respuesta del PUT en almacenamiento
El paso 2 es un PUT directo al almacenamiento de objetos (URL prefirmada), no a nuestra API. La carga de una imagen y la carga masiva ZIP funcionan igual.
El éxito devuelve HTTP 200 con cuerpo vacío — por diseño. No hay JSON que analizar.
Tras el PUT a presigned_url: considere res.ok (estado 200–299) como éxito. No llame a response.json() en éxito — se espera un cuerpo vacío. Informe errores solo en respuestas distintas de 2xx.
3. Enviar la imagen para la detección con IA
Tras la subida, envíe la imagen para la detección con IA referenciando el file_path del paso anterior. En cargas PDF solo se analizará o detectará la primera imagen.
POST https://detect-image.truthscan.com/detectEjemplo de solicitud
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 es la ruta devuelta en el paso de la URL preautorizada (p. ej. uploads/...). Construya la URL completa con su host de almacenamiento como en el ejemplo.
Parámetros opcionales
id: Cadena UUID opcional. Si se omite, el servidor genera un nuevo id de documento. Si se indica, no debe existir ya; de lo contrario la API devuelve un error.generate_preview: Establezca true para generar una URL de vista previa de la imagen (predeterminado: true). Establezca false para omitir la generación de vista previa.document_type: Tipo de documento (predeterminado: Image).email: Dirección de correo electrónico para el procesamiento.generate_analysis_details: Establezca false para omitir el análisis detallado (predeterminado: true).generate_heatmap: Con false, se omite por completo la generación del mapa de calor (predeterminado: true). Los mapas de calor solo se producen para imágenes clasificadas como IA cuando este valor es true. Las imágenes reales nunca reciben mapa de calor.generate_heatmap_overlayed: Controla cómo se produce la imagen del mapa de calor cuando se genera uno (predeterminado: true). Solo aplica cuando generate_heatmap es true y la imagen está clasificada como generada por IA. Con true, el mapa de calor se mezcla con la imagen original (superposición habitual). Con false, el servicio devuelve un mapa de calor transparente: una imagen RGBA con el mapa de activación en color JET y alfa del modelo, con fondo transparente para poder componerla en su interfaz.generate_heatmap_normalized: Con false, la generación del mapa de calor omite el paso de normalización usado para el mapa de activación (predeterminado: true). Solo aplica cuando generate_heatmap es true y la imagen está clasificada como generada por IA. Úselo junto con generate_heatmap_overlayed para controlar el aspecto del mapa de calor.model: Pista de modelo o enrutamiento (predeterminado: generic). Ejemplos admitidos: generic o instance_id/model (p. ej. my-instance-id/generic) para enviar el trabajo a una cola dedicada de esa instancia. Los instance_id no válidos se rechazan con 400.user_agent: Cadena opcional almacenada con el documento para analítica o soporte.
Validación de flags del mapa de calor
Si generate_heatmap es false, no establezca explícitamente generate_heatmap_overlayed o generate_heatmap_normalized en true. La API devuelve 422 Unprocessable Entity con mensajes como "generate_heatmap_overlayed cannot be true when generate_heatmap is false." o "generate_heatmap_normalized cannot be true when generate_heatmap is false."
Ejemplo de solicitud (mapa de calor habilitado, predeterminado)
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-dev.nyc3.digitaloceanspaces.com/uploads/example.jpg",
"generate_heatmap": true,
"generate_preview": false,
"generate_analysis_details": false,
"model": "generic"
}'Ejemplo de solicitud (mapa de calor deshabilitado)
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-dev.nyc3.digitaloceanspaces.com/uploads/example.jpg",
"generate_heatmap": false,
"generate_preview": false,
"generate_analysis_details": false,
"model": "generic"
}'Solicitud no válida (422)
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-dev.nyc3.digitaloceanspaces.com/uploads/example.jpg",
"generate_heatmap": false,
"generate_heatmap_overlayed": true
}'Ejemplo de respuesta
{
"id": "77565038-9e3d-4e6a-8c80-e20785be5ee9",
"status": "pending"
}La respuesta incluye un id de imagen único para seguir el estado de la detección.
Respuestas HTTP
| Estado | Cuerpo | Cuándo |
|---|---|---|
| 200 | JSON: id, status (típicamente "pending") | Trabajo aceptado — esto es lo que devuelve la API en caso de éxito |
| 400 | {"error": "..."} | Validación (sin URL, archivo no subido, tamaño/tipo, id duplicado, modelo incorrecto, conflicto de flag heatmap, etc.) |
| 403 | {"error": "..."} | Clave no válida / créditos insuficientes |
| 422 | {"error": "..."} | Cuerpo de solicitud no válido (p. ej. generate_heatmap_overlayed true cuando generate_heatmap es false) |
| 500 | {"error": "..."} | Error del servidor |
Cualquier respuesta 2xx cuyo JSON incluya id y status es éxito — no solo HTTP 200. Proxies u otras pilas HTTP pueden devolver 201 o 202 para aceptación asíncrona; valide el cuerpo JSON.
Consultar estado y resultados de la detección
Para comprobar el estado y obtener los resultados, use el endpoint /query con el id de la imagen.
Autenticación: el cuerpo de la solicitud solo incluye id; la API no envía clave de API en esta llamada. Cualquiera que conozca el UUID puede consultar resultados: trate los ids de documento como sensibles si necesita restringir quién puede ver las puntuaciones.
Respuestas HTTP
| Estado | Cuerpo | Cuándo |
|---|---|---|
| 200 | JSON de resultado (imagen única o masivo) | Encontrado |
| 404 | Error detail | Id desconocido |
| 500 | Error detail | Error del servidor |
POST https://detect-image.truthscan.com/queryEjemplo de solicitud
curl -X 'POST' \
'https://detect-image.truthscan.com/query' \
-H 'accept: application/json' \
-H 'Content-Type: application/json' \
-d '{
"id": "IMAGE-ID-GOES-HERE"
}'Ejemplo de respuesta
{
"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/..."
}Ejemplo de respuesta (/query, URLs seguras activadas en la organización)
{
"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"
}Ejemplo de respuesta cuando el análisis está listo
{
"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/..."
}Detalles del resultado
is_valid: Indica si el archivo de imagen es válido (true/false).detection_step: Fase en la que finalizó la detección: 1 = solo metadatos; 2 = metadatos y ocr; 3 = metadatos, ocr y ml_model.final_result: Determinación global (p. ej. "AI Generated", "Real", "Digitally Edited", "AI Edited").confidence: Puntuación de confianza de la detección.metadata: Información extraída de los metadatos de la imagen con ExifTool y Pillow.metadata_basic_source: Puede indicar si la imagen se capturó con un modelo concreto de cámara móvil, se generó con una herramienta de IA o se modificó con software de edición fotográfica.ocr: Resultado de detección de marcas de agua bajo el nombre histórico ocr. Array de dos elementos [label, score]: label es una clase de marca de agua detectada (p. ej. "Gemini") u "OCR did not detect AI"; score está en escala 0–100 (o 0 si no hay certeza). Se resume en warnings cuando hay label.ml_model: Resultados del modelo de aprendizaje automático.warnings: Array opcional de objetos de advertencia heterogéneos (tipo blur_dark, watermark, screen_recapture, etc.). Puede estar vacío u omitirse.preview_url: URL de la imagen de vista previa si generate_preview era true. Puede ser almacenamiento directo o, con URLs seguras, una ruta de API como https://<api-host>/preview/<document_id>.heatmap_status: pending, ready o failed. Se omite cuando la imagen no es generada por IA o cuando generate_heatmap era false al enviar. La generación del mapa de calor es asíncrona y solo se ejecuta para imágenes clasificadas como IA cuando generate_heatmap es true.heatmap_url: Presente cuando heatmap_status es ready, la imagen fue clasificada como IA y generate_heatmap estaba habilitado al enviar. El aspecto depende de generate_heatmap_overlayed. Puede ser almacenamiento directo o ruta de API https://<api-host>/heatmap/<document_id> (use POST /heatmap/{id} con clave cuando sea seguro).analysis_results_status: pending, ready, skipped, failed o analyzing. Se omite o es null cuando generate_analysis_details era false.analysis_results: Análisis narrativo detallado cuando está habilitado; véase Explicación del resultado de análisis más abajo.
Explicación del resultado de análisis
Cuando analysis_results está listo, suele incluir: agreement (strong | moderate | weak | disagreement), imageTags (hasta cinco etiquetas breves), confidence (0–100), keyIndicators, detailedReasoning, visualPatterns y recommendations.
Notas
- La generación del mapa de calor es asíncrona y solo se ejecuta para imágenes clasificadas como IA cuando generate_heatmap es true (predeterminado). Consulte /query hasta que heatmap_status sea ready.
- El análisis detallado es asíncrono salvo que generate_analysis_details=false. Consulte analysis_results_status y analysis_results.
- URLs seguras: si están activadas, heatmap_url y preview_url pueden usar el host de la API; obtenga con POST /heatmap/{id} y POST /preview/{id} con su clave (véase Activos de mapa de calor y vista previa seguros).
- Vuelva a consultar /query tras la puntuación principal para recoger heatmap y analysis_results cuando terminen.
Comportamiento del mapa de calor y la superposición
El archivo en heatmap_url refleja generate_heatmap_overlayed y generate_heatmap_normalized de su solicitud /detect (o /bulk-upload) cuando generate_heatmap era true: la superposición por defecto (true) es una imagen normal con el mapa de calor superpuesto; false suele ser un PNG con transparencia para componer. Las imágenes reales y las solicitudes con generate_heatmap: false omiten heatmap_status y heatmap_url.
Ejemplo de respuesta (imagen IA, mapa de calor deshabilitado al enviar)
{
"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
}
}Ejemplo de respuesta (imagen IA, mapa de calor pendiente)
{
"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": "pending",
"heatmap_url": null
}
}Ejemplo: result ~90,24 con final_result AI Generated y detection_step 3 significa que el pipeline completo de metadatos, OCR y modelo ML finalizó.
Resultados de análisis (análisis profundo asíncrono)
Cuando generate_analysis_details es true en /detect, el análisis detallado puede completarse después de la puntuación principal. Consulte /query hasta que analysis_results_status sea ready (o skipped/failed).
1. El resultado inicial puede estar listo antes que el análisis
La detección principal (result, final_result, confidence) puede completarse mientras analysis_results_status sigue en 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
}
}Qué hacer
Use los campos principales de inmediato; siga consultando si necesita analysis_results.
2. Siga consultando
Llame a /query con el mismo id hasta que analysis_results_status deje de ser 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. Análisis completado
Cuando analysis_results_status es ready, analysis_results incluye agreement, imageTags, confidence, keyIndicators, detailedReasoning, visualPatterns y 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/..."
}Cuando el análisis no está disponible
Si analysis_results_status es skipped, failed o está ausente, o generate_analysis_details era false, considere la detección principal como definitiva.
{
"status": "done",
"result": 12.5,
"result_details": {
"analysis_results_status": "skipped",
"analysis_results": null
}
}Campos de resultados de análisis
- analysis_results_status: pending | ready | skipped | failed | analyzing
- analysis_results.agreement: strong | moderate | weak | disagreement
- analysis_results.imageTags: etiquetas descriptivas breves
- analysis_results.confidence: 0–100
- analysis_results.keyIndicators: señales concretas
- analysis_results.detailedReasoning: breve explicación
- analysis_results.visualPatterns: patrones más amplios
- analysis_results.recommendations: siguientes pasos
Carga masiva (ZIP)
Envíe varias imágenes en una sola solicitud subiendo un ZIP. El flujo replica el de una imagen: presign (nombre .zip) → PUT ZIP → POST /bulk-upload → consultar /query.
1. Obtener una URL de carga preautorizada (ZIP)
Use get-presigned-url con un nombre de archivo .zip (p. ej. images.zip).
GET https://detect-image.truthscan.com/get-presigned-url?file_name=images.zipEjemplo de solicitud
curl -X GET 'https://detect-image.truthscan.com/get-presigned-url?file_name=images.zip' \
--header 'apikey: YOUR API KEY GOES HERE'2. Subir el ZIP
Haga PUT del ZIP a la URL preautorizada con 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'Límites del ZIP
- Tamaño máximo del ZIP: 100 MB
- Máximo de imágenes por lote: 50
- Límites por imagen: mínimo 1 KB, máximo 10 MB
Formatos admitidos dentro del ZIP
JPG, JPEG, PNG, WebP, JFIF, HEIC, HEIF, AVIF, BMP, TIFF, TIF, GIF, SVG
Los archivos PDF dentro del ZIP no están admitidos y se omitirán.
Los archivos SVG se convierten a PNG antes de la detección.
3. Enviar el ZIP para detección masiva
POST /bulk-upload con key y url apuntando a la ruta del ZIP subido.
Parámetros opcionales
generate_preview: true para generar URLs de vista previa (predeterminado: false).generate_analysis_details: true para generar análisis detallado (predeterminado: false).generate_heatmap: Con false, se omite por completo la generación del mapa de calor (predeterminado: true). Los mapas de calor solo se producen para imágenes clasificadas como IA cuando este valor es true. Las imágenes reales nunca reciben mapa de calor.generate_heatmap_overlayed: Mismo comportamiento que /detect (superposición frente a mapa de calor RGBA transparente). Solo aplica cuando generate_heatmap es true y la imagen está clasificada como generada por IA.generate_heatmap_normalized: Mismo comportamiento que /detect (predeterminado: true). Solo aplica cuando generate_heatmap es true y la imagen está clasificada como generada por IA.model: Dominio del modelo: generic o formato instance_id/model.
Validación de flags del mapa de calor
Si generate_heatmap es false, no establezca explícitamente generate_heatmap_overlayed o generate_heatmap_normalized en true. La API devuelve 422 Unprocessable Entity con mensajes como "generate_heatmap_overlayed cannot be true when generate_heatmap is false." o "generate_heatmap_normalized cannot be true when generate_heatmap is false."
Ejemplo de solicitud
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"
}'Ejemplo de respuesta
{
"id": "77565038-9e3d-4e6a-8c80-e20785be5ee9",
"status": "pending",
"expected_count": 12
}Devuelve id, status pending y expected_count (cuántas imágenes del ZIP se analizarán).
Respuestas HTTP
| Estado | Cuerpo | Cuándo |
|---|---|---|
| 200 | JSON: id, status, expected_count | Trabajo masivo aceptado |
| 400 | {"error": "..."} (may include skipped) | Fallos de validación del ZIP |
| 403 | {"error": "..."} | Autenticación / créditos |
| 500 | {"error": "..."} | Error del servidor |
Misma regla que /detect: cualquier 2xx con id, status y expected_count (si está presente) es éxito.
Cómo se actualizan los resultados del ZIP masivo
- Tras el envío, el estado es pending hasta que empiece el procesamiento; luego analyzing.
- results enumera cada imagen; las entradas pendientes tienen result y result_details en null hasta terminar.
- Los mapas de calor opcionales y el análisis detallado pueden seguir pendientes dentro de result_details hasta estar listos.
- Cuando todas las imágenes en results han terminado, el estado global pasa a done. Si el lote no puede completarse, el estado puede ser failed.
- Puede llamar a /query antes de que el ZIP termine para ver resultados parciales.
4. Consultar resultados de carga masiva
Use POST /query con el id de /bulk-upload. Mismo endpoint que para una sola imagen; la forma de la respuesta depende de si el id es una imagen o un lote 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"
}'Ejemplo de respuesta (aún procesando)
{
"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": []
}Campos de respuesta (ZIP masivo)
- id — Id de la solicitud masiva.
- status — pending, luego analyzing, luego done o failed.
- results — Una entrada por imagen en análisis (id, status, result, result_details, filename, preview_url cuando exista).
- skipped — Archivos no analizados (tipo no admitido, tamaño, etc.) con status failed y motivo en result_details.
Facturación: los créditos solo se consumen por imágenes analizadas correctamente. Las conversiones SVG fallidas y los archivos omitidos no se facturan.
Activos de mapa de calor y vista previa seguros
Cuando heatmap_url o preview_url en /query apuntan al host de la API (no al almacenamiento de objetos directo), descargue los bytes con POST y su clave.
POST /heatmap/{id}
POST /preview/{id}
Cuerpo JSON de la solicitud: { "key": "YOUR-API-KEY-GOES-HERE" }
Respuestas del mapa de calor (compruebe el estado HTTP y Content-Type)
- 200 + binario (image/png, etc.) — Archivo de mapa de calor disponible. Puede establecerse X-Heatmap-Status.
- 202 + JSON — heatmap_status pending; consulte /query y reintente.
- 200 + JSON — No hay mapa de calor que servir (función opcional, error, etc.); no es error del servidor.
- 500 + JSON — Existe heatmap_url almacenado pero no se pudo descargar el archivo del almacenamiento; reintente más tarde.
- 404 + JSON — Id de documento no encontrado.
- 403 + JSON — La clave de API no es propietaria de este documento.
Vista previa: POST /preview/{id} devuelve los bytes en bruto de la vista previa. 404 con JSON si no se generó vista previa (generate_preview era false).
Ejemplos
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.pngcurl -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.pngInterno: sincronización de uso de la organización con Stripe (secreto de job)
Solo trabajos de backend de confianza, no clientes generales de la API. Requiere la cabecera x-job-secret coincidente con JOB_SECRET del servidor. Sincroniza el uso medido de la organización TruthScan con Stripe para un intervalo de fechas.
POST /organizations/{org_id}/usage/sync-to-stripe
Cabeceras: x-job-secret: <JOB_SECRET>
Cuerpo JSON: start_date, end_date, idempotency_id opcional para idempotencia del medidor de Stripe.
Devuelve success, organization_id, total_documents, value_sent_to_stripe, report_date, message. 400 si la organización no es medida o falta stripe_customer_id cuando hace falta; 401 secreto no válido; 404 organización no encontrada; 500 errores de Stripe o configuración.
Consultar créditos del usuario
Este endpoint acepta la apikey del usuario mediante cabecera y devuelve los detalles de créditos.
GET https://detect-image.truthscan.com/check-user-creditsEjemplo de solicitud
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'Ejemplo de respuesta
{
"baseCredits": 10000,
"boostCredits": 1000,
"credits": 11000
}En integraciones externas solo se rellenará el campo credits.
Comprobación de estado
Compruebe el estado del servidor de la API.
GET https://detect-image.truthscan.com/healthEjemplo de solicitud
curl -X 'GET' \
'https://detect-image.truthscan.com/health' \
-H 'accept: application/json'Ejemplo de respuesta
{
"status": "healthy"
}Una respuesta "healthy" indica que el servicio funciona con normalidad.
Errores
La mayoría de los errores se deben a parámetros incorrectos enviados a la API. Revise cada llamada e intente con los ejemplos proporcionados.
Los códigos de error genéricos que usamos se ajustan al estándar REST:
| Código de error | Significado |
|---|---|
| 400 | Bad Request — Su solicitud no es válida. |
| 401 | Unauthorized — Secreto de job no válido (endpoints de uso interno) u otro fallo de autenticación similar. |
| 403 | Forbidden — La clave de API no es válida, se denegó el acceso o no hay créditos suficientes para la operación. |
| 404 | Not Found — El recurso indicado no existe. |
| 405 | Method Not Allowed — Intentó acceder a un recurso con un método no válido. |
| 406 | Not Acceptable — Solicitó un formato que no es JSON. |
| 410 | Gone — El recurso de este endpoint ha sido eliminado. |
| 422 | Invalid Request Body — El cuerpo de la solicitud está mal formateado, no es válido o faltan parámetros. |
| 429 | Too Many Requests — Ha superado el rate limit de su clave de API (consulte Límites de velocidad). El cuerpo es {"error":"Too many requests"}; la cabecera X-RateLimit-Retry-After indica cuántos segundos esperar antes de reintentar. |
| 500 | Internal Server Error — Hubo un problema en nuestro servidor. Inténtelo de nuevo más tarde. |
| 503 | Service Unavailable — Estamos temporalmente fuera de servicio por mantenimiento. Inténtelo de nuevo más tarde. |
Problemas frecuentes y soluciones
Problemas de autenticación
"User verification failed" (403)
Causa: Clave de API no válida o caducada
Solución:
- Compruebe que la clave de API sea correcta
- Verifique que la clave esté activa en su cuenta
- Pruebe a regenerar la clave de API
"Not enough credits" (403)
Causa: Créditos insuficientes para el procesamiento de imágenes
Solución:
- Consulte los créditos restantes con /check-user-credits
- Compre créditos adicionales si es necesario
Problemas de validación de entrada
"Input URL cannot be empty" (400)
Causa: URL vacía o no válida enviada
Solución:
- Asegúrese de que la entrada url no esté vacía
- Elimine espacios iniciales o finales en los nombres de imagen
- Compruebe que la codificación de URL sea correcta
"Input email is empty" (400)
Causa: Falta el correo para el procesamiento por URL
Solución:
- Proporcione un correo electrónico válido al enviar URLs
- Compruebe el formato del correo
"Unsupported image type" (400)
Causa: Formato de archivo no admitido
Solución:
- Convierta a un formato admitido (JPG, PNG, WebP, HEIC, HEIF, AVIF, BMP, TIFF, GIF, SVG, PDF)
- Compruebe que la extensión del archivo sea correcta
"File size is too small" (400)
Causa: El archivo de imagen está por debajo del tamaño mínimo
Solución:
- Use un archivo de imagen mayor (mínimo 1 KB)
- Compruebe si la imagen se corrompió durante la subida
"File size exceeds limit" (400)
Causa: El archivo de imagen es demasiado grande
Solución:
- Comprima o redimensione la imagen; el máximo depende del despliegue (el mensaje de error de la API indica el límite en MB)
- Pruebe con otro formato de imagen
"Invalid file type" (400)
Causa: Falló la validación del tipo de archivo
Solución:
- Asegúrese de que el archivo sea un formato de imagen válido
- Compruebe que el archivo no esté corrupto
- Verifique que el tipo MIME coincida con la extensión
Problemas de procesamiento
Estado de imagen "failed"
Causa: El procesamiento falló por diversos motivos
Solución:
- Verifique que la URL tenga un formato admitido
- Compruebe que el archivo de imagen sea válido y no esté corrupto
- Asegúrese de que la imagen cumpla los requisitos de tamaño
- Contacte con soporte si el problema continúa
"User not found"
Causa: Id de usuario no válido
Solución:
- Verifique que el id de usuario sea correcto
- Asegúrese de que la cuenta de usuario esté activa
- Vuelva a autenticarse si es necesario
"File metadata could not be fetched" (500)
Causa: No se pudo acceder al archivo subido
Solución:
- Verifique que el archivo se subió correctamente
- Compruebe que la URL del archivo sea accesible
- Intente volver a subir el archivo
Problemas de subida
"Image upload failed" (403/400)
Causa: URL preautorizada no válida o caducada, o problemas con el servidor de almacenamiento
Solución:
- Use la URL preautorizada en cuanto la reciba
- Verifique que Content-Type coincida con el formato del archivo
- Elimine espacios del nombre de archivo antes de subir
- Genere una nueva URL preautorizada si hace falta
"Invalid pre-signed URL" (400)
Causa: Nombre de archivo con espacios o URL preautorizada caducada o corrupta
Solución:
- Elimine espacios del nombre de archivo antes de solicitar la URL preautorizada
- Use caracteres alfanuméricos, guiones y guiones bajos
- Genere una nueva URL preautorizada si hace falta
Problemas de carga masiva
"URL must point to a ZIP file" (400)
Causa: La URL proporcionada a /bulk-upload no apunta a un archivo ZIP
Solución:
- Use get-presigned-url?file_name=images.zip (u otro nombre .zip)
- Suba un ZIP válido a la URL preautorizada
- Asegúrese de que la solicitud bulk-upload apunte con url a ese ZIP subido
"ZIP file too large" (400)
Causa: El ZIP supera el tamaño máximo (100 MB)
Solución:
- Reduzca el número de imágenes o comprímalas
- Divida en varias cargas masivas
"Too many files" (400)
Causa: El ZIP contiene más de 50 imágenes válidas
Solución:
- Reduzca a 50 imágenes o menos por ZIP
- Divida en varias cargas masivas
"No valid images found in ZIP" (400)
Causa: Todos los archivos del ZIP se omitieron (formato no admitido, demasiado pequeños, ruta no válida, etc.)
Solución:
- Use formatos admitidos (JPG, PNG, WebP, HEIC, HEIF, AVIF, BMP, TIFF, TIF, GIF, SVG)
- El PDF no está admitido en masivo
- Cada imagen debe tener al menos 1 KB y como máximo 10 MB
- Evite archivos ocultos (nombres que empiezan por .) y path traversal (..)
"Document is not a bulk upload (image-zip) result" (400)
Causa: El id no corresponde a ese tipo de carga (imagen única frente a lote ZIP)
Solución:
- Use el id de /detect para envíos de una sola imagen
- Use el id de /bulk-upload para envíos ZIP
¿Necesita ayuda?
Para más información sobre el uso de nuestra API o soporte técnico, póngase en contacto con nosotros.
Preguntas frecuentes sobre la API
Respuestas a las preguntas más habituales sobre nuestra API de detección de imágenes con IA.