> ## Knowledge Base Index
> Fetch the complete knowledge base index at: https://help.undetectable.ai/sitemap.xml
> Use this file to discover available pages before exploring further.
> Pure-Markdown content can be obtained by appending a '.md' suffix to the content URLs listed in the sitemap (without the trailing slash).

# AI Video Detector API

# Try it Out

You can explore and try the API with your browser via FastAPI docs: `https://ai-video-detect.undetectable.ai/docs`

# Authentication

Undetectable.AI 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](https://undetectable.ai/develop).

UD 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 Video Detector

### Detect

The AI Video Detection workflow consists of two steps:

* Submit the video for detection (multipart upload or URL)
* Query the job to retrieve results

#### Detection Models

Select which ML model runs during the detection pipeline using the optional `model` parameter. If omitted, `generic` is used.

* `generic` (default): General-purpose AI video detection model
* `faceswap`: Dedicated Face Swap video detection model

Both models use the same detection pipeline (metadata → watermark → ML) and return the same response format. Invalid `model` values return **422**.

#### 1. Submit the Video

Upload a video file directly to the API, or submit a video URL. The server will validate the file. 
<!-- and internally upload it to storage for processing. -->

**Supported File Formats:** mp4, mov, avi, mkv, webm

**File Size Limits:**
* Minimum file size: 1KB
* Maximum file size: 100MB

**Submit via file upload**

Endpoint:
| **${color}[#0093ee](POST) ** `https://ai-video-detect.undetectable.ai/detect-file`

Headers:
* `key`: Your API key (required)
* `email`: Optional email address
* `userkey`: Optional integration user key


Multipart form-data:
* `file`: The video to analyze (required)
* `model`: Detection model to use i.e `generic` or `faceswap` (optional, default: `generic`)

#### Example Request

```
curl -X POST \
'https://ai-video-detect.undetectable.ai/detect-file' \
-H 'accept: application/json' \
-H 'key: YOUR-API-KEY-GOES-HERE' \
-F 'file=@/path/to/video.mp4;type=video/mp4'
```

**Face Swap model example:**

```
curl -X POST \
'https://ai-video-detect.undetectable.ai/detect-file' \
-H 'accept: application/json' \
-H 'key: YOUR-API-KEY-GOES-HERE' \
-F 'file=@/path/to/video.mp4;type=video/mp4' \
-F 'model=faceswap'
```

**Optional Parameters:**
* `document_type`: Type of document (default: `Video`)
* `email`: Email address for processing
* `model`: Detection model i.e `generic` or `faceswap` (default: `generic`)

#### Submit via URL

Endpoint:
| **${color}[#0093ee](POST) ** `https://ai-video-detect.undetectable.ai/detect`

Headers:
* `Content-Type`: `application/json`

Body (JSON):
* `key`: Your API key (required)
* `url`: https://ai-video-detector-prod.nyc3.digitaloceanspaces.com/<FILE_PATH>
* `model`: Detection model to use i.e `generic` or `faceswap` (optional, default: `generic`)

#### Example Request

```
curl -X POST \
'https://ai-video-detect.undetectable.ai/detect' \
-H 'accept: application/json' \
-H 'Content-Type: application/json' \
-d '{
  "key": "YOUR-API-KEY-GOES-HERE",
  "url": "https://example.com/video.mp4",
  "model": "generic"
}'
```

**Face Swap model example:**

```
curl -X POST \
'https://ai-video-detect.undetectable.ai/detect' \
-H 'accept: application/json' \
-H 'Content-Type: application/json' \
-d '{
  "key": "YOUR-API-KEY-GOES-HERE",
  "url": "https://example.com/video.mp4",
  "model": "faceswap"
}'
```

**Optional Parameters:**
* `document_type`: Type of document (default: `Video`)
* `email`: Email address for processing
* `model`: Detection model i.e `generic` or `faceswap` (default: `generic`)

#### Example Response

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

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

#### 2. Query Detection Status and Results

After submitting, poll the `/query` endpoint with the job `id` to retrieve status and results.

Endpoint:
* POST `https://ai-video-detect.undetectable.ai/query`

Body:

```json
{ "id": "JOB-ID-GOES-HERE" }
```

Example:

```bash
curl -X POST 'https://ai-video-detect.undetectable.ai/query' \
  -H 'accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{"id":"JOB-ID-GOES-HERE"}'
```

Example response:

```
{
    "id": "bfd136fc-666b-42d0-89cf-0e9690c98f21",
    "status": "done",
    "result": 0.101969311406719,
    "result_details": {
        "final_stage": "watermark",
        "metadata": {
            "status": "ok",
            "prediction": "no_detection",
            "confidence": 0.0
        },
        "watermark": {
            "prediction": "ai_generated (watermark)",
            "confidence": 1.0
        },
        "ml": {
            "aggregate": {
                "prob_fake": 0.1019693114067195,
                "label": "cancelled",
                "n_frames": 256,
                "latency_sec": 23.319
            }
        },
        "latency_sec": 24.017
    },
    "preview_url": null
}
```

### Result Details

* **status**: `pending`, `analyzing`, `done`, or `failed`
* **result**: Scalar score in [0.0, 1.0] derived from ML `prob_fake`
* **result_details**:
* **final_stage**: Last stage that contributed result: `metadata` or `watermark` or `ml`
* **metadata**:
    * Always sets `prediction: "no_detection"` and `confidence: 0.0`
    * Status is:
    * `reject` if ffprobe metadata contains the string "badcontainer" (case-insensitive)
    * `reencode` if it contains "reencode_me"
    * `ok` otherwise
    * If `status == "reject"`, the pipeline stops early and returns immediately with `final_stage: "metadata"`
* **watermark**:
    * Placeholder heuristic that samples frames and computes a pseudo-confidence from pixel variance
    * If confidence ≥ threshold (default `VIDEO_WATERMARK_THRESHOLD`, 0.5), it returns `prediction: "ai_generated (watermark)"`
    * If it predicts AI-generated, the ML stage is cancelled early and `final_stage` becomes `watermark`
* **ml**:
    * The selected detection model (`generic` or `faceswap`) runs on sampled frames
    * Returns `aggregate.prob_fake` in [0.0, 1.0] and `label` which is `"ai_generated"` if `prob_fake ≥ 0.5`, else `"no_detection"`
* **latency_sec**: Total pipeline time

---

#### Check User Credits

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

| **${color}[#0093ee](GET) ** `https://ai-video-detect.undetectable.ai/check-user-credits`

#### Example Request

```
curl -X 'GET' \
  'https://ai-video-detect.undetectable.ai/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
}
```

**Note:** For external integrations, only the `credits` field will be populated.

---

#### Health Check

Check the health status of the API server.

| **${color}[#0093ee](GET) ** `https://ai-video-detect.undetectable.ai/health`

#### Example Request

```
curl -X 'GET' \
  'https://ai-video-detect.undetectable.ai/health' \
  -H 'accept: application/json'
```

#### Example Response

```
{
    "status": "healthy"
}
```
---

# 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 Code | Meaning |
| ---- |
| 400 | Bad Request -- Your request is invalid. |
| 403 | Forbidden -- The API key is invalid, or there aren't sufficient credits (0.1 per word). |
| 404 | Not Found -- The specified resource doesn't exist. |
| 405 | Method Not Allowed -- You tried to access a resource with an invalid method. |
| 406 | Not Acceptable -- You requested a format that isn't JSON. |
| 410 | Gone -- The resource at this endpoint has been removed. |
| 422 | Invalid Request Body -- Your request body is formatted incorrectly or invalid or has missing parameters. |
| 429 | Too Many Requests -- You're sending too many requests! Slow it down! |
| 500 | Internal Server Error -- We had a problem with our server. Try again later. |
| 503 | Service 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 video processing
* **Solution**:

1. Check your remaining credits using `/check-user-credits`
2. Purchase additional credits if needed

## Input Validation Issues

### "Unsupported video type" (400)
* **Cause**: File format not supported
* **Solution**:

1. Convert the video to a supported format (MP4, MOV, AVI, MKV, WEBM)
2. Ensure the file extension and MIME type are correct

### "File size is too small" (400)
* **Cause**: Video file is below minimum size requirement
* **Solution**:

1. Use a larger video file (minimum 1KB)
2. Check if the file was corrupted during upload

### "File size exceeds limit" (400)
* **Cause**: Video file is too large
* **Solution**:

1. Compress, trim, or re-encode the video to reduce size (maximum 100MB)
2. Use a more efficient codec/container

### "Invalid file type" (400)
* **Cause**: File type validation failed (e.g., wrong MIME type or corrupted file)
* **Solution**:

1. Ensure the file is a valid video format
2. Verify the MIME type matches the file extension
3. Re-export or re-encode the file if necessary

### Invalid `model` value (422)
* **Cause**: The `model` parameter is not `generic` or `faceswap`
* **Solution**:

1. Omit `model` to use the default `generic` model
2. Set `model` to `generic` for general AI video detection
3. Set `model` to `faceswap` for Face Swap video detection

## Processing Issues

### Video status "failed"
* **Cause**: Processing failed (e.g., unreadable container, decode errors)
* **Solution**:

1. Ensure the container/codec is commonly supported (H.264/AAC in MP4 recommended)
2. Re-encode the video using a standard preset (e.g., ffmpeg) and re-upload
3. Ensure the file meets size and format requirements
4. Contact support if the issue persists

### "User not found"
* **Cause**: Invalid user ID
* **Solution**:

1. Verify your API key is correct and tied to an active account
2. Ensure the integration user is valid and active
3. Re-authenticate if needed

### "File metadata could not be fetched" (500)
* **Cause**: Unable to access or parse the uploaded file
* **Solution**:

1. Verify the upload completed successfully
2. Check the file is accessible and not corrupted
3. Try re-uploading the file

---