API Documentation
ISO 27001SOC 2 CertifiedGDPR Compliant

AI Image Detection API

Complete documentation for integrating TruthScan's AI image detection API into your applications.

Try it out without code by visiting our FastAPI endpoint: https://detect-image.truthscan.com/docs

Authentication

TruthScan uses API keys to allow access to the API. You can get your API key at the top of the page in our developer portal.

TruthScan expects for the API key to be included in all API requests to the server in a request body that looks like the following:

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

You must replace YOUR API KEY GOES HERE with your personal API key.

AI Image Detector

Detect (3-Step Process)

The AI Image Detection workflow consists of the following steps:

  • Obtain a Pre-signed Upload URL
  • Upload the Image
  • Submit the Image for Detection

1. Obtain a Pre-signed Upload URL

Begin by requesting a pre-signed URL from the API. This URL allows you to securely upload your image file to the storage server.

Supported File Formats

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

Important Note

It is necessary to remove spaces from the image filename when requesting a pre-signed URL.

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

Example Request

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

Example Response

{
  "status": "success",
  "presigned_url": "https://image-presigned-upload.ai-assets-cdn.com?file_name=581d47c7-3ef4-42af-88d9-6dab6bf69389_20250611-121955_example.jpg?...",
  "file_path": "uploads/example.jpg"
}

2. Upload the Image

Use the provided 'presigned_url' to upload your image via a PUT request. Ensure the correct content type is set according to your image format.

Important Note

It is necessary to remove spaces from the image filename when uploading the image.

Example Request

curl -X PUT 'https://image-presigned-upload.ai-assets-cdn.com?file_name=581d47c7-3ef4-42af-88d9-6dab6bf69389_20250611-121955_example.jpg?...' \
  --header 'Content-Type: image/<FILE_FORMAT - jpeg, jpg, png, webp, heic, heif, avif, bmp, tiff, tif>' \
  --header 'x-amz-acl: private' \
  --data-binary '@example.jpg' # Attachment

File Size Limits

  • Minimum file size: 1KB
  • Maximum file size: 10MB

Ensure that the file format remains consistent during the upload process. A successful upload will return a status code of 200.

3. Submit Image for AI Detection

After uploading, submit the image for AI detection by referencing the 'file_path' from the previous step.

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

Example Request

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": false,
  "generate_analysis_details": true
}'

The 'FILE_PATH' refers to the path obtained from the response in the initial step, 'Obtain a Pre-signed Upload URL'.

Optional Parameters

  • generate_preview: Set to 'true' to generate a preview URL for the image (default: 'false')
  • document_type: Type of document (default: 'Image')
  • email: Email address for processing
  • generate_analysis_details: Set to 'true' to enable deep AI analysis results (default: 'false'). When enabled, the query response will include analysis_results_status and analysis_results fields.

Example Response

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

The response includes a unique image ID for tracking the detection status.

Query

This endpoint accepts an image id returned by the /detect request. And returns the status of the image submission as well as the complete result of the AI Detection operation, including metadata, OCR, and ML model analysis.

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

Example Request

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

Example Response

{
    "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
    },
    "preview_url": "https://ai-image-detector-prod.nyc3.digitaloceanspaces.com/previews/..."
}

Result Interpretation

  • result: Score from 1-100 indicating the likelihood the image is AI-generated. Higher scores = greater AI likelihood.
  • final_result: The overall determination (e.g., 'AI Generated', 'Real', 'Digitally Edited', 'AI Edited')
  • confidence: The confidence score of the detection
  • detection_step: Indicates the stage at which detection was completed. 1 = Only metadata returned, 2 = Returns metadata and OCR, 3 = Returns metadata, OCR, and ML model results (most comprehensive)
  • metadata: Information extracted from image metadata using ExifTool and Pillow
  • ocr: Results from Optical Character Recognition analysis for watermark detection
  • ml_model: Results from the machine learning model
  • preview_url: URL to the preview image (if generate_preview was set to true)
  • heatmap_status: Status of heatmap generation ('pending' or 'ready'). Note: Heatmap generation is asynchronous. Initially, heatmap_status will be 'pending' and heatmap_url may be absent or null. When ready, heatmap_status becomes 'ready' and heatmap_url is populated.
  • heatmap_url: URL to the heatmap image, available when heatmap_status is 'ready'. Only available for images with score >= 20.
  • analysis_results_status: Status of deep AI analysis ('pending', 'done', 'skipped', or null). When 'pending', continue polling the /query endpoint โ€” analysis is still processing in the background. When 'done', the analysis_results field contains the completed analysis. When 'skipped', null, or absent, deep analysis is not available for this image.
  • analysis_results: Deep AI analysis results (available when analysis_results_status is 'done'). Contains: agreement (strong/moderate/weak/disagreement), confidence (0-100), keyIndicators (array of visual anomalies detected), detailedReasoning (explanation), visualPatterns (array of stylistic patterns), and recommendations (actionable items).

Important Note

Heatmap generation is asynchronous. Initially, heatmap_status will be 'pending' and heatmap_url may be absent or null. When ready, heatmap_status becomes 'ready' and heatmap_url is populated. Heatmaps are only generated for images with score >= 20.

Here, "result": 90.24 indicates a high likelihood the image was AI-generated. The "final_result": "AI Generated" provides a clear determination, and "confidence": 90.24 indicates high confidence in this result. The "detection_step": 3 field indicates that complete analysis (metadata, OCR, and ML model) was completed. The "heatmap_status": "ready" and "heatmap_url" provide access to the visual heatmap showing areas detected as AI-generated.

Analysis Results (Asynchronous Deep Analysis)

