Developer API

Code Plagiarism
Detection API

Build plagiarism detection into your apps. Check code against 20+ billion sources.

const response = await fetch('https://codequiry.com/api/v1/check', { method: 'POST', headers: { 'apikey': 'YOUR_API_KEY' }, body: formData }); // Check created!

Codequiry SDK for Java

The official Java SDK for Codequiry provides a robust, thread-safe interface for enterprise Java applications. Built for Java 11+ with support for both synchronous and asynchronous operations.

📦 Installation

Add the dependency to your project using your preferred build tool:

Maven
<dependency>
    <groupId>com.codequiry</groupId>
    <artifactId>codequiry-java</artifactId>
    <version>1.2.0</version>
</dependency>
                
pom.xml
Gradle
// Groovy DSL
implementation 'com.codequiry:codequiry-java:1.2.0'

// Kotlin DSL
implementation("com.codequiry:codequiry-java:1.2.0")
                
build.gradle
Requirements: Java 11 or higher. Compatible with Spring Boot 2.7+ and 3.x.

🚀 Quick Start

Initialize the client and verify your API key:

import com.codequiry.CodequiryClient;
import com.codequiry.models.*;

public class QuickStart {
    public static void main(String[] args) {
        // Initialize client with your API key
        CodequiryClient client = new CodequiryClient.Builder()
            .apiKey("your-api-key-here")
            .baseUrl("https://codequiry.com/api/v1")
            .timeout(30_000)  // 30 second timeout
            .maxRetries(3)
            .build();

        try {
            // Test connection
            AccountInfo account = client.getAccountInfo();
            System.out.println("Connected as: " + account.getName());
            System.out.println("Plan: " + account.getPlan());
            System.out.println("Checks remaining: " + account.getChecksRemaining());
        } catch (CodequiryException e) {
            System.err.println("Error: " + e.getMessage());
            System.err.println("Status: " + e.getStatusCode());
        }
    }
}
        
Quick Start

🔄 Complete Workflow Example

A full end-to-end example showing how to create a check, upload files, run analysis, and retrieve results:

import com.codequiry.CodequiryClient;
import com.codequiry.models.*;
import java.io.File;
import java.util.List;
import java.util.concurrent.TimeUnit;

public class PlagiarismChecker {

    private final CodequiryClient client;

    public PlagiarismChecker(String apiKey) {
        this.client = new CodequiryClient.Builder()
            .apiKey(apiKey)
            .timeout(30_000)
            .maxRetries(3)
            .build();
    }

    public CheckOverview runCheck(String name, int language, List<File> files)
            throws CodequiryException, InterruptedException {

        // 1. Create check
        Check check = client.createCheck(new CreateCheckRequest(name, language));
        System.out.println("Created check: " + check.getId());

        // 2. Upload files
        for (File file : files) {
            UploadResult result = client.uploadFile(check.getId(), file);
            System.out.println("Uploaded: " + file.getName());
        }

        // 3. Start analysis
        client.startCheck(new StartCheckRequest(check.getId(), 1, true, true));
        System.out.println("Analysis started...");

        // 4. Poll for completion
        CheckStatus status = waitForCompletion(check.getId());
        System.out.println("Analysis complete! Status: " + status.getStatus());

        // 5. Get results
        CheckOverview overview = client.getCheckOverview(check.getId());

        // Process results
        for (Submission submission : overview.getSubmissions()) {
            System.out.printf("%s: %.1f%% similarity%n",
                submission.getFilename(),
                submission.getTotalResult());

            if (submission.getTotalResult() > 50.0) {
                System.out.println("  ⚠ HIGH SIMILARITY - Review required");
            }
        }

        return overview;
    }

    private CheckStatus waitForCompletion(int checkId)
            throws CodequiryException, InterruptedException {

        long startTime = System.currentTimeMillis();
        long timeout = TimeUnit.MINUTES.toMillis(10);

        while (System.currentTimeMillis() - startTime < timeout) {
            CheckStatus status = client.getCheckStatus(checkId);

            if (status.getStatusId() == 4) { // Completed
                return status;
            }

            if (status.getStatusId() == 5) { // Error
                throw new CodequiryException("Analysis failed: " + status.getStatusMessage());
            }

            System.out.printf("Progress: %d%% - %s%n",
                status.getProgress(), status.getStatusMessage());

            Thread.sleep(30_000); // Wait 30 seconds
        }

        throw new CodequiryException("Analysis timed out after 10 minutes");
    }

