API Documentation

Check images and videos for AI from your own apps with our simple REST API.

Base URL: https://api.isitai.com

Quick Start

Get started with the Is It AI? API in three steps.

1

Get your API key

Create a free account, then create a key on your API keys page: the key is your bearer token. Every account can create an API key; checks use your credits.

2

Make a request

Send an image URL to the detection endpoint.

Request
# Detect an image by URL
curl -X POST "https://api.isitai.com/detect-img?image_url=https://example.com/image.jpg" \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -H "accept: application/json"
3

Get results

Receive a detailed AI detection verdict with confidence scores.

Response
{
  "predicted_label": "AI",
  "probability": 0.92,
  "potential_method": "midjourney",
  "method_probability": 0.85,
  "NSFW": "No",
  "NSFW_probability": 0.02
}

Authentication

The API uses JWT bearer tokens. Authenticate with your email and API secret to get a token, then include it in the Authorization header of every request.

Step 1: Get your API secret

Your API secret is available on your API keys page. This is different from your account password. It is used only to sign in to the API.

Step 2: Request an access token

POST your account email (as username) and API secret as JSON to the /login endpoint to receive a JWT access token.

Get Token
curl -X POST https://api.isitai.com/login \
  -H "Content-Type: application/json" \
  -d '{"username": "you@example.com", "password": "YOUR_API_SECRET"}'
Token Response
{
  "access_token": "eyJhbGciOiJIUzI1NiIs..."
}

Step 3: Use the token

Include the token in the Authorization header as a Bearer token on all subsequent requests.

Header
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...
Token lifecycle: Tokens last about 90 days. When one expires, create a new key on your API keys page or call /login again. You can also revoke a token early using the /revoke-token endpoint. /login allows 5 requests a minute.

Endpoint Reference

All endpoints use the base URL https://api.isitai.com.

POST /login

Authenticate and receive a JWT access token.

Headers

HeaderValue
Content-Typeapplication/json

JSON Body

ParameterTypeRequiredDescription
usernamestringYesYour account email address
passwordstringYesYour API secret (from the API keys page)

Response

200 OK
{
  "access_token": "eyJhbGciOiJIUzI1NiIs..."
}

POST /detect-img

Analyze an image for AI-generated content. Supports two modes: image URL (query parameter) or file upload (multipart form).

Headers

HeaderValue
AuthorizationBearer YOUR_ACCESS_TOKEN
acceptapplication/json

Option A: Image URL

ParameterInTypeDescription
image_urlquerystringURL of the image to analyze
cURL (URL mode)
curl -X POST "https://api.isitai.com/detect-img?image_url=https://example.com/photo.jpg" \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -H "accept: application/json"

Option B: File Upload

ParameterInTypeDescription
filebody (multipart)fileImage file to analyze
cURL (file upload)
curl -X POST https://api.isitai.com/detect-img \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -H "accept: application/json" \
  -F "file=@/path/to/image.jpg"

Response

200 OK
{
  "predicted_label": "AI",
  "probability": 0.92,
  "potential_method": "midjourney",
  "method_probability": 0.85,
  "NSFW": "No",
  "NSFW_probability": 0.02
}

POST /detect-img/batch

Check up to 20 images in one request, 1 credit each. Upload them as files, or send image_urls as a comma-separated list. If one image cannot be read or downloaded, the whole request fails with 400 and nothing is charged. A failed image, or one you have no credits left for, is not charged. Match the results to your images by index.

ParameterInTypeDescription
filesbody (multipart)fileUp to 20 images, each up to 10 MB (repeat the field)
image_urlsquerystringUp to 20 image URLs, separated by commas
cURL (batch upload)
curl -X POST https://api.isitai.com/detect-img/batch \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -F "files=@/path/to/first.jpg" \
  -F "files=@/path/to/second.png"
200 OK
{
  "results": [
    { "index": 0, "success": true, "predicted_label": "AI", "probability": 0.92, ... },
    { "index": 1, "success": false, "error": "Monthly quota exhausted and no credits available", "code": "QUOTA_EXHAUSTED" }
  ],
  "quota": { "monthly_limit": 200, "monthly_used": 200, "monthly_remaining": 0, "credits_remaining": 0 }
}

Face swap option (face_swap=true)

Adds the face swap check to an image check: did someone swap or fake a real person's face? The check uses 2 credits instead of 1. Only useful for images with people. Works the same on /detect-img/batch (2 credits per image).

ParameterInTypeDescription
face_swapquerybooleantrue adds face_swap ("Yes" or "No") and face_swap_probability (0 to 1) to the answer. Default false.

POST /detect-video

Checks a video shorter than 60 s (up to 50 MB; MP4, MOV, WebM, MKV or AVI) one frame every 2 seconds. Videos are analyzed one at a time, so the check goes into a queue: the answer is the result, or 202 with a job_id to poll. Price: 6 credits for each started 10 s (12 with face_swap=true), counted in whole seconds, rounded down. You can have 3 videos queued or running at a time; a fourth gets 429 TOO_MANY_VIDEO_JOBS.

