Red Paper Dashboard
Comprehensive Document Analysis & Plagiarism Detection
API Documentation
Integrate RedPaper plagiarism checking and AI detection into your application.
Authentication
All API requests require an API key. Generate one from API Key Management.
Send your key via the Authorization header:
You can also use Bearer prefix or pass api_key in POST body.
Base URL
Endpoints
multipart/form-data.
Api-Key YOUR_API_KEY.pdf .docx .doc .txt .rtf0 = auto scan — calculates credit cost, deducts credits, and starts scanning immediately. 1 = manual — calculates and reports cost via the credit_calculation webhook, then waits for you to call /scan/{scan_id}/start. Use action=1 when you want to confirm cost before charging.NA similarity. Case-insensitive.
Supported — English (default):
English.
Indian regional languages (18):
Assamese, Bangla, Bengali, Gujarati, Hindi, Kannada, Malayalam, Manipuri, Marathi, Oriya, Punjabi, Sanskrit, Santhali, Sindhi, Sinhala, Tamil, Telugu, Urdu.
Foreign languages (175+):
Arabic, Chinese (Simplified), Chinese (Traditional), French, German, Italian, Japanese, Korean, Portuguese, Russian, Spanish, Vietnamese, and many more (Afrikaans, Albanian, Amharic, Armenian, Azerbaijani, Basque, Belarusian, Bulgarian, Catalan, Croatian, Czech, Danish, Dutch, Estonian, Filipino, Finnish, Galician, Georgian, Greek, Haitian Creole, Hausa, Hebrew, Hungarian, Icelandic, Indonesian, Irish, Javanese, Kazakh, Khmer, Kurdish, Kyrgyz, Lao, Latin, Latvian, Lithuanian, Macedonian, Malay, Maltese, Mongolian, Myanmar, Nepali, Norwegian, Pashto, Polish, Romanian, Serbian, Slovak, Slovenian, Somali, Swahili, Swedish, Tagalog, Tajik, Tamil, Thai, Turkish, Ukrainian, Urdu, Uzbek, Welsh, Yiddish, Yoruba, Zulu, …).
⚠ AI detection is not supported for non-English languages. If you pass any non-English language (regional or foreign) with
include_ai=true, AI detection is silently disabled — only the plagiarism similarity score and PDF are produced. No ai_report_ready webhook will fire.
.png .jpg .jpeg .svg .webp#2563eb).action=1 workflow — deducts credits, submits the staged file to DrillBit, and begins scanning. Not needed for action=0 (which auto-starts).
Api-Key YOUR_API_KEY400 if status is not cost_checked or staging file is missing. 402 if subscription expired or credits insufficient.
Api-Key YOUR_API_KEYplagiarism_report_ready and ai_report_ready indicate whether each PDF is downloadable yet. The plagiarism PDF lands first; the AI PDF typically follows minutes to a few hours later. Poll this endpoint or wait for the report_ready webhook to know when each becomes available.
Api-Key YOUR_API_KEYai_percentage, human_percentage only appear when AI detection is enabled. cert_no only appears for completed scans.
Content-Type: application/pdf.
Api-Key YOUR_API_KEYContent-Disposition: attachment)
Content-Disposition: attachment)
Api-Key YOUR_API_KEYWebhooks
Pass a webhook_url when submitting a scan to receive real-time notifications.
The plagiarism PDF and the AI detection PDF are generated independently. The plagiarism report is typically ready within 5–10 minutes; the AI report can take an additional few minutes to a few hours. Your
webhook_url may receive up to two completion events for one scan:
report_ready— fires as soon as the plagiarism PDF is ready.ai_report_urlin this payload may be empty.ai_report_ready— fires later when the AI PDF lands. Only sent wheninclude_ai=true.
scan_id so you can correlate them. Alternatively, poll /status for plagiarism_report_ready / ai_report_ready flags.
credit_calculation
Sent immediately after submission with the calculated credit cost. For action=0 (auto), credits are deducted and the scan starts right away — no further action needed. For action=1 (manual), the scan waits for your /scan/{scan_id}/start call before deducting credits.
insufficient_credits
Sent when the scan cannot start due to insufficient credits or an expired subscription. The scan is not consumed — top up credits and resubmit.
scan_completed
Sent when scan completes successfully:
scan_error
Sent when scan fails:
report_ready
Sent when the plagiarism PDF report has been generated and is ready for download. If include_ai=true AND the AI PDF happens to be ready at the same time, ai_report_url is also populated. More commonly, the AI PDF lands later — in that case ai_report_url is empty and you'll receive a separate ai_report_ready event when it becomes available.
ai_report_ready
Sent when the AI detection PDF report becomes available. This event fires separately from report_ready because DrillBit's AI report generation can lag the plagiarism one by several minutes to a few hours. Only fired when include_ai=true was passed at submission. Idempotent — delivered exactly once per scan (use the existing scan_id to match against your records).
Error Codes
| Status | Meaning |
|---|---|
400 | Bad request — missing or invalid parameters |
401 | Unauthorized — invalid or missing API key |
402 | Payment required — insufficient credits or expired subscription |
404 | Not found — scan or report doesn't exist |
405 | Method not allowed — wrong HTTP method |
500 | Server error — something went wrong on our end |
All errors return:
Quick Start — Submit a Scan
curl -X POST https://www.checkplagiarism.ai/api/plagcheck/scan \ -H "Authorization: Api-Key YOUR_API_KEY" \ -F "scan_id=your-unique-scan-id" \ -F "file=@document.pdf" \ -F "webhook_url=https://yoursite.com/webhook" \ -F "action=0" \ -F "include_ai=true" \ # Optional parameters -F "filename=my-report.pdf" \ -F "language=Hindi" \ # English (default), Indian regional, or foreign (Arabic, Chinese, French, German, Japanese, Spanish, ...) # Branding (optional) -F "custom_logo=@logo.png" \ -F "title_color=#2563eb" \ -F "report_title=My Company Report" \ -F "report_subtitle=Plagiarism Analysis" \ -F "submitted_by=John Doe"
import requests url = "https://www.checkplagiarism.ai/api/plagcheck/scan" headers = {"Authorization": "Api-Key YOUR_API_KEY"} with open("document.pdf", "rb") as f: response = requests.post( url, headers=headers, files={ "file": f, # "custom_logo": open("logo.png", "rb"), # optional }, data={ "scan_id": "your-unique-scan-id", "webhook_url": "https://yoursite.com/webhook", "include_ai": "true", # Optional parameters # "filename": "my-report.pdf", # Branding # "title_color": "#2563eb", # "report_title": "My Company Report", # "report_subtitle": "Plagiarism Analysis", # "submitted_by": "John Doe", } ) print(response.json())
const fs = require("fs"); const form = new FormData(); form.append("scan_id", "your-unique-scan-id"); form.append("file", fs.createReadStream("document.pdf")); form.append("webhook_url", "https://yoursite.com/webhook"); form.append("include_ai", "true"); // Optional parameters // form.append("filename", "my-report.pdf"); // Branding // form.append("custom_logo", fs.createReadStream("logo.png")); // form.append("title_color", "#2563eb"); // form.append("report_title", "My Company Report"); // form.append("report_subtitle", "Plagiarism Analysis"); // form.append("submitted_by", "John Doe"); const res = await fetch("https://www.checkplagiarism.ai/api/plagcheck/scan", { method: "POST", headers: { "Authorization": "Api-Key YOUR_API_KEY" }, body: form, }); const data = await res.json(); console.log(data);
<?php $url = "https://www.checkplagiarism.ai/api/plagcheck/scan"; $ch = curl_init($url); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_HTTPHEADER, [ "Authorization: Api-Key YOUR_API_KEY" ]); curl_setopt($ch, CURLOPT_POSTFIELDS, [ "scan_id" => "your-unique-scan-id", "file" => new CURLFile("document.pdf"), "webhook_url" => "https://yoursite.com/webhook", "include_ai" => "true", // Optional parameters // "filename" => "my-report.pdf", // Branding // "custom_logo" => new CURLFile("logo.png"), // "title_color" => "#2563eb", // "report_title" => "My Company Report", // "report_subtitle" => "Plagiarism Analysis", // "submitted_by" => "John Doe", ]); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); $response = curl_exec($ch); curl_close($ch); echo $response;
import java.io.*; import java.net.http.*; import java.nio.file.*; var boundary = "----FormBoundary" + System.currentTimeMillis(); var filePath = Path.of("document.pdf"); var fileBytes = Files.readAllBytes(filePath); var body = new StringBuilder(); body.append("--" + boundary + "\r\n"); body.append("Content-Disposition: form-data; name=\"file\"; filename=\"document.pdf\"\r\n"); body.append("Content-Type: application/pdf\r\n\r\n"); // append file bytes, then add text fields: // scan_id, webhook_url, include_ai // Optional: filename // Branding: title_color, report_title, report_subtitle, // submitted_by, custom_logo (file) var client = HttpClient.newHttpClient(); var request = HttpRequest.newBuilder() .uri(URI.create("https://www.checkplagiarism.ai/api/plagcheck/scan")) .header("Authorization", "Api-Key YOUR_API_KEY") .header("Content-Type", "multipart/form-data; boundary=" + boundary) .POST(HttpRequest.BodyPublishers.ofByteArray(bodyBytes)) .build(); var response = client.send(request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.body());
package main import ( "bytes" "fmt" "io" "mime/multipart" "net/http" "os" ) func main() { body := &bytes.Buffer{} writer := multipart.NewWriter(body) file, _ := os.Open("document.pdf") part, _ := writer.CreateFormFile("file", "document.pdf") io.Copy(part, file) writer.WriteField("scan_id", "your-unique-scan-id") writer.WriteField("webhook_url", "https://yoursite.com/webhook") writer.WriteField("include_ai", "true") // Optional parameters // writer.WriteField("filename", "my-report.pdf") // Branding // writer.WriteField("title_color", "#2563eb") // writer.WriteField("report_title", "My Company Report") // writer.WriteField("report_subtitle", "Plagiarism Analysis") // writer.WriteField("submitted_by", "John Doe") writer.Close() req, _ := http.NewRequest("POST", "https://www.checkplagiarism.ai/api/plagcheck/scan", body) req.Header.Set("Authorization", "Api-Key YOUR_API_KEY") req.Header.Set("Content-Type", writer.FormDataContentType()) resp, _ := http.DefaultClient.Do(req) respBody, _ := io.ReadAll(resp.Body) fmt.Println(string(respBody)) }
Check Status
curl -X POST https://www.checkplagiarism.ai/api/plagcheck/status/SCAN_ID \ -H "Authorization: Api-Key YOUR_API_KEY"
response = requests.post(
"https://www.checkplagiarism.ai/api/plagcheck/status/SCAN_ID",
headers={"Authorization": "Api-Key YOUR_API_KEY"}
)
print(response.json())POST /api/plagcheck/status/SCAN_ID HTTP/1.1 Host: www.checkplagiarism.ai Authorization: Api-Key YOUR_API_KEY
const res = await fetch("https://www.checkplagiarism.ai/api/plagcheck/status/SCAN_ID", { method: "POST", headers: { "Authorization": "Api-Key YOUR_API_KEY" }, }); console.log(await res.json());
$ch = curl_init("https://www.checkplagiarism.ai/api/plagcheck/status/SCAN_ID"); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_HTTPHEADER, ["Authorization: Api-Key YOUR_API_KEY"]); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); echo curl_exec($ch);
var client = HttpClient.newHttpClient(); var request = HttpRequest.newBuilder() .uri(URI.create("https://www.checkplagiarism.ai/api/plagcheck/status/SCAN_ID")) .header("Authorization", "Api-Key YOUR_API_KEY") .POST(HttpRequest.BodyPublishers.noBody()) .build(); var response = client.send(request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.body());
require "net/http" require "json" uri = URI("https://www.checkplagiarism.ai/api/plagcheck/status/SCAN_ID") req = Net::HTTP::Post.new(uri) req["Authorization"] = "Api-Key YOUR_API_KEY" res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) } puts JSON.parse(res.body)
req, _ := http.NewRequest("POST", "https://www.checkplagiarism.ai/api/plagcheck/status/SCAN_ID", nil) req.Header.Set("Authorization", "Api-Key YOUR_API_KEY") resp, _ := http.DefaultClient.Do(req) body, _ := io.ReadAll(resp.Body) fmt.Println(string(body))
Get Report
curl -X POST https://www.checkplagiarism.ai/api/plagcheck/reports/SCAN_ID \ -H "Authorization: Api-Key YOUR_API_KEY"
response = requests.post(
"https://www.checkplagiarism.ai/api/plagcheck/reports/SCAN_ID",
headers={"Authorization": "Api-Key YOUR_API_KEY"}
)
print(response.json())POST /api/plagcheck/reports/SCAN_ID HTTP/1.1 Host: www.checkplagiarism.ai Authorization: Api-Key YOUR_API_KEY
const res = await fetch("https://www.checkplagiarism.ai/api/plagcheck/reports/SCAN_ID", { method: "POST", headers: { "Authorization": "Api-Key YOUR_API_KEY" }, }); console.log(await res.json());
$ch = curl_init("https://www.checkplagiarism.ai/api/plagcheck/reports/SCAN_ID"); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_HTTPHEADER, ["Authorization: Api-Key YOUR_API_KEY"]); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); echo curl_exec($ch);
var client = HttpClient.newHttpClient(); var request = HttpRequest.newBuilder() .uri(URI.create("https://www.checkplagiarism.ai/api/plagcheck/reports/SCAN_ID")) .header("Authorization", "Api-Key YOUR_API_KEY") .POST(HttpRequest.BodyPublishers.noBody()) .build(); var response = client.send(request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.body());
require "net/http" require "json" uri = URI("https://www.checkplagiarism.ai/api/plagcheck/reports/SCAN_ID") req = Net::HTTP::Post.new(uri) req["Authorization"] = "Api-Key YOUR_API_KEY" res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) } puts JSON.parse(res.body)
req, _ := http.NewRequest("POST", "https://www.checkplagiarism.ai/api/plagcheck/reports/SCAN_ID", nil) req.Header.Set("Authorization", "Api-Key YOUR_API_KEY") resp, _ := http.DefaultClient.Do(req) body, _ := io.ReadAll(resp.Body) fmt.Println(string(body))
Download Certificate
curl -X GET "https://www.checkplagiarism.ai/api/plagcheck/reports/SCAN_ID/certificate" \ -o certificate.pdf
response = requests.get(
"https://www.checkplagiarism.ai/api/plagcheck/reports/SCAN_ID/certificate"
)
with open("certificate.pdf", "wb") as f:
f.write(response.content)GET /api/plagcheck/reports/SCAN_ID/certificate HTTP/1.1 Host: www.checkplagiarism.ai
const res = await fetch("https://www.checkplagiarism.ai/api/plagcheck/reports/SCAN_ID/certificate"); const blob = await res.blob(); // Save blob as file
$ch = curl_init("https://www.checkplagiarism.ai/api/plagcheck/reports/SCAN_ID/certificate"); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); file_put_contents("certificate.pdf", curl_exec($ch));
import java.net.http.*; import java.nio.file.*; HttpClient client = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder() .uri(URI.create("https://www.checkplagiarism.ai/api/plagcheck/reports/SCAN_ID/certificate")) .GET() .build(); HttpResponse<byte[]> response = client.send(request, HttpResponse.BodyHandlers.ofByteArray()); Files.write(Path.of("certificate.pdf"), response.body());
require 'net/http' uri = URI("https://www.checkplagiarism.ai/api/plagcheck/reports/SCAN_ID/certificate") response = Net::HTTP.get_response(uri) File.open("certificate.pdf", "wb") { |f| f.write(response.body) }
resp, err := http.Get("https://www.checkplagiarism.ai/api/plagcheck/reports/SCAN_ID/certificate") if err != nil { log.Fatal(err) } defer resp.Body.Close() body, _ := io.ReadAll(resp.Body) os.WriteFile("certificate.pdf", body, 0644)
Download Report PDF
curl -X POST https://www.checkplagiarism.ai/api/plagcheck/reports/SCAN_ID/download \ -H "Authorization: Api-Key YOUR_API_KEY" \ -o report.pdf
response = requests.post(
"https://www.checkplagiarism.ai/api/plagcheck/reports/SCAN_ID/download",
headers={"Authorization": "Api-Key YOUR_API_KEY"}
)
with open("report.pdf", "wb") as f:
f.write(response.content)POST /api/plagcheck/reports/SCAN_ID/download HTTP/1.1 Host: www.checkplagiarism.ai Authorization: Api-Key YOUR_API_KEY
const res = await fetch("https://www.checkplagiarism.ai/api/plagcheck/reports/SCAN_ID/download", { method: "POST", headers: { "Authorization": "Api-Key YOUR_API_KEY" }, }); const blob = await res.blob(); // Save blob as file
$ch = curl_init("https://www.checkplagiarism.ai/api/plagcheck/reports/SCAN_ID/download"); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_HTTPHEADER, ["Authorization: Api-Key YOUR_API_KEY"]); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); file_put_contents("report.pdf", curl_exec($ch));
import java.net.http.*; import java.nio.file.*; HttpClient client = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder() .uri(URI.create("https://www.checkplagiarism.ai/api/plagcheck/reports/SCAN_ID/download")) .header("Authorization", "Api-Key YOUR_API_KEY") .POST(HttpRequest.BodyPublishers.noBody()) .build(); HttpResponse<byte[]> response = client.send(request, HttpResponse.BodyHandlers.ofByteArray()); Files.write(Path.of("report.pdf"), response.body());
require 'net/http' uri = URI("https://www.checkplagiarism.ai/api/plagcheck/reports/SCAN_ID/download") http = Net::HTTP.new(uri.host, uri.port) http.use_ssl = true request = Net::HTTP::Post.new(uri) request["Authorization"] = "Api-Key YOUR_API_KEY" response = http.request(request) File.open("report.pdf", "wb") { |f| f.write(response.body) }
req, _ := http.NewRequest("POST", "https://www.checkplagiarism.ai/api/plagcheck/reports/SCAN_ID/download", nil) req.Header.Set("Authorization", "Api-Key YOUR_API_KEY") resp, err := http.DefaultClient.Do(req) if err != nil { log.Fatal(err) } defer resp.Body.Close() body, _ := io.ReadAll(resp.Body) os.WriteFile("report.pdf", body, 0644)