# Export PDF Report

> Generate branded, customizable PDF reports of Copyleaks scan results (plagiarism, AI detection, and grammar feedback), delivered via webhook.

This document provides a comprehensive overview of the essential steps for creating and customizing PDF reports, setting up report generation, handling webhooks, and managing completed reports.

## Introduction

The PDF API allows you to generate detailed and customizable PDF reports of scan results, including plagiarism checks, AI detection, and Grammar Checker feedback. These reports can be branded with your own logo and customized to match your organization's needs.

The PDF generation process is integrated with the Copyleaks scanning process, where you enable PDF creation during scan submission and then receive the generated PDF through webhooks.

Copyleaks API also offers different PDF report versions, with version 3 being the latest and most feature-rich option that includes advanced formatting and comprehensive analysis visualization.

<Note>
PDF files for keeping records of individual scan results, which complement the interactive reports, are created through the download functionality in the report UI. If you have other PDF requirements to complement the interactive report options, please contact [**Copyleaks Support**](https://help.copyleaks.com/hc/en-us/requests/new).
</Note>
## Before you begin

Before you start using the PDF API, ensure you have the following:

1. An active Copyleaks account: If you don't have one, [sign up here](https://copyleaks.com).
2. Familiarity with RESTful API principles: Basic knowledge of HTTP requests and responses.
3. A tool for HTTP requests: Use tools like cURL, Postman, or Copyleaks' SDK.

## Installations

<InstallSDKs />

## Login

To enable PDF report generation, we first need to generate an access token. We will use the [login](/reference/actions/account/login) endpoint.

The API key can be found on the [Copyleaks API Dashboard](https://api.copyleaks.com/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.

<Tip>
To boost performance, cache your login token and reuse it for all requests. The token remains valid for up to 48 hours, so you don't need to log in repeatedly. The login method has stricter rate limits than other endpoints.
</Tip>
<CodeGroup>
    ```http title="HTTP" icon="globe"
    POST https://id.copyleaks.com/v3/account/login/api
    Content-Type: application/json

    {
        "email": "<EMAIL_ADDRESS>",
        "key": "<API_KEY>"
    }
    ```
    ```bash title="cURL" icon="terminal"
    curl -X POST "https://id.copyleaks.com/v3/account/login/api" \
         -H "Content-Type: application/json" \
         -d '{
               "email": "<EMAIL_ADDRESS>",
               "key": "<API_KEY>"
             }'
    ```
    ```python title="Python" icon="python"
    from copyleaks.copyleaks import Copyleaks
    from copyleaks.exceptions.command_error import CommandError
    from copyleaks.models.submit.document import FileDocument
    from copyleaks.models.submit.properties.scan_properties import ScanProperties
    from copyleaks.models.export import Export, ExportCrawledVersion, ExportResult, ExportPDF
    import base64
    import random

    EMAIL_ADDRESS = "<EMAIL_ADDRESS>"
    API_KEY = "<API_KEY>"

    # Login to Copyleaks
    try:
        auth_token = Copyleaks.login(EMAIL_ADDRESS, API_KEY)
    except CommandError as ce:
        response = ce.get_response()
        print(f"An error occurred (HTTP status code {response.status_code}):")
        print(response.content)
        exit(1)

    print("Logged successfully!\nToken:")
    print(auth_token)
    ```
    ```javascript title="JavaScript" icon="square-js"
    const copyleaks = require('copyleaks');

    const EMAIL_ADDRESS = "<EMAIL_ADDRESS>";
    const API_KEY = "<API_KEY>";

    // Login to Copyleaks
    const login = async () => {
        try {
            const authToken = await copyleaks.login(EMAIL_ADDRESS, API_KEY);
            console.log('Logged successfully!\nToken:', authToken);
            return authToken;
        } catch (error) {
            console.error('Failed to login:', error);
            process.exit(1);
        }
    };
    ```
    ```java title="Java" icon="java"
    import com.copyleaks.sdk.api.Copyleaks;
    import com.copyleaks.sdk.api.exceptions.CommandException;
    import com.copyleaks.sdk.api.models.ScanProperties;
    import com.copyleaks.sdk.api.models.FileSubmission;
    import com.copyleaks.sdk.api.models.Export;
    import com.copyleaks.sdk.api.models.ExportCrawledVersion;
    import com.copyleaks.sdk.api.models.ExportResult;
    import com.copyleaks.sdk.api.models.ExportPDF;
    import java.util.Base64;
    import java.util.Arrays;

    String EMAIL_ADDRESS = "<EMAIL_ADDRESS>";
    String API_KEY = "<API_KEY>";

    // Login to Copyleaks
    try {
        String authToken = Copyleaks.login(EMAIL_ADDRESS, API_KEY);
        System.out.println("Logged successfully!\nToken: " + authToken);
    } catch (CommandException e) {
        System.out.println("Failed to login: " + e.getMessage());
        System.exit(1);
    }
    ```
</CodeGroup>

## Submit Scan with PDF Report Enabled

Use the [submit](/reference/actions/authenticity/submit-file/) file endpoint to send content for analysis while enabling PDF report generation. The key difference for PDF reports is including the `properties.pdf.create` parameter set to true.

In the URL, supply your chosen scan ID, which serves as the identifier for the scan. Each scan needs to have a unique scan ID.

The `properties.pdf.reportVersion` should be set to "latest" to use the latest PDF report format with enhanced visuals and comprehensive data visualization.

The `properties.pdf.title` allows you to customize the title that appears on the PDF report.

The `properties.displayLanguage` allows you to generate the PDF report in a specific language.

For branding purposes, you can include your organization's logo using `properties.pdf.largeLogo` (PNG format, base64 encoded, max 100kb, recommended size 185x50px).

<Note>
There are more customization options available for PDF reports, but this guide doesn't cover all of them.

For this tutorial, we also pass in `properties.sandbox` as **TRUE** to enable sandbox mode. The sandbox mode is free to use, but it returns mock results. Using sandbox mode while working on integrating with the Copyleaks API is helpful.
</Note>
<CodeGroup>
    ```http title="HTTP" icon="globe"
    PUT https://api.copyleaks.com/v3/scans/submit/file/<SCAN_ID>
    Authorization: Bearer <your_token>
    Content-Type: application/json

    {
        "base64": "<base64_encoded_file_content>",
        "filename": "<FILE_NAME>",
        "properties": {
            "webhooks": { "status": "https://your.server/webhook?event={\{STATUS\}}" },
            "sandbox": true,
            "pdf": {
                "create": true,
                "reportVersion": "v3",
                "title": "Custom PDF Report Title",
                "largeLogo": "<base64_encoded_logo>"
            }
        }
    }
    ```
    ```bash title="cURL" icon="terminal"
    curl -X PUT "https://api.copyleaks.com/v3/scans/submit/file/<SCAN_ID>" \
         -H "Authorization: Bearer <your_token>" \
         -H "Content-Type: application/json" \
         -d '{
               "base64": "<base64_encoded_file_content>",
               "filename": "<FILE_NAME>",
               "properties": {
                   "webhooks": { "status": "https://your.server/webhook?event={\{STATUS\}}" },
                   "sandbox": true,
                   "pdf": {
                       "create": true,
                       "reportVersion": "v3",
                       "title": "Custom PDF Report Title",
                       "largeLogo": "<base64_encoded_logo>"
                   }
               }
             }'
    ```
    ```python title="Python" icon="python"
    # Submit a file for scanning with PDF generation enabled
    scan_id = "<SCAN_ID>";
    file_name = "<FILE_NAME>"
    base64_file_content = base64.b64encode(b'Hello world.').decode('utf8')  # or read your file and convert it into BASE64 presentation.
    print("Submitting a new file...")
    file_submission = FileDocument(base64_file_content, file_name)

    # Set scan properties with PDF options
    scan_properties = ScanProperties('https://your.server/webhook?event={\{STATUS\}}')
    scan_properties.set_sandbox(True)  # Turn on sandbox mode. Turn off on production.

    # Enable PDF report generation
    scan_properties.set_pdf({
        "create": True,
        "reportVersion": "v3",
        "title": "Custom PDF Report Title"
        # Add base64_logo if needed
    })

    file_submission.set_properties(scan_properties)

    # Submit the file for scanning
    Copyleaks.submit_file(auth_token, scan_id, file_submission)
    print("Sent to scanning with PDF report enabled")
    print("You will be notified, using your webhook, once the scan is completed.")
    ```
    ```javascript title="JavaScript" icon="square-js"
    // Submit a file for scanning with PDF report enabled
    const scanId = "<SCAN_ID>"; // Replace with your unique scan ID
    const filename = "<FILE_NAME>";
    const fileContent = Buffer.from('Hello world').toString('base64'); // Convert file content to base64

    const submitFile = async (authToken) => {
        const scanProperties = new copyleaks.ScanProperties('https://your.server/webhook?event={\{STATUS\}}');
        scanProperties.setSandbox(true); // Enable sandbox mode for testing

        // Enable PDF report generation
        scanProperties.setPDF({
            create: true,
            reportVersion: "v3",
            title: "Custom PDF Report Title"
            // Add largeLogo if needed
        });

        const fileSubmission = new copyleaks.FileSubmission(fileContent, filename);
        fileSubmission.setProperties(scanProperties);

        try {
            await copyleaks.submitFile(authToken, scanId, fileSubmission);
            console.log('File submitted for scanning with PDF report enabled. Scan ID:', scanId);
        } catch (error) {
            console.error('Failed to submit file:', error);
        }
    };
    ```
    ```java title="Java" icon="java"
    // Submit a file for scanning with PDF report enabled
    String scanId = "<SCAN_ID>"; // Replace with your unique scan ID
    String filename = "<FILE_NAME>";
    String fileContent = Base64.getEncoder().encodeToString("Hello world".getBytes()); // Convert file content to base64

    ScanProperties scanProperties = new ScanProperties("https://your.server/webhook?event={\{STATUS\}}");
    scanProperties.setSandbox(true); // Enable sandbox mode for testing

    // Enable PDF report generation
    Map<String, Object> pdfProperties = new HashMap<>();
    pdfProperties.put("create", true);
    pdfProperties.put("reportVersion", "v3");
    pdfProperties.put("title", "Custom PDF Report Title");
    // Add largeLogo if needed
    scanProperties.setPDF(pdfProperties);

    FileSubmission fileSubmission = new FileSubmission(fileContent, filename);
    fileSubmission.setProperties(scanProperties);

    try {
        Copyleaks.submitFile(authToken, scanId, fileSubmission);
        System.out.println("File submitted for scanning with PDF report enabled. Scan ID: " + scanId);
    } catch (CommandException e) {
        System.out.println("Failed to submit file: " + e.getMessage());
    }
    ```
</CodeGroup>

## PDF Customization Options

The PDF report can be extensively customized to match your organization's branding and requirements.

| Property          | Type            | Description                                                                                                                                                                                            | Default |
| -----------       | --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------- |
| `create`          | boolean         | Add a request to generate a customizable export of the scan report, in a pdf format. Set to true in order to generate a pdf report for this scan.                                                      | false   |
| `title`           | string          | Customize the title for the PDF report. Maximum 256 characters.                                                                                                                                        | null    |
| `colors`          | object          | Object containing color customization options for the PDF report.                                                                                                                                      | -       |
| `largeLogo`       | string (base64) | Customize the logo image in the PDF report. Only supports **png** format. Max file size: 100kb. Recommended size: width 185px, height 50px.                                                            | null    |
| `rtl`             | boolean         | When set to true, the text in the report will be aligned from right to left.                                                                                                                           | false   |
| `reportVersion`   | string          | PDF version to generate. By default latest version will be generated. Version 3 is the latest iteration of the PDF report. Available values: **v1**, **v2**, **v3**, **latest**                        | latest  |

## Wait For Scan Completion

The scan and PDF report generation may take seconds to minutes, depending on the content, features used, and products enabled.

Once the scan is complete successfully, Copyleaks API will send a completed webhook to the URL you supplied in the submit under `properties.webhooks.status`. At the same time, the **\{STATUS\}** is replaced with "completed".

The completed webhooks hold the summary information about the scan, such as the number of matched words, total words, and results found.

If the scan finishes with an error, an error webhook will be sent to the `properties.webhooks.status` while the **\{STATUS\}** is replaced with **error**.

<Note>
For testing purposes, we recommend using a third-party service such as **request bin** or **ngrok**.
</Note>
## Exporting PDF Reports

Use the [export](/reference/actions/downloads/export/) method to retrieve the generated PDF report along with other scan artifacts. The export method sends webhooks with each artifact's content to your specified target server.

We supply the Scan ID we used earlier in the submit endpoint in the URL. The user chooses a unique Export ID for each export.

For PDF reports specifically, we add a `pdf` section to the export request, providing an endpoint where the PDF should be sent when ready.

<CodeGroup>
    ```http title="HTTP" icon="globe"
    POST https://api.copyleaks.com/v3/downloads/<SCAN_ID>/export/<EXPORT_ID>
    Authorization: Bearer <API_TOKEN>
    Content-Type: application/json

    {
        "completionWebhook": "https://your.server/webhook/export/completion",
        "pdf": {
            "endpoint": "https://your.server/webhook/export/pdf",
            "verb": "POST",
            "headers": {
                "key": "value",
                "key2": "value2"
            }
        }
    }
    ```
    ```bash title="cURL" icon="terminal"
    curl -X POST "https://api.copyleaks.com/v3/downloads/<SCAN_ID>/export/<EXPORT_ID>" \
         -H "Authorization: Bearer <API_TOKEN>" \
         -H "Content-Type: application/json" \
         -d '{
               "completionWebhook": "https://your.server/webhook/export/completion",
               "pdf": {
                   "endpoint": "https://your.server/webhook/export/pdf",
                   "verb": "POST",
                   "headers": {
                       "key": "value",
                       "key2": "value2"
                   }
               }
             }'
    ```
    ```python title="Python" icon="python"
    # Export scan results including PDF report
    export_id = "<EXPORT_ID>"
    export = Export()
    export.set_completion_webhook('https://your.server/webhook/export/completion')

    # Export PDF report
    pdf_export = ExportPDF()
    pdf_export.set_endpoint('https://your.server/webhook/export/pdf')
    pdf_export.set_verb('POST')
    pdf_export.set_headers([['key', 'value'], ['key2', 'value2']])  # optional
    export.set_pdf(pdf_export)

    # Trigger the export
    Copyleaks.export(auth_token, scan_id, export_id, export)
    print("Export initiated. You will be notified via webhook once the export is completed.")
    ```
    ```javascript title="JavaScript" icon="square-js"
    // Export scan results including PDF report
    const exportId = '<EXPORT_ID>';
    const exportResults = async (authToken, scanId) => {
        const exportRequest = new copyleaks.Export();
        exportRequest.setCompletionWebhook('https://your.server/webhook/export/completion');

        // Export PDF report
        const pdfExport = new copyleaks.ExportPDF();
        pdfExport.setEndpoint('https://your.server/webhook/export/pdf');
        pdfExport.setVerb('POST');
        exportRequest.setPDF(pdfExport);

        try {
            await copyleaks.export(authToken, scanId, exportId, exportRequest);
            console.log('Export initiated with PDF report. Export ID:', exportId);
        } catch (error) {
            console.error('Failed to export results:', error);
        }
    };
    ```
    ```java title="Java" icon="java"
    // Export scan results including PDF report
    String exportId = "<EXPORT_ID>";
    Export exportRequest = new Export();
    exportRequest.setCompletionWebhook("https://your.server/webhook/export/completion");

    // Export PDF report
    ExportPDF pdfExport = new ExportPDF();
    pdfExport.setEndpoint("https://your.server/webhook/export/pdf");
    pdfExport.setVerb("POST");
    exportRequest.setPDF(pdfExport);

    try {
        Copyleaks.export(authToken, scanId, exportId, exportRequest);
        System.out.println("Export initiated with PDF report. Export ID: " + exportId);
    } catch (CommandException e) {
        System.out.println("Failed to export results: " + e.getMessage());
    }
    ```
</CodeGroup>

## Next Steps

<CardGroup cols={2}>
  <Card title="Webhooks Overview" icon="plug" href="/reference/data-types/authenticity/webhooks/overview/">Learn about webhooks in the Copyleaks API and how to handle real-time notifications.</Card>
  <Card title="Export Method" icon="file-export" href="/reference/actions/downloads/export/">Understand the export method for retrieving various scan artifacts including PDF reports.</Card>
  <Card title="Authenticity API Overview" icon="code" href="/reference/actions/authenticity/overview/">Learn about the comprehensive scanning API that supports multiple products and features.</Card>
</CardGroup>

## Support

Should you require any assistance or have inquiries, please contact [**Copyleaks Support**](https://help.copyleaks.com/hc/en-us/requests/new) or ask a question on [**Stack Overflow**](https://stackoverflow.com/questions/tagged/copyleaks-api) with the `copyleaks-api` tag.