ParameterInTypeDescription
filebody (multipart)fileThe video, or use video_url
video_urlquerystringA direct link to a video file (http or https)
face_swapquerybooleanAlso run the face swap check (doubles the price)
waitqueryintegerSeconds to wait for the result, 0 to 60 (default 30). Not done by then: 202
cURL
curl -X POST "https://api.isitai.com/detect-video?wait=30" \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -F "file=@/path/to/clip.mp4"

Queued

202 Accepted
{
  "job_id": 48213,
  "status": "queued",
  "position": 2,
  "duration_seconds": 23,
  "poll_url": "/detect-video/48213",
  "quota": { "credits_used": 18, ... }
}

The credits are taken when the job is queued and come back if it fails. Save the job_id at once.

GET /detect-video/{job_id}

Where a video check stands: 202 while it is queued or running (with its place in line), 200 with the result, 410 if the result was deleted (90 days after the check), or the stored error of a failed job (its credits were refunded). Poll every few seconds. You can read only your own jobs: any other job_id gets 404.

Result

200 OK
{
  "predicted_label": "AI",
  "probability": 0.95,
  "potential_method": "sora",
  "NSFW": "No",
  "frames_checked": 12,
  "frames": [
    { "time_seconds": 0.0, "ai_probability": 0.08, "NSFW_probability": 0.01 },
    { "time_seconds": 2.0, "ai_probability": 0.95, "NSFW_probability": 0.01 },
    ...
  ],
  "job_id": 48213,
  "quota": { "credits_used": 18, ... }
}

The highest frame decides each verdict: one AI frame is enough to call the video AI-generated. With face_swap=true, the answer also has face_swap and face_swap_probability, and so does each frame.

GET /pricing

The price of every kind of check, in credits. No token needed.

200 OK
{
  "image": { "credits": 1, "with_face_swap": 2 },
  "video": {
    "credits_per_started_10_seconds": 6,
    "face_swap_factor": 2,
    "max_seconds": 60,
    "max_megabytes": 50,
    "examples": { "10s": 6, "30s": 18, "59s": 36, "30s_with_face_swap": 36 }
  },
  "notes": "Lengths are counted in whole seconds, rounded down. A failed detection does not use credits."
}

GET /consumption/

Retrieve the total number of credits your account has used, all time (website and API together).

Note: The trailing slash is required for this endpoint.

Headers

HeaderValue
AuthorizationBearer YOUR_ACCESS_TOKEN
cURL
curl https://api.isitai.com/consumption/ \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN"

Response

200 OK
{
  "username": "you@example.com",
  "consumption": 142
}

POST /revoke-token

Revoke the token you send. After revocation, you will need a new key or a new token from /login.

Headers

HeaderValue
AuthorizationBearer YOUR_ACCESS_TOKEN
cURL
curl -X POST https://api.isitai.com/revoke-token \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN"

Response

200 OK
{
  "message": "Token revoked successfully!"
}

Response Fields

The detection endpoint (/detect-img) returns the following fields.

FieldTypeDescription
predicted_label string "AI" or "Human" - the detection verdict
probability number Confidence score from 0 to 1 (e.g. 0.92 = 92% confidence)
potential_method string Most likely AI generator (e.g. "midjourney", "stable_diffusion", "dalle"). Only when the label is "AI" and a generator was named.
method_probability number Confidence score for the generator (0 to 1). Only with potential_method.
NSFW string "Yes" or "No" - whether the image contains NSFW content
NSFW_probability number Confidence score for the NSFW classification (0 to 1)
face_swap, face_swap_probability string, number With face_swap=true only: "Yes" or "No", and its chance from 0 to 1
verdict_source string Only for a file with Content Credentials: "c2pa" when a trusted signed label said the image is AI-generated (the label decided; probability is 0.99), else "model"
provenance object Only for a file with Content Credentials: c2pa (always true), trusted, signed_by, generator, source_type, ai_generated, ai_edited. No label never means "human-made".
quota object credits_used (this check), source ("subscription", "credit" or "mixed": plan credits are used first, then bought credits), monthly_limit, monthly_used, monthly_remaining and credits_remaining (bought credits left)

Error Handling

The API uses standard HTTP status codes. Errors include a JSON body with a message.

