Deepfake Detection API: Adding Image and Video Verification to Your Platform A developer guide details how to integrate the DeepfakeDetector.ai API into platforms that accept user-uploaded images and video, covering key generation, image and video detection endpoints, asynchronous job handling, and defensive response parsing. The API returns a verdict, confidence score, and driving signals, with image detection at roughly 0.8 seconds and short-clip video at about 2.1 seconds. The guide stresses scanning files before transcoding or compression, since re-encoding can degrade the artifacts detectors rely on and heavy compression is a common cause of inconclusive results. If your platform accepts user-uploaded images or video, synthetic media is already in your pipeline. Profile photos, ID selfies during onboarding, product listing images, UGC clips submitted to a newsroom, video testimonials. Some fraction of that is generated or manipulated, and the fraction is growing. This guide covers adding detection using the DeepfakeDetector.ai API: getting a key, scanning an image, handling video asynchronously, parsing the response defensively, and, the part most guides skip, designing your product around a result that is a probability rather than a fact. The DeepfakeDetector.ai API https://deepfakedetector.ai/deepfake-detection-api takes an image, video, or voice file and returns a verdict on whether it's AI-generated or manipulated, with a confidence score and the signals that drove it. Everything sits behind one base URL with the same auth, response shape, and error semantics across media types: https://app.deepfakedetector.ai/api/v1 The endpoints, with the typical latencies the docs list: POST /api/v1/detect/image at around 0.8 seconds POST /api/v1/detect/video at around 2.1 seconds for short clips POST /api/v1/detect/voice at around 1.4 seconds GET /api/v1/jobs/{id} at around 50 milliseconds, for checking async jobs For images, it targets AI-generated images and faces from the major generators, including Midjourney, DALLĀ·E, Stable Diffusion, and Flux. For video, it covers face swaps, lip-sync manipulation, and fully AI-generated clips, analyzed frame by frame. This guide focuses on images and video; voice works the same way through its own endpoint. API access starts on the Starter plan. The free tier gives you 50 detections a month in the web app, which is useful for evaluating accuracy on your own media before you pay, but it doesn't include API access. Create an account, subscribe to a plan with API access, and generate a key. Two things to handle correctly: The key is shown once. DeepfakeDetector.ai hashes keys at rest and displays the full key only at creation. Copy it into your secrets manager immediately. Keep it server-side. Requests authenticate with a Bearer token, and a key in a browser bundle is a key anyone can read. All calls below belong on your backend. export DFD API KEY="sk live ..." The simplest call passes a publicly reachable HTTPS URL: curl -X POST https://app.deepfakedetector.ai/api/v1/detect/image \ -H "Authorization: Bearer $DFD API KEY" \ -H "Content-Type: application/json" \ -d '{ "media url": "https://example.com/profile-photo.jpg" }' The request accepts a few optional parameters worth knowing from the start: media type image , video , or voice . Inferred from the MIME type if you leave it out. strict mode false . callback url retain If your media lives in private storage, a signed URL with a short expiry works well: the API fetches the file, and the link dies shortly after. When you have the file in hand rather than a URL, send it as multipart form data: curl -X POST https://app.deepfakedetector.ai/api/v1/detect/image \ -H "Authorization: Bearer $DFD API KEY" \ -F "file=@./uploads/selfie.jpg" Either media url or a multipart upload is required, not both. Supported formats include MP4, MOV, and WEBM for video, and JPG, PNG, and WEBP for images, along with common audio formats. File size and duration limits depend on your plan; paid plans handle video up to 10 minutes per detection. A practical point for user uploads: scan the file your user actually submitted, before you transcode, resize, or compress it for storage. Re-encoding can degrade the artifacts detectors rely on, and the docs note that heavy compression is a common reason for an inconclusive result. A completed detection returns structured JSON. The example in the API documentation looks like this: { "job id": "job 8mTk2x", "verdict": "synthetic", "confidence": 0.91, "generator family": "diffusion", "signals": { "skin texture": "unnatural", "geometric": "symmetric", "lighting": "consistent" }, "flagged segments": { "start": 2.4, "end": 5.8 } , "latency ms": 1842 } What each field gives you: verdict and confidence are what most of your logic will hang off. Confidence is a float between 0 and 1. signals explains what drove the verdict, which is what makes a flag reviewable rather than opaque. generator family indicates the likely type of generator, for example diffusion-based. flagged segments applies to video and voice, giving start and end times in seconds for the portions that failed. For video moderation, this is the most useful field in the response: a reviewer can jump straight to second 2.4 instead of watching the whole clip. job id identifies the request. Store it with every result, since it's how you trace a decision back to a specific detection later. One caution worth taking seriously. DeepfakeDetector.ai's web app presents verdicts as Authentic, Likely Synthetic, or Inconclusive with a 0 to 100 TrustScore, and the examples across its own pages don't use identical field names and verdict strings. Before you write logic that matches exact verdict values, confirm the current enum against the live API documentation, and build your thresholds on confidence rather than on string matching alone. The wrapper in section 7 does exactly that. Images and short clips return quickly. Video processing scales with duration at roughly real time, so a three-minute clip takes on the order of three minutes. Holding an HTTP request open that long is a bad idea, and the API is designed for you not to. For files over 60 seconds, use a webhook. Pass a callback url and the API will POST the verdict to it when the analysis finishes: curl -X POST https://app.deepfakedetector.ai/api/v1/detect/video \ -H "Authorization: Bearer $DFD API KEY" \ -H "Content-Type: application/json" \ -d '{ "media url": "https://storage.example.com/signed/clip.mp4", "callback url": "https://your-app.com/webhooks/deepfake" }' You get a job id back immediately. Store it alongside the record it belongs to. Treat the webhook as a notification, not as truth. The official SDKs handle webhook signature verification for you. If you're calling the API directly, the simplest robust pattern is to use the webhook only as a trigger, then fetch the authoritative result yourself: GET https://app.deepfakedetector.ai/api/v1/jobs/{job id} That way a forged POST to your webhook endpoint can't push a fake verdict into your system, because the result you act on always comes from an authenticated call you made. Add a reconciliation sweep. Webhooks occasionally fail to arrive. A scheduled job that checks any detection still pending after a reasonable window, using the same jobs endpoint, closes that gap. Here's a Node wrapper that handles timeouts, rate limits, and the verdict normalization from section 5: js const BASE = "https://app.deepfakedetector.ai/api/v1"; async function detectMedia mediaUrl, { type = "image", callbackUrl, timeoutMs = 15000 } = {} { const controller = new AbortController ; const timer = setTimeout = controller.abort , timeoutMs ; const body = { media url: mediaUrl }; if callbackUrl body.callback url = callbackUrl; try { const res = await fetch ${BASE}/detect/${type} , { method: "POST", headers: { Authorization: Bearer ${process.env.DFD API KEY} , "Content-Type": "application/json", }, body: JSON.stringify body , signal: controller.signal, } ; if res.status === 429 { const retryAfter = Number res.headers.get "retry-after" || 5 ; throw Object.assign new Error "rate limited" , { retryAfter } ; } if res.ok throw new Error Detector returned ${res.status} ; const data = await res.json ; // Async job: no verdict yet if data.confidence === undefined { return { pending: true, jobId: data.job id ?? data.id }; } return { pending: false, jobId: data.job id ?? data.id, verdict: String data.verdict ?? "" .toLowerCase , confidence: data.confidence, signals: data.signals ?? null, flaggedSegments: data.flagged segments ?? , }; } catch err { if err.name === "AbortError" throw new Error "detector timeout" ; throw err; } finally { clearTimeout timer ; } } The data.job id ?? data.id fallback is deliberate, given the field-name variation noted in section 5. Once you've confirmed the live schema, you can tighten it. The Python equivalent, with exponential backoff: python import os import time import requests BASE = "https://app.deepfakedetector.ai/api/v1" HEADERS = { "Authorization": f"Bearer {os.environ 'DFD API KEY' }", "Content-Type": "application/json", } def detect media media url: str, media type: str = "image", callback url: str | None = None, max retries: int = 3 - dict: payload = {"media url": media url} if callback url: payload "callback url" = callback url for attempt in range max retries : r = requests.post f"{BASE}/detect/{media type}", headers=HEADERS, json=payload, timeout=15 if r.status code == 429: time.sleep int r.headers.get "Retry-After", 2 attempt continue r.raise for status data = r.json if "confidence" not in data: return {"pending": True, "job id": data.get "job id" or data.get "id" } return { "pending": False, "job id": data.get "job id" or data.get "id" , "verdict": str data.get "verdict", "" .lower , "confidence": data "confidence" , "signals": data.get "signals" , "flagged segments": data.get "flagged segments", , } raise RuntimeError "detector: retries exhausted" If you'd rather not write this yourself, DeepfakeDetector.ai publishes official SDKs that handle auth, retries, backoff, file streaming, and webhook signature verification. The API page lists clients for JavaScript and TypeScript, Python, Go, Ruby, PHP, Java, .NET, and Rust. This is where integrations succeed or quietly fail. DeepfakeDetector.ai describes its own detection as probabilistic rather than absolute, and your product has to reflect that. Use three outcomes, not two. A binary pass or block forces every uncertain result into the wrong bucket. A tiered design gives the middle somewhere to go: function triage result { if result.pending return "awaiting result"; if result.confidence < 0.5 return "clear"; if result.confidence < 0.85 return "human review"; return "high confidence flag"; } Read that function as a starting point, not a recommendation. Where you set the boundaries depends on what a mistake costs in your product, and you should tune them against real samples of your own media. Choose strict mode by which error costs more. It raises recall and lowers precision. For KYC onboarding, where a missed synthetic ID is expensive, strict mode makes sense. For a social feed, where wrongly flagging real users damages trust, the default is usually better. Route inconclusive results to a person, and ask for better input. Heavy compression is a common cause of low confidence. Requesting the original file, or a higher-quality copy, often resolves it. Never automate a consequence off the score alone. Blocking an account, rejecting an ID, or labeling a user's content as fake should involve review, especially when the verdict is anywhere near your threshold. Combine signals where you can. A detection result is strongest alongside provenance checks, such as Content Credentials where they exist, account history, and the context of the upload. If you're processing user media, the data handling defaults matter as much as the accuracy, and they're reasonable here. Files are purged 60 seconds after the verdict by default. Setting retain: true keeps a file for 30 days, which is useful for audit trails in regulated workflows. Leave it off unless you have a specific reason to turn it on. Keys are hashed at rest , and every call returns a request ID for auditing. EU data residency is available on Business plans and above. SOC 2 is in progress, not complete. The company states this plainly, and it's worth being equally plain with your own compliance team rather than assuming certification. Rate limits run from 60 to 300 requests per minute depending on plan, with burst allowance for known clients. The API targets a 99.9 percent uptime SLO, with a status page at status.deepfakedetector.ai . Plans with API access: Annual billing saves up to 20 percent. Your monthly detections are shared between the web app and the API, so a team using both draws from one pool. A few habits keep usage under control: Don't scan what can't be synthetic. System-generated thumbnails, your own marketing assets, and media from trusted internal sources don't need checks. Deduplicate. Hash uploaded files and cache results, since the same meme or stock photo can arrive thousands of times. Scan at the decision point. Check media when it's about to matter, at onboarding, at publication, at payout, rather than on every view. The same API slots into quite different products. KYC and identity verification. Check selfies and ID images at onboarding, before an account is approved. This is where strict mode and a mandatory review step earn their keep. Trust and safety. Screen uploaded images and video before they reach a public feed, routing flagged items to a moderation queue with flagged segments attached so moderators review only the relevant seconds. Newsrooms and fact-checking. Verify user-submitted footage before publication, with retain: true if you need an audit record of what was checked and when. Marketplaces. Check listing photos and seller verification images, where generated images are used to fake inventory or identity. Financial fraud prevention. Verify voice messages and video calls that request payments, using the voice endpoint alongside video for impersonation attempts targeting finance teams. Which plans include API access? Starter, Business, and Enterprise. The free tier offers 50 detections a month in the web app but doesn't include API access. How do I authenticate? With a Bearer token in the Authorization header. Keys are shown once at creation and hashed at rest, so store yours immediately in a secrets manager. Can I send a file instead of a URL? Yes. Send a multipart upload, or pass an HTTPS media url . One of the two is required. How should I handle long videos? Use a callback url . Video processes at roughly real time, and the API recommends webhooks for files over 60 seconds. Confirm results by fetching GET /api/v1/jobs/{id} rather than trusting the webhook payload directly, unless you're using an official SDK that verifies webhook signatures. What does strict mode do? It lowers the confidence threshold, increasing recall at the cost of precision. Use it where missing a deepfake is more expensive than flagging a real file. What happens to uploaded files? They're purged 60 seconds after the verdict by default. Set retain: true to keep a file for 30 days for audit purposes. Is the API SOC 2 certified? Not yet. DeepfakeDetector.ai lists SOC 2 as in progress. EU data residency is available on Business plans and above. How accurate is it? DeepfakeDetector.ai describes detection as probabilistic rather than absolute and returns a confidence score with every verdict. Test it against a sample of your own media before setting thresholds, since performance depends on the generators, compression, and content types your users actually upload.