Assess Writing in Documents
The Copyleaks Writing Assistant API is a powerful tool to help improve the quality of written content by providing detailed feedback on grammar, spelling, sentence structure, and word choice.
This guide will walk you through the process of submitting documents for writing assessment and retrieving the detailed feedback.
🚀 Get Started
Section titled “🚀 Get Started”-
Before you begin
Section titled “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.
-
Installation
Section titled “Installation”Choose your preferred method for making API calls.
You can interact with the API using any standard HTTP client.
For a quicker setup, we provide a Postman collection. See our Postman guide for instructions.
Terminal window sudo apt-get install curlDownload it from curl.se
Terminal window brew install curlTerminal window pip install copyleaksTerminal window npm install plagiarism-checker -
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/apiHeadersContent-Type: application/jsonBody{"key": "00000000-0000-0000-0000-000000000000"}Terminal window 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 CopyleaksAPI_KEY = "your-api-key-here"# Login to Copyleaksauth_token = Copyleaks.login(EMAIL_ADDRESS, API_KEY)print("Logged successfully!\nToken:", auth_token)const { Copyleaks } = require("plagiarism-checker");const API_KEY = "your-api-key-here";const copyleaks = new Copyleaks();// Login functionfunction 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 com.copyleaks.sdk.api.Copyleaks;String API_KEY = "00000000-0000-0000-0000-000000000000";// Login to Copyleakstry {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);}Response
{"access_token": "<ACCESS_TOKEN>",".issued": "2025-07-31T10:19:40.0690015Z",".expires": "2025-08-02T10:19:40.0690016Z"} -
Submit for Writing Assessment
Section titled “Submit for Writing Assessment”Submission Methods
You can submit content for analysis using multiple methods:
For this guide, we’ll demonstrate document submission for writing assessment. Each submission requires a unique
scanIdfor proper tracking and identification.PUT https://api.copyleaks.com/v3/scans/submit/file/my-writing-assessment-scanContent-Type: application/jsonAuthorization: Bearer YOUR_LOGIN_TOKEN{"base64": "SGVsbG8gd29ybGQuIFRoaXMgaXMgYW4gZXhhbXBsZSB0ZXh0IHRvIGJlIGNoZWNrZWQgZm9yIGdyYW1tYXIgZXJyb3JzLg==","filename": "my-document.txt","properties": {"sandbox": true,"webhooks": {"status": "https://your.server/webhook/{STATUS}"},"writingFeedback": {"enable": true}}}Terminal window # First, encode your file to base64base64_content=$(base64 -w 0 my-document.docx)curl -X PUT "https://api.copyleaks.com/v3/scans/submit/file/my-writing-assessment-scan" \-H "Content-Type: application/json" \-H "Authorization: Bearer YOUR_LOGIN_TOKEN" \-d '{"base64": "'$base64_content'","filename": "my-document.docx","properties": {"sandbox": true,"webhooks": {"status": "https://your.server/webhook/{STATUS}"},"writingFeedback": {"enable": true}}}'import base64import randomfrom copyleaks.copyleaks import Copyleaksfrom copyleaks.models.submit.document import FileDocumentfrom copyleaks.models.submit.properties.scan_properties import ScanPropertiesfrom copyleaks.models.submit.properties.submit_webhooks import SubmitWebhooksfrom copyleaks.models.submit.properties.writing_feedback import WritingFeedbackprint("Submitting a document for writing assessment...")# Read and encode the filewith open('my-document.docx', 'rb') as file:file_content = file.read()base64_file_content = base64.b64encode(file_content).decode('utf8')# Generate a random scan ID or use a meaningful identifierscan_id = f"writing-scan-{random.randint(100, 100000)}"# Create a file submissionfile_submission = FileDocument(base64_file_content, "my-document.docx")# Configure writing assistantwriting_feedback = WritingFeedback()writing_feedback.enable = True# Configure webhooks for notificationswebhooks = SubmitWebhooks()webhooks.set_status('https://your.server/webhook/{STATUS}')# Set up scan propertiesscan_properties = ScanProperties(status_webhook='https://your.server/webhook/{STATUS}')scan_properties.set_webhooks(webhooks)scan_properties.set_writing_feedback(writing_feedback)scan_properties.set_sandbox(True) # Turn on sandbox mode. Turn off on production.# Add properties to the submissionfile_submission.set_properties(scan_properties)# Submit the document for assessmentCopyleaks.submit_file(auth_token, scan_id, file_submission)print("Document sent for writing assessment")print("You will be notified via webhook when the assessment completes.")const { Copyleaks, CopyleaksFileSubmissionModel } = require('plagiarism-checker');const fs = require('fs');async function submitForWritingAssessment() {try {// Read the file and encode it as base64const fileContent = fs.readFileSync('my-document.docx');const base64Content = fileContent.toString('base64');// Generate a unique scan IDconst scanId = `writing-scan-${Date.now()}`;// Create the submission propertiesconst properties = {sandbox: true, // Set to false in productionwebhooks: {status: 'https://your.server/webhook/{STATUS}'},writingFeedback: {enable: true,// Optionally customize scoring weightsscore: {grammarScoreWeight: 1.0,mechanicsScoreWeight: 1.0,sentenceStructureScoreWeight: 1.0,wordChoiceScoreWeight: 1.0}}};// Create the submission modelconst submission = new CopyleaksFileSubmissionModel(base64Content,'my-document.docx',properties);// Get authentication tokenconst loginResult = await Copyleaks.login(EMAIL, API_KEY);const authToken = loginResult.access_token;// Submit the document for assessmentawait Copyleaks.submitFile(authToken, scanId, submission);console.log(`Document submitted for writing assessment with scan ID: ${scanId}`);console.log('You will be notified via webhook when the assessment completes.');} catch (error) {console.error('Error submitting document:', error);}}submitForWritingAssessment();import classes.Copyleaks;import models.submissions.CopyleaksFileSubmissionModel;import models.submissions.properties.*;import java.util.Base64;import java.nio.file.Files;import java.nio.file.Paths;import java.io.IOException;public class WritingAssessmentExample {public static void main(String[] args) {try {// Read the file and encode it as base64byte[] fileBytes = Files.readAllBytes(Paths.get("my-document.docx"));String base64Content = Base64.getEncoder().encodeToString(fileBytes);// Set scan IDString scanId = "writing-scan-" + System.currentTimeMillis();// Configure webhooksSubmissionWebhooks webhooks = new SubmissionWebhooks("https://your.server/webhook/{STATUS}");// Create submission propertiesSubmissionProperties properties = new SubmissionProperties(webhooks);properties.setSandbox(true); // Set to false in production// Enable writing feedbackWritingFeedback writingFeedback = new WritingFeedback();writingFeedback.setEnable(true);properties.setWritingFeedback(writingFeedback);// Create and submit the fileCopyleaksFileSubmissionModel submission = new CopyleaksFileSubmissionModel(base64Content,"my-document.docx",properties);// Submit the documentCopyleaks.submitFile(authToken, scanId, submission);System.out.println("Document sent for writing assessment with scan ID: " + scanId);System.out.println("You will be notified via webhook when the assessment completes.");} catch (Exception e) {e.printStackTrace();}}} -
Wait for Completion Webhook
Section titled “Wait for Completion Webhook”Once the scan is complete, Copyleaks will send a completed webhook to the status URL you provided.
When writing assistant is enabled, the webhook response will include a
writingFeedbacksection with detailed information about the writing quality. -
Interpreting Writing Assessment Results
Section titled “Interpreting Writing Assessment Results”The completed webhook contains a
writingFeedbackobject with the Correction Types:-
textStatistics: Basic metrics about the text, including sentence count, average word and sentence length, and estimated reading time.
-
score: Detailed breakdown of writing quality across four categories:
- Grammar
- Mechanics (spelling, punctuation)
- Sentence Structure
- Word Choice
Each category includes both a count of corrections and a score (0-100).
-
readability: An assessment of how easy the text is to read, including:
- Overall readability score (0-100)
- Readability level (grade level)
- Text description of the readability
-
-
Export Detailed Results
Section titled “Export Detailed Results”To get the specific writing corrections, you need to export the detailed results using the export endpoint:
POST https://api.copyleaks.com/v3/downloads/my-writing-assessment-scan/export/my-export-1Content-Type: application/jsonAuthorization: Bearer YOUR_LOGIN_TOKEN{"writingFeedback": {"corrections": true,"verb": "POST","headers": [["Content-Type", "application/json"]],"endpoint": "https://your.server/export/writing-feedback"},"completionWebhook": "https://your.server/webhook/export/completion","maxRetries": 3,"developerPayload": "writing-assessment-export"}Terminal window curl -X POST "https://api.copyleaks.com/v3/downloads/my-writing-assessment-scan/export/my-export-1" \-H "Content-Type: application/json" \-H "Authorization: Bearer YOUR_LOGIN_TOKEN" \-d '{"writingFeedback": {"corrections": true,"verb": "POST","headers": [["Content-Type", "application/json"]],"endpoint": "https://your.server/export/writing-feedback"},"completionWebhook": "https://your.server/webhook/export/completion","maxRetries": 3,"developerPayload": "writing-assessment-export"}'from copyleaks.copyleaks import Copyleaksfrom copyleaks.models.export import Export, ExportResults, WritingFeedbackExportfrom copyleaks.models.export.http_method import HttpMethodfrom copyleaks.models.export.endpoint import Endpoint# Set up the exportexport_id = "my-export-1"# Configure what to exportexport = Export()export.set_completion_webhook('https://your.server/webhook/export/completion')# Add optional parametersexport.set_max_retries(3) # Default is 3, can be 1-12export.set_developer_payload("writing-assessment-export") # Custom identifier# Request writing feedback corrections with endpointwriting_feedback = WritingFeedbackExport()writing_feedback.set_corrections(True)writing_feedback.set_endpoint(Endpoint(HttpMethod.POST,"https://your.server/export/writing-feedback",[["Content-Type", "application/json"]]))export.set_writing_feedback(writing_feedback)# Start the export processCopyleaks.export(auth_token, scan_id, export_id, export)print(f"Export requested with ID: {export_id}")print("You will be notified via webhook when the export is ready.")const { Copyleaks, CopyleaksExportModel } = require('plagiarism-checker');async function exportWritingFeedback() {try {const scanId = 'my-writing-assessment-scan';const exportId = 'my-export-1';// Configure the exportconst exportRequest = {writingFeedback: {corrections: true,verb: "POST",headers: [["Content-Type", "application/json"]],endpoint: "https://your.server/export/writing-feedback"},completionWebhook: 'https://your.server/webhook/export/completion',maxRetries: 3, // Default is 3, can be 1-12developerPayload: "writing-assessment-export" // Custom identifier};// Get authentication tokenconst loginResult = await Copyleaks.login(EMAIL, API_KEY);const authToken = loginResult.access_token;// Request the exportawait Copyleaks.export(authToken, scanId, exportId, exportRequest);console.log(`Export requested with ID: ${exportId}`);console.log('You will be notified via webhook when the export is ready.');} catch (error) {console.error('Error exporting results:', error);}}exportWritingFeedback();import classes.Copyleaks;import models.exports.*;import java.util.ArrayList;import java.util.List;public class ExportWritingFeedbackExample {public static void main(String[] args) {try {String scanId = "my-writing-assessment-scan";String exportId = "my-export-1";// Create headers for endpointsList<EndpointHeader> headers = new ArrayList<>();headers.add(new EndpointHeader("Content-Type", "application/json"));// Configure writing feedback export with endpointWritingFeedbackExport writingFeedback = new WritingFeedbackExport();writingFeedback.setCorrections(true);writingFeedback.setEndpoint(new ExportEndpoint(HttpMethod.POST,"https://your.server/export/writing-feedback",headers));// Create complete export requestCopyleaksExportModel export = new CopyleaksExportModel();export.setCompletionWebhook("https://your.server/webhook/export/completion");export.setWritingFeedback(writingFeedback);// Add optional parametersexport.setMaxRetries(3); // Default is 3, can be 1-12export.setDeveloperPayload("writing-assessment-export"); // Custom identifier// Request the exportCopyleaks.export(authToken, scanId, exportId, export);System.out.println("Export requested with ID: " + exportId);System.out.println("You will be notified via webhook when the export is ready.");} catch (Exception e) {e.printStackTrace();}}}} -
🎉Congratulations!
Section titled “🎉Congratulations!”You have successfully submitted a document for writing assessment and exported the detailed correction recommendations. You can now integrate these corrections into your application, display them to users, or use them to improve the document’s quality.