For what References Validation does and when to use it, see the References Validation concept page. This guide will walk you through submitting a scan with reference validation turned on, reading the summary from the completed webhook, and fetching the full per-reference results.

How it works

Each detected reference is sorted into one of two categories, and each category is validated differently:
Reference typeHow Copyleaks validates itWhat you get back
Academic (papers, journal articles)Looked up in the Copyleaks academic citation index by title, then corroborated on year and authors.Parsed fields plus matching source suggestions with per-field signals.
Non-academic (web pages, docs, blogs, encyclopedias)The cited URL is fetched live and its title, year, and authors are compared to what was cited.Parsed fields plus the fetched source as a suggestion with per-field signals.
A reference is counted as validated only when the top suggestion matches the title and no checked field contradicts it. Fields that could not be checked are simply ignored - they do not count against the reference.

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 a scan with reference validation

Submit a document for scanning and turn reference validation on. Use the top-level properties.references.validate field and set it to true.If you omit the section entirely, validation defaults to false.This example also disables internet plagiarism scanning (scanning.internet: false) so the scan runs references-only.
PUT https://api.copyleaks.com/v3/scans/submit/file/my-scan-id
Content-Type: application/json
Authorization: Bearer <YOUR_AUTH_TOKEN>

{
  "base64": "VGhpcyBpcyBhIHRlc3QgZG9jdW1lbnQu",
  "filename": "paper_with_references.txt",
  "properties": {
    "webhooks": {
      "status": "https://your-server.com/webhook/{STATUS}"
    },
    "scanning": {
      "internet": false
    },
    "references": {
      "validate": true
    }
  }
}
curl -X PUT "https://api.copyleaks.com/v3/scans/submit/file/my-scan-id" \
     -H "Authorization: Bearer <YOUR_AUTH_TOKEN>" \
     -H "Content-Type: application/json" \
     -d '{
           "base64": "VGhpcyBpcyBhIHRlc3QgZG9jdW1lbnQu",
           "filename": "paper_with_references.txt",
           "properties": {
             "webhooks": {
               "status": "https://your-server.com/webhook/{STATUS}"
             },
             "scanning": {
               "internet": false
             },
             "references": {
               "validate": true
             }
           }
         }'
import requests
import base64

# Document content (your text with references)
document_content = "This is a test document with references."
base64_content = base64.b64encode(document_content.encode()).decode('utf-8')

url = "https://api.copyleaks.com/v3/scans/submit/file/my-scan-id"
payload = {
    "base64": base64_content,
    "filename": "paper_with_references.txt",
    "properties": {
        "webhooks": {
            "status": "https://your-server.com/webhook/{STATUS}"
        },
        "scanning": {
            "internet": False
        },
        "references": {
            "validate": True
        }
    }
}
headers = {
    "Authorization": "Bearer <YOUR_AUTH_TOKEN>",
    "Content-Type": "application/json"
}

response = requests.put(url, json=payload, headers=headers)
print(response.json())
const axios = require('axios');

const url = 'https://api.copyleaks.com/v3/scans/submit/file/my-scan-id';
const headers = {
    'Authorization': 'Bearer <YOUR_AUTH_TOKEN>',
    'Content-Type': 'application/json'
};

const data = {
    base64: "VGhpcyBpcyBhIHRlc3QgZG9jdW1lbnQu",
    filename: "paper_with_references.txt",
    properties: {
        webhooks: {
            status: "https://your-server.com/webhook/{STATUS}"
        },
        scanning: {
            internet: false
        },
        references: {
            validate: true
        }
    }
};

axios.put(url, data, { headers })
    .then(response => console.log(response.data))
    .catch(error => console.error(error));
import classes.Copyleaks;
import models.submissions.CopyleaksFileSubmissionModel;
import models.submissions.properties.*;
import java.util.Base64;
import java.nio.charset.StandardCharsets;

String scanId = "my-scan-id";
String base64Content = Base64.getEncoder().encodeToString("This is a test document with references.".getBytes(StandardCharsets.UTF_8));

// Create submission properties
SubmissionProperties properties = new SubmissionProperties(new SubmissionWebhooks("https://your-server.com/webhook/{STATUS}"));

// Disable plagiarism so the scan runs references-only
SubmissionScanning scanning = new SubmissionScanning();
scanning.setInternet(false);
properties.setScanning(scanning);

// Turn reference validation on
SubmissionReferences references = new SubmissionReferences();
references.setValidate(true);
properties.setReferences(references);

// Create and submit the file
CopyleaksFileSubmissionModel submission = new CopyleaksFileSubmissionModel(base64Content, "paper_with_references.txt", properties);

Copyleaks.submitFile(authToken, scanId, submission);
System.out.println("Scan submitted with reference validation.");
Keep track of the scanId (in this case my-scan-id). You will need it to fetch the full per-reference results once the scan completes.
5

Read the summary from the completed webhook

When the scan finishes, Copyleaks sends the completed webhook to the status URL you provided. The payload reports that validation ran via scannedDocument.enabled.referencesValidation, and adds a top-level referencesValidation.summary with the counts.
Completed webhook (excerpt)
{
  "scannedDocument": {
    "enabled": {
      "referencesValidation": true
    }
  },
  "referencesValidation": {
    "summary": {
      "total": 2,
      "academic": 1,
      "academicValidated": 1,
      "nonAcademicValidated": 0
    }
  }
}
The summary fields are:
  • total - total references detected in the document.
  • academic - how many of those were academic.
  • academicValidated - academic references that were fully corroborated.
  • nonAcademicValidated - non-academic references that were fully corroborated.
The completed webhook carries the summary only. To see each individual reference, what was parsed, and which sources corroborated it, fetch the crawled version in the next step.
6

Fetch the per-reference results

The completed webhook gives you the summary only. The full per-reference results live in the crawled version of the scan.Retrieve it with the Export method, using the scanId from your submission. The exported crawled version contains a top-level referencesValidation block: the same summary plus a results array with one entry per reference.For the full field-by-field response schema, including how a reference counts as validated and the strict year matching rule, see the References Validation results data type.
7

Summary

You have just:
  • Submitted a scan with reference validation turned on via references.validate
  • Read the validation counts from the completed webhook summary
  • Fetched the crawled version to inspect each parsed reference and its corroborating sources

Next steps

How References Validation Works

Understand the concepts behind reference detection, parsing, and corroboration before you build.

References Validation Results

The full field reference for the summary and per-reference results, including signals and suggestions.

Detect AI-Generated Content

Run AI detection on uploaded documents as part of a full authenticity scan.

Check for Plagiarism

Submit text or files and get a plagiarism report with matched sources.