API Reference

Forensic AI image detection over a single REST endpoint. Bearer-token auth, multipart upload, JSON response with per-detector breakdown. Sub-350ms typical latency.

Quickstart

Three steps from zero to your first detection:

  1. Create a free account at pixelprism.ai
  2. Generate an API key from your dashboard — keys start with dsk_live_
  3. POST an image to /api/detect with your key in the Authorization header
SHELLcurl -X POST https://pixelprism.ai/api/detect \
  -H "Authorization: Bearer dsk_live_YOUR_KEY" \
  -F "file=@/path/to/image.jpg"

You'll receive a JSON response within a few hundred milliseconds:

JSON{
  "verdict": "AI_GENERATED",
  "confidence": 0.9234,
  "latency_ms": 312,
  "signals": ["fft_artifact", "vit_artifact", "clip_artifact", "exif_artifact"],
  "detector_scores": {
    "fft": 0.92, "vit": 0.99, "vit2": 0.88, "vit3": 0.91,
    "dire": 0.76, "clip": 0.95, "srm": 0.82,
    "exif": 1.0, "face": 0.04
  },
  "meta_classifier_used": true
}

Authentication

Authenticate every request with an API key in the Authorization header using the Bearer scheme:

HTTPAuthorization: Bearer dsk_live_8f77305a8f2d4aa2ab947fe1cc409333…

API keys are issued from your dashboard and shown once at creation — store them in a secure place (environment variable, secret manager). We store only a hashed prefix; if you lose the full key, you'll need to generate a new one.

Never embed keys in client-side code. A leaked key is a billable liability. Treat them like database passwords. Use a backend proxy if you need to call the API from a browser. Rotate immediately at the dashboard if you suspect a key has been exposed.

Key prefixes

PrefixEnvironment
dsk_live_Production keys (real billing)
dsk_test_Reserved for future test-mode keys (not yet supported — see changelog)

Base URL

All API calls use HTTPS over the production base URL:

https://pixelprism.ai

HTTP requests are redirected to HTTPS. Plaintext is not supported.

POST /api/detect

POST /api/detect Run forensic detection on a single image.

Request

Send a multipart/form-data request with one form field named file:

FieldTypeRequiredDescription
filefileyesThe image to analyze. JPEG, PNG, WebP, GIF, BMP. Max 25 MB.

Headers

HeaderRequiredValue
AuthorizationyesBearer dsk_live_…
Content-Typeyes (set by client)multipart/form-data; boundary=…

Response

HTTP 200 with a JSON body — see Response shape below for the full schema.

GET /api/health

GET /api/health Liveness probe. No auth required. Use this for monitoring / uptime checks.
JSON{
  "status": "ok",
  "version": "0.8.0",
  "meta_classifier_loaded": true,
  "feature_order": ["fft", "vit", "vit2", "vit3", "dire", "clip", "srm", "exif", "face"]
}

Returns 503 with {"status":"backend_unreachable"} if the GPU detection backend is offline.

Response shape

FieldTypeDescription
verdictstringOne of "AI_GENERATED" or "LIKELY_REAL"
confidencenumber 0–1P(AI-generated). The verdict flips at the 0.5 threshold. A confidence of 0.13 with verdict LIKELY_REAL means 87% confidence the image is real.
latency_msintegerEnd-to-end inference latency on our backend
signalsarray of stringsForensic flags raised — see Signals
detector_scoresobjectPer-detector P(AI) scores in [0,1] — see below
skipped_detectorsarray of stringsDetectors that returned -1 (e.g., face detector when no face found)
meta_classifier_usedbooleantrue when the trained meta-classifier produced the verdict; false if a weighted-fallback was used (rare, only during model load)

Detector scores

Each detector outputs a probability in [0, 1] that the image is AI-generated. The meta-classifier combines all 9 detector outputs into the final confidence. Useful for explaining a verdict, debugging false positives, or targeting your own thresholds.

DetectorCatchesHardware · Latency
fftFrequency-domain artifacts (GAN/diffusion radial spectrum)CPU · ~5ms
vitSDXL-class semantic artifacts (Organika fine-tune)GPU · ~50ms
vit2Mixed-generator artifacts (umm-maybe AI-image-detector)GPU · ~50ms
vit3Custom fine-tune on diverse training corpusGPU · ~50ms
direDiffusion-model reconstruction error (SD/DALL-E/Midjourney/FLUX)GPU · ~200ms
clipCLIP-space Mahalanobis distance from real-photo referenceGPU · ~30ms
srmCamera sensor noise pattern absence (SRM filter bank)CPU · ~10ms
exifEXIF / C2PA provenance metadata checkCPU · <1ms
faceFace deepfake / face-swap (Xception). Returns a score only when a face is detected; otherwise omitted from response.GPU · ~40ms

Signals

Each detector raises a corresponding {name}_artifact signal when its score crosses a per-detector threshold. The signals array is a quick human-readable summary of which forensic systems flagged the image:

Error responses

Errors return appropriate HTTP status codes with a JSON body of the form {"detail": "…"}:

StatusWhenHow to handle
400Malformed request (missing file, invalid format)Fix the request
401Missing or invalid Authorization headerCheck your API key is correct and not revoked
403API key revoked or account suspendedGenerate a new key or contact support
413Image larger than 25 MBResize before upload
415Unsupported image formatConvert to JPEG/PNG/WebP
429Quota exceeded (Free / Enterprise hard cap) or per-IP rate limitUpgrade your plan or back off
500Internal errorRetry with exponential backoff
502Detection backend unreachableRetry; check /api/health