    public static void main(String[] args) throws Exception {
        PlagiarismChecker checker = new PlagiarismChecker("your-api-key-here");

        List<File> files = List.of(
            new File("student1_submission.zip"),
            new File("student2_submission.zip"),
            new File("student3_submission.zip")
        );

        CheckOverview results = checker.runCheck(
            "Java Assignment - Data Structures",
            13,  // Java language ID
            files
        );

        System.out.printf("Analyzed %d submissions%n", results.getSubmissions().size());
    }
}
        
Complete Workflow

⚡ Async Operations with CompletableFuture

Leverage Java's CompletableFuture for non-blocking, asynchronous API calls:

import com.codequiry.CodequiryClient;
import com.codequiry.CodequiryAsyncClient;
import com.codequiry.models.*;
import java.io.File;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.stream.Collectors;

public class AsyncPlagiarismChecker {

    private final CodequiryAsyncClient asyncClient;
    private final ExecutorService executor;

    public AsyncPlagiarismChecker(String apiKey) {
        CodequiryClient client = new CodequiryClient.Builder()
            .apiKey(apiKey)
            .timeout(30_000)
            .build();

        this.asyncClient = new CodequiryAsyncClient(client);
        this.executor = Executors.newFixedThreadPool(4);
    }

    public CompletableFuture<CheckOverview> runCheckAsync(
            String name, int language, List<File> files) {

        // Create check asynchronously
        return asyncClient.createCheckAsync(new CreateCheckRequest(name, language))
            .thenCompose(check -> {
                System.out.println("Created check: " + check.getId());

                // Upload all files concurrently
                List<CompletableFuture<UploadResult>> uploads = files.stream()
                    .map(file -> asyncClient.uploadFileAsync(check.getId(), file)
                        .thenApply(result -> {
                            System.out.println("Uploaded: " + file.getName());
                            return result;
                        }))
                    .collect(Collectors.toList());

                // Wait for all uploads, then start analysis
                return CompletableFuture.allOf(uploads.toArray(new CompletableFuture[0]))
                    .thenCompose(v -> {
                        System.out.println("All files uploaded. Starting analysis...");
                        return asyncClient.startCheckAsync(
                            new StartCheckRequest(check.getId(), 1, true, true));
                    })
                    .thenCompose(v -> pollStatusAsync(check.getId()))
                    .thenCompose(status -> asyncClient.getOverviewAsync(check.getId()));
            });
    }

    private CompletableFuture<CheckStatus> pollStatusAsync(int checkId) {
        return CompletableFuture.supplyAsync(() -> {
            long startTime = System.currentTimeMillis();
            long timeout = 600_000; // 10 minutes

            while (System.currentTimeMillis() - startTime < timeout) {
                try {
                    CheckStatus status = asyncClient.getClient()
                        .getCheckStatus(checkId);

                    if (status.getStatusId() == 4) return status;
                    if (status.getStatusId() == 5) {
                        throw new RuntimeException("Analysis failed");
                    }

                    System.out.printf("Progress: %d%%%n", status.getProgress());
                    Thread.sleep(30_000);
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                    throw new RuntimeException(e);
                }
            }
            throw new RuntimeException("Timeout");
        }, executor);
    }

    public static void main(String[] args) throws Exception {
        AsyncPlagiarismChecker checker = new AsyncPlagiarismChecker("your-api-key-here");

        List<File> files = List.of(
            new File("student1.zip"),
            new File("student2.zip"),
            new File("student3.zip")
        );

        // Run asynchronously
        CompletableFuture<CheckOverview> future = checker.runCheckAsync(
            "Async Assignment Check", 14, files
        );

        // Do other work while check runs...
        System.out.println("Check running in background...");

        // Get results when ready
        CheckOverview overview = future.get();
        overview.getSubmissions().forEach(sub ->
            System.out.printf("%s: %.1f%% similarity%n",
                sub.getFilename(), sub.getTotalResult())
        );
    }
}
        
Async Operations

🔧 Error Handling

The SDK provides structured exception handling with detailed error information:

import com.codequiry.CodequiryClient;
import com.codequiry.exceptions.*;

public class ErrorHandling {

    public static void main(String[] args) {
        CodequiryClient client = new CodequiryClient.Builder()
            .apiKey("your-api-key-here")
            .build();

        try {
            var check = client.createCheck(
                new CreateCheckRequest("Test", 14));

        } catch (AuthenticationException e) {
            // 401 - Invalid API key
            System.err.println("Invalid API key: " + e.getMessage());

        } catch (ValidationException e) {
            // 422 - Invalid parameters
            System.err.println("Validation error: " + e.getMessage());
            e.getErrors().forEach((field, message) ->
                System.err.println("  " + field + ": " + message));

        } catch (RateLimitException e) {
            // 429 - Rate limit exceeded
            System.err.println("Rate limited. Retry after: " + e.getRetryAfter() + "s");

        } catch (NotFoundException e) {
            // 404 - Resource not found
            System.err.println("Not found: " + e.getMessage());

        } catch (CodequiryException e) {
            // Any other API error
            System.err.println("API error " + e.getStatusCode() + ": " + e.getMessage());

        } catch (Exception e) {
            // Network or other errors
            System.err.println("Unexpected error: " + e.getMessage());
        }
    }
}
        
