The Copyleaks Authenticity API is the most powerful way to analyze your content for plagiarism. This API is asynchronous - you submit a scan, and Copyleaks notifies your server via webhooks when the results are ready to be retrieved. This guide will walk you through the process of submitting a scan, enabling plagiarism detection, and exporting the results.

Get started

1

Before you begin

Before you start, ensure you have the following:
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 plagiarism-checker
Install-Package Copyleaks
composer require copyleaks/php-plagiarism-checker
gem install plagiarism-checker
<!-- Add to your pom.xml (requires Java 11+) -->
<dependency>
    <groupId>com.copyleaks.sdk</groupId>
    <artifactId>copyleaks-java-sdk</artifactId>
    <version>5.1.0</version>
</dependency>
HTTP needs no installation - call the API with any standard HTTP client, or import our Postman collection for a quicker start.
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("plagiarism-checker");

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
try {
    CopyleaksAuthToken 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);
}
Response
{
    "access_token": "<ACCESS_TOKEN>",
    ".issued": "2025-07-31T10:19:40.0690015Z",
    ".expires": "2025-08-02T10:19:40.0690016Z"
}
Save this token. It is valid for 48 hours and can be reused for subsequent API calls.
4

Submit for scanning

Use the Submit File Endpoint to send content for analysis. We suggest you provide a unique scanId for each submission.
For testing, set "sandbox": true. Sandbox mode is free and returns mock results.
What is Base64 Encoding?Base64 converts binary files into text strings so they can be sent via JSON. All programming languages have built-in Base64 encoding functions, see the code examples below for your language.
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('plagiarism-checker');

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);

// Configure indexing (this enables plagiarism detection)
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...");
5

Wait for the completion 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 completion 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('plagiarism-checker');

  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 completion 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.*;

    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(token, 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();
    }
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.