When you set 'generate_analysis_details' to 'true' in the /detect request, TruthScan runs a deep AI analysis in the background after the initial detection completes. The initial query response will return with status 'done' and your detection results ready to use, but the analysis_results_status field may still be 'pending'. You can use the initial results immediately and optionally poll for the deep analysis to complete.

1. Initial Result Settles (Analysis Still Pending)

When you submit with 'generate_analysis_details': true and first query with status 'done', the core detection results (result, final_result, confidence) are ready. However, analysis_results_status may be 'pending' โ€” this means the deep AI analysis is still processing in the background.

{
    "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
    }
}

What to do

You can use the initial detection results (result, final_result, confidence, metadata, ocr, ml_model) immediately. If you also need the deep analysis, continue polling the /query endpoint with the same image ID until analysis_results_status changes from 'pending'.

2. Keep Polling for Analysis Results

Continue calling the /query endpoint with the same image ID. Check the analysis_results_status field on each response. When it changes from 'pending' to 'done', the analysis_results object will be populated.

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 Complete โ€” Full Response

Once analysis_results_status is 'done', the analysis_results object contains the full deep AI analysis with agreement level, confidence, key indicators, detailed reasoning, visual patterns, and 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": {
            "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/..."
}

When Analysis Is Not Available

If analysis_results_status is 'skipped', null, or absent, deep analysis will not be produced for this image. This happens when 'generate_analysis_details' was not set to 'true' in the /detect request, or for certain image types and detection scenarios. You should treat the initial detection results as final.

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

Analysis Results Fields

  • analysis_results_status: 'pending' = still processing, 'done' = results available, 'skipped' / null / absent = not available for this image
  • analysis_results.agreement: How strongly the deep analysis agrees with the initial detection (strong / moderate / weak / disagreement)
  • analysis_results.confidence: Confidence score of the deep analysis (0-100)
  • analysis_results.keyIndicators: Array of specific visual anomalies detected in the image
  • analysis_results.detailedReasoning: 2-4 sentence explanation of why the image was classified this way
  • analysis_results.visualPatterns: Array of stylistic patterns found (e.g., noise patterns typical of diffusion models)
  • analysis_results.recommendations: Array of actionable recommendations for further verification

Check User Credits

This endpoint accepts the users apikey via the header. And returns users credit details.

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

Example Request

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'

Example Response

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

Health Check

This endpoint allows you to check the status of the AI image detection service.

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

Example Request

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

Example Response

{
    "status": "healthy",
    "timestamp": "2024-01-15T10:30:00Z"
}

A "healthy" response indicates the service is operating normally.

Errors

Most errors will be from incorrect parameters being sent to the API. Double check the parameters of each API call to make sure it's properly formatted, and try running the provided example code.

The generic error codes we use conform to the REST standard:

Error CodeMeaning
400Bad Request -- Your request is invalid.
403Forbidden -- The API key is invalid, or there aren't sufficient credits for image processing.
404Not Found -- The specified resource doesn't exist.
405Method Not Allowed -- You tried to access a resource with an invalid method.
406Not Acceptable -- You requested a format that isn't JSON.
410Gone -- The resource at this endpoint has been removed.
422Invalid Request Body -- Your request body is formatted incorrectly or invalid or has missing parameters.
429Too Many Requests -- You're sending too many requests! Slow it down!
500Internal Server Error -- We had a problem with our server. Try again later.
503Service Unavailable -- We're temporarily offline for maintenance. Please try again later.

Common Issues and Solutions

Authentication Issues

"User verification failed" (403)

Cause: Invalid or expired API key

Solution:

  1. Verify your API key is correct
  2. Check if your API key is active in your account
  3. Try regenerating your API key

"Not enough credits" (403)

Cause: Insufficient credits for image processing

Solution:

  1. Check your remaining credits using /check-user-credits
  2. Purchase additional credits if needed
  3. Optimize image size before upload to consume fewer credits

Input Validation Issues

"Unsupported file format" (400)

Cause: Unsupported or invalid image format submitted

Solution:

  1. Verify image format is supported (JPG, JPEG, PNG, WebP, JFIF, HEIC, HEIF, AVIF, BMP, TIFF, TIF)
  2. Ensure the file is not corrupted
  3. Check Content-Type header when uploading

"File too large" (400)

Cause: File size exceeds 10MB limit

Solution:

  1. Resize or compress the image to under 10MB
  2. Check file size before uploading
  3. Use more efficient formats like WebP when possible

Processing Issues

"Request timeout" (WebSocket)

Cause: Image processing took too long

Solution:

  1. Try with a smaller or less complex image
  2. Check if the service is experiencing high load
  3. Retry the request

Document Status "failed"

Cause: Processing failed for various reasons

Solution:

  1. Check if image meets minimum requirements (1KB - 10MB)
  2. Verify image is in a supported format
  3. Verify upload completed successfully before submitting for detection
  4. Contact support if issue persists

Upload Issues

"Image upload failed" (403/400)

Cause: Invalid or expired pre-signed URL, or issues with storage server

Solution:

  1. Ensure you use the pre-signed URL immediately after receiving it (may expire)
  2. Verify Content-Type header is correct for image format
  3. Remove spaces from filename before uploading
  4. Try generating a new pre-signed URL if the current one expired

"Invalid pre-signed URL" (400)

Cause: Filename with spaces or expired/corrupted pre-signed URL

Solution:

  1. Remove all spaces from filename before requesting pre-signed URL
  2. Use only alphanumeric characters, hyphens and underscores in filename
  3. Generate a new pre-signed URL if needed

Need Help?

For more information about using our API or for technical support, please contact us.

API Frequently Asked Questions

Find answers to the most common questions about our AI image detection API.