Orivfy · Production API

Video Detection API

Version 4 integration guide for provenance checks, adaptive frame analysis, asynchronous scanning, and streamed forensic explanations.

API v4 Multipart video upload X-API-Key protected WebSocket tickets

Authentication

Protected REST requests require the permanent server-to-server key:

X-API-Key: YOUR_ORIVFY_API_KEY

The permanent key belongs in a backend secret store. Never ship it in browser JavaScript, mobile application bundles, URLs, or source control.

Interactive schema

Use Swagger’s Authorize control to set X-API-Key for protected REST operations.

Open Swagger UI →

Download OpenAPI JSON →

Service discovery JSON →

Endpoint overview

GET/v4/health — public health and model readiness
POST/v4/detect-video — synchronous detection
POST/v4/detect-video-async — queue a detection job
GET/v4/jobs — list recent video jobs
GET/v4/jobs/{job_id} — poll queued job state
POST/v4/ws-ticket — create one-time browser WebSocket ticket
WS/v4/ws/explain-video — forensic explanation stream

Synchronous video detection

Submit one video as the multipart field file.

curl -X POST   -H "X-API-Key: $ORIVFY_API_KEY"   -F "file=@sample.mp4"   https://mlvideo.orivfy.com/v4/detect-video

Python

import requests

with open("sample.mp4", "rb") as video:
    response = requests.post(
        "https://mlvideo.orivfy.com/v4/detect-video",
        headers={"X-API-Key": api_key},
        files={"file": ("sample.mp4", video, "video/mp4")},
        timeout=360,
    )
response.raise_for_status()
result = response.json()

Asynchronous jobs

POST video→Receive job_id→ Poll job→done or error
POST /v4/detect-video-async
GET  /v4/jobs/{job_id}

Job status: queued → processing → done | error

Send X-API-Key on both the upload request and every polling request.

Forensic explanation WebSocket

Browser clients first ask their trusted application backend to create a one-time ticket.

Main backend + API key→POST /v4/ws-ticket→ Single-use ticket→Browser WebSocket
POST /v4/ws-ticket
X-API-Key: YOUR_ORIVFY_API_KEY

{
  "ticket": "...",
  "expires_in": 120,
  "expires_at": "..."
}
const socket = new WebSocket(
  `wss://mlvideo.orivfy.com/v4/ws/explain-video?ticket=${encodeURIComponent(ticket)}`
);

socket.onopen = () => socket.send(JSON.stringify(detectionResult));
socket.onmessage = event => {
  const message = JSON.parse(event.data);
  // message.type: start | chunk | complete | error
};
Ticket expiry applies only to opening the connection. Once accepted, the ticket is consumed and Gemini may continue streaming for the lifetime of that socket.

Representative detection response

{
  "prediction": "AI-generated",
  "confidence": 0.93,
  "success": true,
  "source": "unknown AI",
  "detection_stage": "Stage 3",
  "video_duration": 8.4,
  "frame_count": 252,
  "successful_frames": 16,
  "ai_ratio": 0.875,
  "real_ratio": 0.125,
  "base64_frames": ["..."],
  "pipeline_results": { }
}

The exact response includes legacy-compatible fields used by existing Orivfy clients. Decode failures return a structured JSON result with prediction: "Error" and success: false.

Limits and status codes

ItemCurrent contract
Maximum upload100 MB by default
Maximum duration300 seconds by default
Accepted containersMP4, MOV, AVI, WebM, MKV, M4V, MPEG/MPG
Missing API key401 Unauthorized
Incorrect API key403 Forbidden
Authentication unconfigured503 Service Unavailable
Invalid upload400 or structured decode error
Invalid/consumed WS ticketWebSocket close code 4401