Get started
1
Before you begin
Before you start, ensure you have the following:
- An active Copyleaks account. If you don’t have one, sign up for free.
- You can find your API key on the API Dashboard.
2
Installation
Choose your preferred method for making API calls.
# macOS
brew install curl
# Ubuntu/Debian
sudo apt-get install curl
# Windows - download from https://curl.se
pip install copyleaks
npm install copyleaks
dotnet add package Copyleaks
# Or, in the Visual Studio Package Manager Console:
# Install-Package Copyleaks
composer require copyleaks/copyleaks
gem install copyleaks
<!-- Add to your pom.xml (requires Java 11+) -->
<dependency>
<groupId>com.copyleaks</groupId>
<artifactId>copyleaks</artifactId>
<version>6.0.0</version>
</dependency>
go get github.com/Copyleaks/[email protected]
cargo add copyleaks@2
cargo add tokio --features macros,rt-multi-thread
3
Login
To perform a scan, we first need to generate an access token. For that, we will use the login endpoint.
The API key can be found on the Copyleaks API Dashboard.Upon successful authentication, you will receive a token that must be attached to subsequent API calls via the
Authorization: Bearer <TOKEN> header.
This token remains valid for 48 hours.POST https://id.copyleaks.com/v3/account/login/api
Headers
Content-Type: application/json
Body
{
"email": "[email protected]",
"key": "00000000-0000-0000-0000-000000000000"
}
export COPYLEAKS_EMAIL="[email protected]"
export COPYLEAKS_API_KEY="your-api-key-here"
curl --request POST \
--url https://id.copyleaks.com/v3/account/login/api \
--header 'Accept: application/json' \
--header 'Content-Type: application/json' \
--data "{
\"email\": \"${COPYLEAKS_EMAIL}\",
\"key\": \"${COPYLEAKS_API_KEY}\"
}"
from copyleaks.copyleaks import Copyleaks
EMAIL_ADDRESS = "[email protected]"
API_KEY = "your-api-key-here"
# Login to Copyleaks
auth_token = Copyleaks.login(EMAIL_ADDRESS, API_KEY)
print("Logged successfully!\nToken:", auth_token)
const { Copyleaks } = require("copyleaks");
const EMAIL_ADDRESS = "[email protected]";
const API_KEY = "your-api-key-here";
const copyleaks = new Copyleaks();
// Login function
function loginToCopyleaks() {
return copyleaks.loginAsync(EMAIL_ADDRESS, API_KEY).then(
(loginResult) => {
console.log("Login successful!");
console.log("Access Token:", loginResult.access_token);
return loginResult;
},
(err) => {
console.error('Login failed:', err);
throw err;
}
);
}
loginToCopyleaks();
import classes.Copyleaks;
import models.response.CopyleaksAuthToken;
String EMAIL_ADDRESS = "[email protected]";
String API_KEY = "00000000-0000-0000-0000-000000000000";
// Login to Copyleaks
CopyleaksAuthToken authToken = null;
try {
authToken = Copyleaks.login(EMAIL_ADDRESS, API_KEY);
System.out.println("Logged in successfully!");
} catch (Exception e) {
System.out.println("Failed to login: " + e.getMessage());
System.exit(1);
}
using System;
using Copyleaks.SDK.V3.API;
const string EMAIL_ADDRESS = "[email protected]";
const string API_KEY = "your-api-key-here";
// Login to Copyleaks
var identityClient = new CopyleaksIdentityApi();
var loginResponse = await identityClient.LoginAsync(EMAIL_ADDRESS, API_KEY);
string authToken = loginResponse.Token;
Console.WriteLine("Logged in successfully!");
<?php
require_once(__DIR__ . '/vendor/autoload.php');
use Copyleaks\Copyleaks;
$EMAIL_ADDRESS = "[email protected]";
$API_KEY = "your-api-key-here";
// Login to Copyleaks
$copyleaks = new Copyleaks();
$authToken = $copyleaks->login($EMAIL_ADDRESS, $API_KEY);
echo "Logged in successfully!\n";
require 'copyleaks'
EMAIL_ADDRESS = "[email protected]"
API_KEY = "your-api-key-here"
# Login to Copyleaks
copyleaks = Copyleaks::API.new
auth_token = copyleaks.login(EMAIL_ADDRESS, API_KEY)
puts "Logged in successfully!"
Response
{
"access_token": "<ACCESS_TOKEN>",
".issued": "2025-07-31T10:19:40.0690015Z",
".expires": "2025-08-02T10:19:40.0690016Z"
}
4
Submit for scanning
Use the Submit File Endpoint to send content for analysis. We suggest you provide a unique
scanId for each submission.PUT https://api.copyleaks.com/v3/scans/submit/file/my-plagiarism-scan
Headers
Authorization: Bearer <YOUR_AUTH_TOKEN>
Content-Type: application/json
Body
{
"base64": "SGVsbG8gd29ybGQh",
"filename": "file.txt",
"properties": {
"webhooks": {
"status": "https://your-server.com/webhook/{STATUS}"
},
"sandbox": true
}
}
curl -X PUT "https://api.copyleaks.com/v3/scans/submit/file/my-plagiarism-scan" \
-H "Authorization: Bearer <YOUR_AUTH_TOKEN>" \
-H "Content-Type: application/json" \
-d '{
"base64": "SGVsbG8gd29ybGQh",
"filename": "file.txt",
"properties": {
"webhooks": {
"status": "https://your-server.com/webhook/{STATUS}"
},
"sandbox": true,
"scanning": {
"internet": true
},
"cheatDetection": false
}
}'
import base64
import random
from copyleaks.copyleaks import Copyleaks
from copyleaks.models.submit.document import FileDocument
from copyleaks.models.submit.properties.scan_properties import ScanProperties
from copyleaks.models.submit.properties.submit_webhooks import SubmitWebhooks
print("Submitting a new file...")
BASE64_FILE_CONTENT = base64.b64encode(b'Hello world').decode('utf8') # or read your file and convert it into BASE64 presentation.
FILENAME = "hello.txt"
scan_id = random.randint(100, 100000) # generate a random scan id
file_submission = FileDocument(BASE64_FILE_CONTENT, FILENAME)
# Once the scan completes on Copyleaks servers, we will trigger a webhook that notifies you.
# Provide your public endpoint server address. If you are testing locally, make sure that this endpoint
# is publicly available.
webhooks = SubmitWebhooks()
webhooks.set_status('https://your.server/webhook/{STATUS}')
webhooks.set_new_result('https://your.server/webhook/new-results')
# Pass the webhooks to ScanProperties
scan_properties = ScanProperties(status_webhook='https://your.server/webhook/{STATUS}')
scan_properties.set_webhooks(webhooks)
scan_properties.set_sandbox(True) # Turn on sandbox mode. Turn off on production.
file_submission.set_properties(scan_properties)
Copyleaks.submit_file(auth_token, scan_id, file_submission) # sending the submission to scanning
print("Sent to scanning")
print("You will be notified, using your webhook, once the scan is completed.")
const { Copyleaks, CopyleaksFileSubmissionModel } = require('copyleaks');
async function submitTextForPlagiarismCheck() {
try {
// Initialize Copyleaks
const copyleaks = new Copyleaks();
// Login to get the authentication token.
// Replace with your email and API key.
const loginResult = await copyleaks.loginAsync('[email protected]', 'YOUR_API_KEY');
const scanId = `text-plagiarism-scan-${Date.now()}`;
const WEBHOOK_URL = "https://your-server.com/webhook";
// The text to be checked for plagiarism
const textContent = "Hello world, this is a test.";
const base64Content = Buffer.from(textContent).toString('base64');
// Create a submission model
const submission = new CopyleaksFileSubmissionModel(
base64Content,
'sample.txt',
{
sandbox: true, // Use sandbox for testing
webhooks: {
// Copyleaks will notify this URL when the scan is complete.
status: `${WEBHOOK_URL}/{STATUS}`
}
}
);
// Submit the file for scanning
await copyleaks.submitFileAsync(loginResult, scanId, submission);
console.log(`Submission successful. Scan ID: ${scanId}`);
} catch (error) {
console.error("An error occurred:", error);
}
}
submitTextForPlagiarismCheck();
import classes.Copyleaks;
import models.submissions.CopyleaksFileSubmissionModel;
import models.submissions.properties.*;
import java.util.Base64;
import java.nio.charset.StandardCharsets;
String scanId = "my-plagiarism-scan";
String base64Content = Base64.getEncoder().encodeToString("Hello world".getBytes(StandardCharsets.UTF_8));
// Configure webhooks
SubmissionWebhooks webhooks = new SubmissionWebhooks("https://your-server.com/webhook/{STATUS}");
webhooks.setNewResult("https://your-server.com/webhook/new-results");
// Create submission properties
SubmissionProperties properties = new SubmissionProperties(webhooks);
properties.setSandbox(true);
// Add the document to the Shared Data Hub
SubmissionIndexing indexing = new SubmissionIndexing();
indexing.setCopyleaksDb(true);
properties.setIndexing(indexing);
// Set action to scan (plagiarism is enabled by default)
properties.setAction(SubmissionActions.Scan);
// Optional: Set sensitivity level for plagiarism detection
properties.setSensitivityLevel(3); // 1-5, where 5 is most sensitive
// Create and submit the file
CopyleaksFileSubmissionModel submission = new CopyleaksFileSubmissionModel(base64Content, "file.txt", properties);
Copyleaks.submitFile(authToken, scanId, submission);
System.out.println("Sent to scanning...");
using System;
using System.Text;
using Copyleaks.SDK.V3.API;
using Copyleaks.SDK.V3.API.Models.Requests;
using Copyleaks.SDK.V3.API.Models.Requests.Properties;
// authToken comes from the login step
var scanId = "my-plagiarism-scan";
var base64Content = Convert.ToBase64String(Encoding.UTF8.GetBytes("Hello world"));
// Configure webhooks and submission properties
var properties = new ClientScanProperties();
properties.Webhooks = new Webhooks
{
Status = new Uri("https://your-server.com/webhook/{STATUS}"),
NewResult = new Uri("https://your-server.com/webhook/new-results")
};
properties.Sandbox = true; // Turn on sandbox mode. Turn off on production.
// Create and submit the file
var submission = new FileDocument
{
Base64 = base64Content,
Filename = "file.txt",
PropertiesSection = properties
};
var scansClient = new CopyleaksScansApi();
await scansClient.SubmitFileAsync(scanId, submission, authToken);
Console.WriteLine("Sent to scanning...");
<?php
use Copyleaks\CopyleaksFileSubmissionModel;
use Copyleaks\SubmissionProperties;
use Copyleaks\SubmissionWebhooks;
// $copyleaks and $authToken come from the login step
$scanId = "my-plagiarism-scan";
$base64Content = base64_encode("Hello world");
// Configure webhooks and submission properties
$webhooks = new SubmissionWebhooks(
"https://your-server.com/webhook/{STATUS}",
"https://your-server.com/webhook/new-results"
);
$properties = new SubmissionProperties($webhooks);
$properties->sandbox = true; // Turn on sandbox mode. Turn off on production.
// Create and submit the file
$submission = new CopyleaksFileSubmissionModel($base64Content, "file.txt", $properties);
$copyleaks->submitFile($authToken, $scanId, $submission);
echo "Sent to scanning...\n";
require 'copyleaks'
require 'base64'
# copyleaks and auth_token come from the login step
scan_id = "my-plagiarism-scan"
base64_content = Base64.strict_encode64("Hello world")
# Configure webhooks
webhooks = Copyleaks::SubmissionWebhooks.new(
"https://your-server.com/webhook/{STATUS}", # status
"https://your-server.com/webhook/new-results" # newResult
)
# The Ruby SDK takes properties positionally; arguments left nil are not sent
properties = Copyleaks::SubmissionProperties.new(
webhooks,
nil, # includeHtml
"my-developer-payload", # developerPayload
true, # sandbox: turn off on production
2880, # expiration, in hours
3 # sensitivityLevel, 1-5
)
# Create and submit the file
submission = Copyleaks::CopyleaksFileSubmissionModel.new(base64_content, "file.txt", properties)
copyleaks.submit_file(auth_token, scan_id, submission)
puts "Sent to scanning..."
5
Wait for the completed webhook
The scan can take some time. Once it’s complete, Copyleaks will send a completed webhook to the status URL you provided. This webhook contains a summary of the scan results, including any
result IDs for found plagiarism matches.6
Export detailed results
After the
completed webhook arrives, use the export endpoint to retrieve the detailed plagiarism results using the result IDs you received in the completed webhook.We will also export the Crawled Version. The crawledVersion webhook contains the text and html version of the document. This can later be used in order to display the report.In addition, you should also specify a completionWebhook to receive notifications when the export is ready.POST https://api.copyleaks.com/v3/downloads/my-plagiarism-scan/export/<export_id>
Headers
Authorization: Bearer <your_token>
Content-Type: application/json
Body
{
"completionWebhook": "https://your.server/export/completed",
"maxRetries": 3,
"developerPayload": "custom_data_identifier",
"crawledVersion": {
"endpoint": "https://your.server/webhook/export/crawled",
"verb": "POST",
"headers": [
[
"header-key",
"header-value"
]
]
},
"results": [
{
"id": "result-1",
"endpoint": "https://your.server/webhook/export/result/result-1",
"verb": "POST",
"headers": [
[
"header-key",
"header-value"
]
]
}
]
}
curl -X POST "https://api.copyleaks.com/v3/downloads/my-plagiarism-scan/export/my-export-1" \
-H "Authorization: Bearer <YOUR_AUTH_TOKEN>" \
-H "Content-Type: application/json" \
-d '{
"completionWebhook": "https://your-server.com/webhook/export/completion",
"maxRetries": 3,
"developerPayload": "custom_data_identifier",
"crawledVersion": {
"endpoint": "https://your-server.com/webhook/export/crawled",
"verb": "POST",
"headers": {
"header-key": "header-value",
"header-key-2": "header-value-2"
}
},
"results": [
{
"id": "<RESULT_ID_FROM_COMPLETED_WEBHOOK>",
"endpoint": "https://your-server.com/webhook/export/result/1",
"verb": "POST",
"headers": {
"header-key": "header-value"
}
}
]
}'
from copyleaks.copyleaks import Copyleaks
from copyleaks.models.export import Export, ExportResult
export_id = "my-export-1"
export = Export()
export.set_completion_webhook('https://your-server.com/webhook/export/completion')
# Export a specific plagiarism result
result1 = ExportResult()
result1.set_id('<RESULT_ID_FROM_COMPLETED_WEBHOOK>')
result1.set_endpoint('https://your-server.com/webhook/export/result/1') # Only URL
result1.set_verb('POST') # HTTP method separately
export.set_results([result1])
Copyleaks.export(auth_token, scan_id, export_id, export)
print("Export initiated.")
const { Copyleaks, CopyleaksExportModel } = require('copyleaks');
async function exportPlagiarismResults() {
try {
// Initialize Copyleaks
const copyleaks = new Copyleaks();
// Login to get the authentication token.
// Replace with your email and API key.
const loginResult = await copyleaks.loginAsync('[email protected]', 'YOUR_API_KEY');
const scanId = "YOUR_SCAN_ID"; // The ID of the scan you want to export
const exportId = `export-${scanId}-${Date.now()}`;
const WEBHOOK_URL = "https://your-server.com/webhook";
// The result IDs to export, obtained from the completed webhook
const resultIdsToExport = ["RESULT_ID_1", "RESULT_ID_2"];
const results = resultIdsToExport.map(resultId => ({
id: resultId,
endpoint: `${WEBHOOK_URL}/export/${exportId}/result/${resultId}`,
verb: "POST"
}));
// Create an export model
const exportModel = new CopyleaksExportModel(
`${WEBHOOK_URL}/export/${exportId}/completion`, // Completion webhook URL
results,
{
// Request to export the crawled version of the original document
endpoint: `${WEBHOOK_URL}/export/${exportId}/crawled-version`,
verb: "POST"
}
);
// Start the export process
await copyleaks.exportAsync(loginResult, scanId, exportId, exportModel);
console.log(`Export initiated. Export ID: ${exportId}`);
} catch (error) {
console.error("An error occurred:", error);
}
}
exportPlagiarismResults();
import classes.Copyleaks;
import models.exports.*;
import models.exceptions.*;
import java.text.ParseException;
import java.util.concurrent.ExecutionException;
String scanId = "2a1b402420"; // Your scan ID from submission
String exportId = "08338e505d"; // Your chosen export ID
// Create headers (optional)
String[][] headers = new String[][]{
new String[]{"key", "value"},
new String[]{"key2", "value2"}
};
// Export specific plagiarism results
ExportResults results = new ExportResults(
"2a1b402420", // Result ID from completed webhook
"https://your.server/webhook/export/result/2a1b402420", // Endpoint URL
"POST", // HTTP method
headers // Optional headers
);
// Create array of results to export
ExportResults[] exportResultsArray = new ExportResults[1];
exportResultsArray[0] = results;
// Export crawled version of original document
ExportCrawledVersion crawledVersion = new ExportCrawledVersion(
"https://your.server/webhook/export/result/08338e505d",
"POST",
headers
);
// Create the export model
CopyleaksExportModel exportModel = new CopyleaksExportModel(
"https://your.server/webhook/export/result/2b42c39fba", // Completion webhook
exportResultsArray, // Results to export
crawledVersion // Crawled version
);
// Execute the export with comprehensive exception handling
try {
Copyleaks.export(authToken, scanId, exportId, exportModel);
System.out.println("Export initiated successfully.");
} catch (ParseException e) {
System.out.println("Parse error: " + e.getMessage());
e.printStackTrace();
} catch (AuthExpiredException e) {
System.out.println("Authentication expired: " + e.getMessage());
e.printStackTrace();
} catch (UnderMaintenanceException e) {
System.out.println("Service under maintenance: " + e.getMessage());
e.printStackTrace();
} catch (RateLimitException e) {
System.out.println("Rate limit exceeded: " + e.getMessage());
e.printStackTrace();
} catch (CommandException e) {
System.out.println("Command error: " + e.getMessage());
e.printStackTrace();
} catch (ExecutionException e) {
System.out.println("Execution error: " + e.getMessage());
e.printStackTrace();
} catch (InterruptedException e) {
System.out.println("Process interrupted: " + e.getMessage());
e.printStackTrace();
}
using System;
using Copyleaks.SDK.V3.API;
using Copyleaks.SDK.V3.API.Models.Requests;
// authToken comes from the login step
var scanId = "my-plagiarism-scan";
var exportId = "my-export-1";
var exportRequest = new ExportRequest
{
CompletionWebhook = new Uri("https://your-server.com/webhook/export/completion"),
// Export a specific plagiarism result
Results = new[]
{
new ResultExportTask
{
ResultId = "<RESULT_ID_FROM_COMPLETED_WEBHOOK>",
Endpoint = new Uri("https://your-server.com/webhook/export/result/1"),
Verb = "POST"
}
},
// Export the crawled version of the scanned document
CrawledVersion = new ExportTask
{
Endpoint = new Uri("https://your-server.com/webhook/export/crawled"),
Verb = "POST"
}
};
var scansClient = new CopyleaksScansApi();
await scansClient.ExportAsync(scanId, exportId, exportRequest, authToken);
Console.WriteLine("Export initiated.");
<?php
use Copyleaks\CopyleaksExportModel;
use Copyleaks\ExportCrawledVersion;
use Copyleaks\ExportResults;
// $copyleaks and $authToken come from the login step
$scanId = "my-plagiarism-scan";
$exportId = "my-export-1";
// Export a specific plagiarism result
$result = new ExportResults(
"<RESULT_ID_FROM_COMPLETED_WEBHOOK>",
"https://your-server.com/webhook/export/result/1",
"POST"
);
// Export the crawled version of the scanned document
$crawledVersion = new ExportCrawledVersion(
"https://your-server.com/webhook/export/crawled",
"POST"
);
$exportModel = new CopyleaksExportModel(
"https://your-server.com/webhook/export/completion",
[$result],
$crawledVersion
);
$copyleaks->export($authToken, $scanId, $exportId, $exportModel);
echo "Export initiated.\n";
require 'copyleaks'
# copyleaks and auth_token come from the login step
scan_id = "my-plagiarism-scan"
export_id = "my-export-1"
# Export a specific plagiarism result
result = Copyleaks::ExportResults.new(
"<RESULT_ID_FROM_COMPLETED_WEBHOOK>", # id
"https://your-server.com/webhook/export/result/1", # endpoint
"POST" # verb
)
# Export the crawled version of the scanned document
crawled_version = Copyleaks::ExportCrawledVersion.new(
"https://your-server.com/webhook/export/crawled", # endpoint
"POST" # verb
)
export_model = Copyleaks::CopyleaksExportModel.new(
"https://your-server.com/webhook/export/completion", # completionWebhook
[result], # results
crawled_version # crawledVersion
)
copyleaks.export(auth_token, scan_id, export_id, export_model)
puts "Export initiated."
7
Summary
You have successfully submitted a scan for plagiarism detection and exported the results. You can now handle the results in your application, display them to users, or take further actions based on the findings.
Next steps
Webhooks Overview
Learn how to securely receive and process notifications from Copyleaks.
Viewing Scan Results
Understand the scan result format and how to display it to your users.