Error Handling

🌱 Spring Boot Integration

Integrate Codequiry seamlessly into your Spring Boot application:

Configuration
# application.yml
codequiry:
  api-key: ${CODEQUIRY_API_KEY}
  base-url: https://codequiry.com/api/v1
  timeout: 30000
  max-retries: 3
        
application.yml
Configuration Bean
import com.codequiry.CodequiryClient;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class CodequiryConfig {

    @Value("${codequiry.api-key}")
    private String apiKey;

    @Value("${codequiry.base-url:https://codequiry.com/api/v1}")
    private String baseUrl;

    @Value("${codequiry.timeout:30000}")
    private int timeout;

    @Value("${codequiry.max-retries:3}")
    private int maxRetries;

    @Bean
    public CodequiryClient codequiryClient() {
        return new CodequiryClient.Builder()
            .apiKey(apiKey)
            .baseUrl(baseUrl)
            .timeout(timeout)
            .maxRetries(maxRetries)
            .build();
    }
}
        
Spring Config
Service Layer
import com.codequiry.CodequiryClient;
import com.codequiry.models.*;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.util.List;

@Service
public class PlagiarismService {

    private final CodequiryClient client;

    public PlagiarismService(CodequiryClient client) {
        this.client = client;
    }

    public Check createAndUpload(String name, int language, List<MultipartFile> files)
            throws CodequiryException, IOException {

        // Create check
        Check check = client.createCheck(new CreateCheckRequest(name, language));

        // Upload each file
        for (MultipartFile multipartFile : files) {
            File tempFile = Files.createTempFile("upload-", ".zip").toFile();
            try {
                multipartFile.transferTo(tempFile);
                client.uploadFile(check.getId(), tempFile);
            } finally {
                tempFile.delete();
            }
        }

        return check;
    }

    public void startAnalysis(int checkId, int testType) throws CodequiryException {
        client.startCheck(new StartCheckRequest(checkId, testType, true, true));
    }

    public CheckStatus getStatus(int checkId) throws CodequiryException {
        return client.getCheckStatus(checkId);
    }

    public CheckOverview getResults(int checkId) throws CodequiryException {
        return client.getCheckOverview(checkId);
    }
}
        
Spring Service
REST Controller
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import java.util.List;
import java.util.Map;

@RestController
@RequestMapping("/api/plagiarism")
public class PlagiarismController {

    private final PlagiarismService plagiarismService;

    public PlagiarismController(PlagiarismService plagiarismService) {
        this.plagiarismService = plagiarismService;
    }

    @PostMapping("/check")
    public ResponseEntity<?> createCheck(
            @RequestParam  String name,
            @RequestParam  int language,
            @RequestParam("files") List<MultipartFile> files) {

        try {
            Check check = plagiarismService.createAndUpload(name, language, files);
            plagiarismService.startAnalysis(check.getId(), 1);

            return ResponseEntity.ok(Map.of(
                "success", true,
                "check_id", check.getId(),
                "message", "Check created and analysis started"
            ));
        } catch (Exception e) {
            return ResponseEntity.badRequest().body(Map.of(
                "success", false,
                "error", e.getMessage()
            ));
        }
    }

    @GetMapping("/check/{checkId}/status")
    public ResponseEntity<?> getStatus(@PathVariable  int checkId) {
        try {
            CheckStatus status = plagiarismService.getStatus(checkId);
            return ResponseEntity.ok(status);
        } catch (Exception e) {
            return ResponseEntity.badRequest().body(Map.of(
                "error", e.getMessage()
            ));
        }
    }

    @GetMapping("/check/{checkId}/results")
    public ResponseEntity<?> getResults(@PathVariable  int checkId) {
        try {
            CheckOverview overview = plagiarismService.getResults(checkId);
            return ResponseEntity.ok(overview);
        } catch (Exception e) {
            return ResponseEntity.badRequest().body(Map.of(
                "error", e.getMessage()
            ));
        }
    }
}
        
REST Controller

🧵 Thread-Safe Batch Processing

Process multiple assignments concurrently with thread-safe batch operations:

import com.codequiry.CodequiryClient;
import com.codequiry.models.*;
import java.io.File;
import java.util.*;
import java.util.concurrent.*;
import java.util.stream.Collectors;