StatusMeaningCommon Cause
200SuccessRequest completed successfully
202AcceptedA video is queued or running: poll its job_id
400Bad RequestThe file could not be read, the link failed or a parameter is missing, or the video is 60 s or longer. Not charged
401UnauthorizedMissing, invalid, expired or revoked token
403ForbiddenQUOTA_EXHAUSTED: no plan credits or bought credits left. INSUFFICIENT_CREDITS (with credits_required): not enough credits for a face swap check or a video
404Not FoundNo video job with this job_id for your account
410GoneA video result deleted 90 days after the check
413Payload Too LargeThe file is over its limit (images 10 MB, videos 50 MB)
422Unprocessable EntityA parameter is not valid, for example wait=90
429Too Many RequestsRATE_LIMITED: over 120 check requests a minute for your account (or 5 a minute on /login). Wait for Retry-After and retry
429Too Many RequestsTOO_MANY_VIDEO_JOBS: you already have 3 videos queued or running. Wait until one is done
500Internal Server ErrorUnexpected error on our side - retry or contact support
502Bad GatewayThe detection service is down for a moment. Try again shortly. Not charged
503Service BusySERVICE_BUSY: the detection service is busy. Try again after Retry-After (10 s). Not charged

Error Response Format

Error Response
{
  "detail": "Monthly quota exhausted and no credits available",
  "code": "QUOTA_EXHAUSTED"
}

Every error has a detail message. Some also have a code you can check in your app, such as QUOTA_EXHAUSTED, RATE_LIMITED or SERVICE_BUSY.

Supported Formats & Limits

Image Types

  • JPEG / JPG
  • PNG
  • WebP
  • GIF (first frame)
  • AVIF, BMP and TIFF

Video Types

  • MP4 and MOV
  • WebM and MKV
  • AVI

Limits

  • Max image size: 10 MB
  • Videos: shorter than 60 s, up to 50 MB
  • Batch: up to 20 images per request
  • Up to 3 videos queued or running at a time
  • Up to 120 check requests a minute per account
  • Credits from your plan first, then bought credits

Best Practices

  • Use images at least 256×256 px for best accuracy
  • Avoid heavily compressed or cropped images
  • Re-authenticate when you receive a 401 response

Code Examples

Full authentication + detection flow in popular languages.

Detect by Image URL

cURL
# 1. Get access token
TOKEN=$(curl -s -X POST https://api.isitai.com/login \
  -H "Content-Type: application/json" \
  -d '{"username": "you@example.com", "password": "YOUR_API_SECRET"}' \
  | jq -r '.access_token')

# 2. Detect image
curl -X POST "https://api.isitai.com/detect-img?image_url=https://example.com/photo.jpg" \
  -H "Authorization: Bearer $TOKEN" \
  -H "accept: application/json"
Python
import requests

# 1. Authenticate
auth = requests.post("https://api.isitai.com/login", json={
    "username": "you@example.com",
    "password": "YOUR_API_SECRET"
})
token = auth.json()["access_token"]

# 2. Detect by URL
response = requests.post(
    "https://api.isitai.com/detect-img",
    params={"image_url": "https://example.com/photo.jpg"},
    headers={
        "Authorization": f"Bearer {token}",
        "accept": "application/json"
    }
)
result = response.json()
print(f"Verdict: {result['predicted_label']} ({result['probability']:.0%} confidence)")
Node.js
// 1. Authenticate
const authRes = await fetch("https://api.isitai.com/login", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({ username: "you@example.com", password: "YOUR_API_SECRET" })
});
const { access_token } = await authRes.json();

// 2. Detect by URL
const imageUrl = encodeURIComponent("https://example.com/photo.jpg");
const res = await fetch(
  `https://api.isitai.com/detect-img?image_url=${imageUrl}`,
  {
    method: "POST",
    headers: {
      "Authorization": `Bearer ${access_token}`,
      "accept": "application/json"
    }
  }
);
const result = await res.json();
console.log(`Verdict: ${result.predicted_label} (${(result.probability * 100).toFixed(0)}% confidence)`);

Detect by File Upload

cURL
curl -X POST https://api.isitai.com/detect-img \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -H "accept: application/json" \
  -F "file=@/path/to/image.jpg"
Python
import requests

token = "YOUR_ACCESS_TOKEN"

with open("image.jpg", "rb") as f:
    response = requests.post(
        "https://api.isitai.com/detect-img",
        headers={
            "Authorization": f"Bearer {token}",
            "accept": "application/json"
        },
        files={"file": f}
    )
print(response.json())
Node.js
import { readFileSync } from "fs";

const token = "YOUR_ACCESS_TOKEN";
const formData = new FormData();
formData.append("file", new Blob([readFileSync("image.jpg")]), "image.jpg");

const res = await fetch("https://api.isitai.com/detect-img", {
  method: "POST",
  headers: {
    "Authorization": `Bearer ${token}`,
    "accept": "application/json"
  },
  body: formData
});
console.log(await res.json());

API Pricing

Every account can create an API key; checks use your credits, the same as on the website: 1 per image (2 with the face swap check), 6 per started 10 s of video (12 with the face swap check). Your monthly plan credits are used first, then bought credits.

View Plans & Pricing

Start Building with Is It AI?

Every account can create an API key; checks use your credits. Create a key and start checking images and videos from your own apps.