Rate limits & quotas

Per-tier monthly quota

TierMonthly imagesDetectors activeOverage
Free503 (FFT + ViT + EXIF)none — hard cap at 50
Starter2,0005$0.001 / image
Pro25,000All 9 + meta-classifier$0.0005 / image
EnterpriseCustomAll + custom fine-tunesVolume pricing

Concurrent request rate

Soft limit of 20 concurrent requests per API key. Beyond that, requests are queued briefly. Sustained bursts above 100 RPS may receive 429 responses; in that case back off using Retry-After.

Overage billing

Once a paid tier exceeds its monthly quota, additional requests are billed as metered overage through Stripe. Overage charges appear on your next invoice as a separate line item:

Detection overage: 247 imgs × $0.0005 = $0.1235

Free and Enterprise tiers do not overage — Free hard-caps at 50 and Enterprise is custom-contracted.

Webhooks

Webhook delivery (per-detection, retried with exponential backoff, signed with an HMAC) is a Pro-tier feature currently in development. When ready, you'll be able to register a callback URL from your dashboard and receive a POST for every detection your account performs.

Heads up: webhooks are not yet shipping. Until then, poll your usage via the dashboard or scrape the local UsageRecord table on Enterprise on-prem deployments. We'll announce in the changelog when webhooks go live.

Code samples

The same operation in four languages. All examples expect DEEPSCAN_API_KEY to be set in your environment.

SHELL# Single image
curl -X POST https://pixelprism.ai/api/detect \
  -H "Authorization: Bearer $DEEPSCAN_API_KEY" \
  -F "file=@/path/to/image.jpg"

# Pretty-print + extract verdict using jq
curl -s -X POST https://pixelprism.ai/api/detect \
  -H "Authorization: Bearer $DEEPSCAN_API_KEY" \
  -F "file=@image.jpg" | jq '{verdict, confidence, signals}'

# Loop a folder with concurrency-2 (xargs)
ls *.jpg | xargs -P 2 -I {} curl -s -X POST https://pixelprism.ai/api/detect \
  -H "Authorization: Bearer $DEEPSCAN_API_KEY" \
  -F "file=@{}"
PYTHON 3.10+import os
import httpx

API_KEY = os.environ["DEEPSCAN_API_KEY"]
BASE = "https://pixelprism.ai"


def detect(image_path: str) -> dict:
    """POST an image to /api/detect and return the parsed JSON response."""
    with open(image_path, "rb") as f:
        files = {"file": (os.path.basename(image_path), f.read(), "image/jpeg")}
    r = httpx.post(
        f"{BASE}/api/detect",
        headers={"Authorization": f"Bearer {API_KEY}"},
        files=files,
        timeout=120.0,
    )
    r.raise_for_status()
    return r.json()


if __name__ == "__main__":
    result = detect("my-image.jpg")
    print(f"verdict={result['verdict']}, P(AI)={result['confidence']:.3f}")
    print("signals:", result['signals'])
NODE 18+import fs from "fs/promises";

const API_KEY = process.env.DEEPSCAN_API_KEY;
const BASE = "https://pixelprism.ai";

async function detect(imagePath) {
  const bytes = await fs.readFile(imagePath);
  const form = new FormData();
  form.append("file", new Blob([bytes], { type: "image/jpeg" }), imagePath.split("/").pop());

  const r = await fetch(`${BASE}/api/detect`, {
    method: "POST",
    headers: { Authorization: `Bearer ${API_KEY}` },
    body: form,
  });
  if (!r.ok) throw new Error(`${r.status} ${await r.text()}`);
  return r.json();
}

const result = await detect("my-image.jpg");
console.log(`verdict=${result.verdict}, P(AI)=${result.confidence.toFixed(3)}`);
console.log("signals:", result.signals);
BROWSER JS// Browser code MUST go through your own backend proxy — never embed
// API keys in client-side JS where users can read them.
// Below: client posts to YOUR /detect endpoint; YOUR backend forwards
// to DeepScan with the secret key.

async function detectFromBrowser(file) {
  const form = new FormData();
  form.append("file", file);

  const r = await fetch("/your-backend/detect", {
    method: "POST",
    body: form,
    credentials: "same-origin",
  });
  return r.json();
}

// Wire up to a file input
document.querySelector("#file").addEventListener("change", async (e) => {
  const file = e.target.files[0];
  if (!file) return;
  const result = await detectFromBrowser(file);
  console.log("verdict:", result.verdict, "P(AI):", result.confidence);
});

Best practices

Changelog

VersionDateNotes
0.8.02026-05-019-detector ensemble live (added vit3); meta-classifier retrained on diverse corpus including DALL-E 3, Imagen 3, Nano Banana, FLUX, SD 3.5, Recraft, Grok, Ideogram
0.7.02026-04-26Added vit2; meta-classifier fusion launched
0.6.02026-04-23EXIF / C2PA provenance check added
0.5.02026-04-15Initial 7-detector ensemble (FFT + ViT + DIRE + CLIP + SRM + Face + EXIF)

Support

Email: support@pixelprism.ai
Status: /api/health (live)
Bug reports: include the request timestamp + a sample image, and the request body if available.

SLA on response time: best-effort within 24 business hours for Free / Starter; same-day for Pro; contractual for Enterprise.