public class BatchProcessor {

    private final CodequiryClient client;
    private final ExecutorService executor;
    private final Semaphore semaphore;

    public BatchProcessor(CodequiryClient client, int maxConcurrent) {
        this.client = client;
        this.executor = Executors.newFixedThreadPool(maxConcurrent);
        this.semaphore = new Semaphore(maxConcurrent);
    }

    public record Assignment(String name, int language, List<File> files) {}
    public record Result(Assignment assignment, int checkId, CheckOverview overview, Exception error) {}

    public List<Result> processAssignments(List<Assignment> assignments)
            throws InterruptedException {

        List<Future<Result>> futures = new ArrayList<>();

        for (Assignment assignment : assignments) {
            Future<Result> future = executor.submit(() -> {
                semaphore.acquire();
                try {
                    return processAssignment(assignment);
                } finally {
                    semaphore.release();
                }
            });
            futures.add(future);
        }

        // Collect results
        return futures.stream()
            .map(future -> {
                try {
                    return future.get(15, TimeUnit.MINUTES);
                } catch (Exception e) {
                    return new Result(null, 0, null, e);
                }
            })
            .collect(Collectors.toList());
    }

    private Result processAssignment(Assignment assignment) {
        try {
            // Create check
            Check check = client.createCheck(
                new CreateCheckRequest(assignment.name(), assignment.language()));

            // Upload files
            for (File file : assignment.files()) {
                client.uploadFile(check.getId(), file);
            }

            // Start analysis
            client.startCheck(new StartCheckRequest(check.getId(), 1, true, true));

            // Wait for completion
            long deadline = System.currentTimeMillis() + 600_000;
            while (System.currentTimeMillis() < deadline) {
                CheckStatus status = client.getCheckStatus(check.getId());
                if (status.getStatusId() == 4) {
                    CheckOverview overview = client.getCheckOverview(check.getId());
                    return new Result(assignment, check.getId(), overview, null);
                }
                if (status.getStatusId() == 5) {
                    throw new RuntimeException("Analysis failed: " + status.getStatusMessage());
                }
                Thread.sleep(30_000);
            }
            throw new RuntimeException("Timeout");

        } catch (Exception e) {
            return new Result(assignment, 0, null, e);
        }
    }

    public void shutdown() {
        executor.shutdown();
    }

    // Usage
    public static void main(String[] args) throws Exception {
        CodequiryClient client = new CodequiryClient.Builder()
            .apiKey("your-api-key-here")
            .build();

        BatchProcessor processor = new BatchProcessor(client, 5);

        List<Assignment> assignments = List.of(
            new Assignment("CS101 - Week 1", 14,
                List.of(new File("week1_student1.zip"), new File("week1_student2.zip"))),
            new Assignment("CS101 - Week 2", 14,
                List.of(new File("week2_student1.zip"), new File("week2_student2.zip"))),
            new Assignment("CS201 - Midterm", 13,
                List.of(new File("midterm_student1.zip"), new File("midterm_student2.zip")))
        );

        List<Result> results = processor.processAssignments(assignments);

        for (Result result : results) {
            if (result.error() != null) {
                System.err.printf("FAILED: %s - %s%n",
                    result.assignment().name(), result.error().getMessage());
            } else {
                System.out.printf("OK: %s - %d submissions analyzed%n",
                    result.assignment().name(),
                    result.overview().getSubmissions().size());
            }
        }

        processor.shutdown();
    }
}
        
Batch Processing

📋 API Method Reference

Complete list of available methods in the Java SDK:

Method Description Returns
getAccountInfo() Get account details and subscription info AccountInfo
getLanguages() List all supported programming languages List<Language>
getTestTypes() List available analysis engines List<TestType>
getChecks() List all your plagiarism checks List<Check>
createCheck(request) Create a new plagiarism check Check
uploadFile(checkId, file) Upload a ZIP file to a check UploadResult
batchUpload(checkId, files) Upload multiple files at once BatchUploadResult
startCheck(request) Start plagiarism analysis void
getCheckStatus(checkId) Get check progress and status CheckStatus
getCheckOverview(checkId) Get results overview with scores CheckOverview
getCheckResults(checkId, subId) Get detailed match analysis CheckResults
getCheckSummary(checkId) Get aggregate statistics CheckSummary
exportResults(checkId, format) Export results as CSV or JSON ExportResult
getAIResults(checkId) Get AI detection results AIResults
updateCheck(checkId, request) Update check name or language Check
deleteCheck(checkId) Delete a check permanently void
deleteSubmission(checkId, subId) Remove a submission from a check void