Developer API

Code Plagiarism Detection API

Build plagiarism detection into your applications with our powerful REST API. Detect copied code across 20+ billion sources with industry-leading accuracy.

99.7%
Accuracy
51+
Languages
20B+
Sources
5
SDKs

API Playground

Not Connected

Connect your API key to test endpoints in real-time

Codequiry SDK for PHP

The official PHP SDK for Codequiry provides a clean, object-oriented interface for integrating plagiarism detection into your PHP applications. Compatible with modern PHP frameworks including Laravel, Symfony, and CodeIgniter.

Open Source: View the complete source code and contribute at github.com/cqchecker/codequiry-php

📦 Installation

Composer (Recommended)
                        composer require codequiry/codequiry-php
                        
Composer
Manual Installation
                        git clone https://github.com/cqchecker/codequiry-php.git
cd codequiry-php
composer install
                        
Manual
Requirements: PHP 7.4 or higher, cURL extension, JSON extension

🚀 Quick Start

1. Basic Setup
        @php

require_once 'vendor/autoload.php';

use Codequiry\Client;
use Codequiry\Exceptions\CodequiryException;

// Initialize the client
$client = new Client([
    'api_key' => 'your-api-key-here',
    'base_url' => 'https://codequiry.com/api/v1', // Optional
    'timeout' => 30, // Request timeout in seconds
]);

// Test connection
try {
    $account = $client->getAccountInfo();
    echo "Connected as: " . $account['name'] . PHP_EOL;
    echo "Checks remaining: " . $account['checks_remaining'] . PHP_EOL;
} catch (CodequiryException $e) {
    echo "Connection failed: " . $e->getMessage() . PHP_EOL;
}
        
Basic Setup
2. Complete Workflow Example
        @php

class PlagiarismChecker
{
    private $client;
    
    public function __construct($apiKey)
    {
        $this->client = new Client(['api_key' => $apiKey]);
    }
    
    public function runCompleteCheck($assignmentName, $language, array $filePaths)
    {
        try {
            // 1. Create a new check
            $check = $this->client->createCheck([
                'name' => $assignmentName,
                'language' => $language
            ]);
            
            echo "Created check: {$check['id']}" . PHP_EOL;
            
            // 2. Upload files
            $uploadedFiles = [];
            foreach ($filePaths as $filePath) {
                if (!file_exists($filePath)) {
                    throw new Exception("File not found: {$filePath}");
                }
                
                $result = $this->client->uploadFile($check['id'], $filePath);
                $uploadedFiles[] = $result;
                echo "Uploaded: {$result['filename']}" . PHP_EOL;
            }
            
            // 3. Start the analysis
            $analysis = $this->client->startCheck($check['id'], [
                'webcheck' => true,  // Check against web sources
                'dbcheck' => true    // Check against database
            ]);
            
            echo "Analysis started..." . PHP_EOL;
            
            // 4. Wait for completion
            $results = $this->waitForCompletion($check['id']);
            
            // 5. Get overview results
            $overview = $this->client->getOverview($check['id']);
            
            echo "Analysis complete!" . PHP_EOL;
            echo "Found {$overview['submissions_count']} submissions" . PHP_EOL;
            
            // 6. Process results
            $suspiciousSubmissions = array_filter(
                $overview['submissions'], 
                function($sub) {
                    return floatval($sub['total_result']) > 50;
                }
            );
            
            foreach ($suspiciousSubmissions as $submission) {
                echo "⚠️  {$submission['filename']}: {$submission['total_result']}% similarity" . PHP_EOL;
                
                // Get detailed results
                $details = $this->client->getDetailedResults($check['id'], $submission['id']);
                
                // Process peer matches
                foreach ($details['peer_matches'] as $match) {
                    echo "  → Match with {$match['file_matched']}: {$match['similarity']}%" . PHP_EOL;
                }
            }
            
            return $overview;
            
        } catch (Exception $e) {
            echo "Error: " . $e->getMessage() . PHP_EOL;
            throw $e;
        }
    }
    
    private function waitForCompletion($checkId, $maxWaitTime = 600)
    {
        $startTime = time();
        
        while (time() - $startTime < $maxWaitTime) {
            $status = $this->client->getCheckStatus($checkId);
            
            if ($status['status_id'] == 4) { // Completed
                return $status;
            }
            
            echo "Status: " . ($status['message'] ?? 'Processing...') . PHP_EOL;
            sleep(30); // Wait 30 seconds before checking again
        }
        
        throw new Exception("Check did not complete within {$maxWaitTime} seconds");
    }
}

// Usage
$checker = new PlagiarismChecker('your-api-key-here');

$results = $checker->runCompleteCheck(
    'Assignment 1 - PHP Basics',
    3, // PHP language ID
    [
        'student1_submission.php',
        'student2_submission.php',
        'student3_submission.php'
    ]
);

echo "Check completed successfully!" . PHP_EOL;
        
Complete Workflow

🔧 Laravel Integration

Seamlessly integrate Codequiry into your Laravel applications:

1. Environment Configuration
        # .env
CODEQUIRY_API_KEY=your-api-key-here
CODEQUIRY_BASE_URL=https://codequiry.com/api/v1
        
.env Configuration
2. Service Provider
        @php

// app/Providers/CodequiryServiceProvider.php

namespace App\Providers;

use Illuminate\Support\ServiceProvider;
use Codequiry\Client;

class CodequiryServiceProvider extends ServiceProvider
{
    public function register()
    {
        $this->app->singleton(Client::class, function ($app) {
            return new Client([
                'api_key' => config('services.codequiry.api_key'),
                'base_url' => config('services.codequiry.base_url'),
                'timeout' => config('services.codequiry.timeout', 30),
            ]);
        });
    }

    public function boot()
    {
        //
    }
}
        
Service Provider
3. Controller Example
        @php

// app/Http/Controllers/PlagiarismController.php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Codequiry\Client;
use App\Assignment;
use App\Jobs\ProcessPlagiarismCheck;

class PlagiarismController extends Controller
{
    private $codequiry;
    
    public function __construct(Client $codequiry)
    {
        $this->codequiry = $codequiry;
    }
    
    public function upload(Request $request)
    {
        $request->validate([
            'assignment_id' => 'required|exists:assignments,id',
            'files.*' => 'required|file|max:2048', // 2MB max
        ]);
        
        $assignment = Assignment::findOrFail($request->assignment_id);
        
        try {
            // Create check
            $check = $this->codequiry->createCheck([
                'name' => $assignment->title,
                'language' => $assignment->language_id
            ]);
            
            // Store check ID
            $assignment->update(['codequiry_check_id' => $check['id']]);
            
            // Upload files
            $uploadedFiles = [];
            foreach ($request->file('files') as $file) {
                $tempPath = $file->store('temp');
                $fullPath = storage_path('app/' . $tempPath);
                
                $result = $this->codequiry->uploadFile($check['id'], $fullPath, $file->getClientOriginalName());
                $uploadedFiles[] = $result;
                
                // Clean up temp file
                unlink($fullPath);
            }
            
            // Start analysis in background
            ProcessPlagiarismCheck::dispatch($assignment);
            
            return response()->json([
                'success' => true,
                'check_id' => $check['id'],
                'uploaded_files' => count($uploadedFiles),
                'message' => 'Files uploaded successfully. Analysis started.'
            ]);
            
        } catch (\Exception $e) {
            return response()->json([
                'success' => false,
                'error' => $e->getMessage()
            ], 500);
        }
    }
    
    public function status(Assignment $assignment)
    {
        if (!$assignment->codequiry_check_id) {
            return response()->json(['error' => 'No check ID found'], 404);
        }
        
        try {
            $status = $this->codequiry->getCheckStatus($assignment->codequiry_check_id);
            
            if ($status['status_id'] == 4) { // Completed
                $overview = $this->codequiry->getOverview($assignment->codequiry_check_id);
                
                return response()->json([
                    'status' => 'completed',
                    'results' => $overview
                ]);
            }
            
            return response()->json([
                'status' => 'processing',
                'message' => $status['message'] ?? 'Analysis in progress...'
            ]);
            
        } catch (\Exception $e) {
            return response()->json(['error' => $e->getMessage()], 500);
        }
    }
}
        
Laravel Controller
4. Background Job
        @php

// app/Jobs/ProcessPlagiarismCheck.php

namespace App\Jobs;

use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use App\Assignment;
use Codequiry\Client;

class ProcessPlagiarismCheck implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

    protected $assignment;

    public function __construct(Assignment $assignment)
    {
        $this->assignment = $assignment;
    }

    public function handle(Client $codequiry)
    {
        try {
            // Start the check
            $codequiry->startCheck($this->assignment->codequiry_check_id, [
                'webcheck' => true,
                'dbcheck' => true
            ]);
            
            // Wait for completion (with timeout)
            $maxWaitTime = 600; // 10 minutes
            $startTime = time();
            
            while (time() - $startTime < $maxWaitTime) {
                $status = $codequiry->getCheckStatus($this->assignment->codequiry_check_id);
                
                if ($status['status_id'] == 4) { // Completed
                    // Get results and store in database
                    $overview = $codequiry->getOverview($this->assignment->codequiry_check_id);
                    
                    $this->assignment->update([
                        'plagiarism_results' => json_encode($overview),
                        'plagiarism_status' => 'completed',
                        'processed_at' => now()
                    ]);
                    
                    // Send notification to instructor
                    $this->assignment->instructor->notify(
                        new PlagiarismCheckCompleted($this->assignment)
                    );
                    
                    return;
                }
                
                sleep(30); // Wait 30 seconds before checking again
            }
            
            // Timeout occurred
            $this->assignment->update(['plagiarism_status' => 'timeout']);
            
        } catch (\Exception $e) {
            $this->assignment->update([
                'plagiarism_status' => 'failed',
                'plagiarism_error' => $e->getMessage()
            ]);
            
            throw $e; // Re-throw to mark job as failed
        }
    }
}
        
Background Job

🔧 Advanced Features

File Upload Methods
                        @php

// Upload from file path
$result = $client->uploadFile($checkId, './code.php');

// Upload from string content
$code = 'Hello World';
$result = $client->uploadString($checkId, $code, 'hello.php');

// Upload with custom filename
$result = $client->uploadFile($checkId, './temp.php', 'student1.php');

// Bulk upload
$files = ['file1.php', 'file2.php', 'file3.php'];
$results = $client->uploadMultiple($checkId, $files);

// Upload with progress callback
$result = $client->uploadFile($checkId, './large-file.php', null, function($uploaded, $total) {
    $percent = round(($uploaded / $total) * 100);
    echo "Upload progress: {$percent}%" . PHP_EOL;
});
                        
Upload Methods
Configuration & Options
                        @php

// Client configuration
$client = new Client([
    'api_key' => 'your-api-key',
    'base_url' => 'https://codequiry.com/api/v1',
    'timeout' => 30,
    'retries' => 3,
    'debug' => false,
    'user_agent' => 'MyApp/1.0'
]);

// Analysis options
$client->startCheck($checkId, [
    'webcheck' => true,     // Check web sources
    'dbcheck' => false,     // Skip database check
    'test_type' => 1,       // Analysis engine type
    'sensitivity' => 'high' // Detection sensitivity
]);

// Custom headers
$client->setHeaders([
    'X-Custom-Header' => 'value',
    'X-Client-Version' => '1.0'
]);
                        
Configuration

🛠️ Error Handling & Best Practices

        @php

use Codequiry\Exceptions\CodequiryException;
use Codequiry\Exceptions\RateLimitException;
use Codequiry\Exceptions\UnauthorizedException;

class RobustPlagiarismChecker
{
    private $client;
    private $maxRetries;
    
    public function __construct($apiKey, $maxRetries = 3)
    {
        $this->client = new Client(['api_key' => $apiKey]);
        $this->maxRetries = $maxRetries;
    }
    
    public function checkWithRetry($assignment, $retryCount = 0)
    {
        try {
            return $this->performCheck($assignment);
            
        } catch (RateLimitException $e) {
            if ($retryCount < $this->maxRetries) {
                // Wait with exponential backoff
                $waitTime = pow(2, $retryCount) * 1000000; // microseconds
                usleep($waitTime);
                
                return $this->checkWithRetry($assignment, $retryCount + 1);
            }
            throw new Exception("Rate limit exceeded after {$this->maxRetries} retries");
            
        } catch (UnauthorizedException $e) {
            throw new Exception("Invalid API key or access denied");
            
        } catch (CodequiryException $e) {
            if ($e->getCode() === 422) {
                throw new Exception("Invalid request: " . $e->getMessage());
            }
            
            if ($retryCount < $this->maxRetries) {
                sleep(2 * ($retryCount + 1)); // Linear backoff for other errors
                return $this->checkWithRetry($assignment, $retryCount + 1);
            }
            
            throw new Exception("Check failed after {$this->maxRetries} attempts: " . $e->getMessage());
        }
    }
    
    private function performCheck($assignment)
    {
        // Validate input
        if (empty($assignment['files'])) {
            throw new InvalidArgumentException('No files provided for analysis');
        }
        
        foreach ($assignment['files'] as $file) {
            if (!file_exists($file)) {
                throw new InvalidArgumentException("File not found: {$file}");
            }
            
            $fileSize = filesize($file);
            if ($fileSize > 2 * 1024 * 1024) { // 2MB limit
                throw new InvalidArgumentException("File too large: {$file} ({$fileSize} bytes)");
            }
        }
        
        // Create check
        $check = $this->client->createCheck([
            'name' => $assignment['name'] ?? 'Untitled Check',
            'language' => $assignment['language'] ?? 1
        ]);
        
        echo "Created check: {$check['id']}" . PHP_EOL;
        
        // Upload files with progress
        $totalFiles = count($assignment['files']);
        $uploaded = 0;
        
        foreach ($assignment['files'] as $file) {
            try {
                $result = $this->client->uploadFile($check['id'], $file);
                $uploaded++;
                echo "Progress: {$uploaded}/{$totalFiles} files uploaded" . PHP_EOL;
                
            } catch (Exception $e) {
                echo "Failed to upload {$file}: " . $e->getMessage() . PHP_EOL;
                // Continue with other files
            }
        }
        
        if ($uploaded === 0) {
            throw new Exception('No files were successfully uploaded');
        }
        
        // Start analysis
        $this->client->startCheck($check['id'], [
            'webcheck' => $assignment['check_web'] ?? true,
            'dbcheck' => $assignment['check_database'] ?? true
        ]);
        
        echo "Analysis started for {$uploaded} files..." . PHP_EOL;
        
        // Monitor progress
        return $this->waitForCompletion($check['id']);
    }
    
    private function waitForCompletion($checkId, $timeout = 600)
    {
        $startTime = time();
        $lastStatus = '';
        
        while (time() - $startTime < $timeout) {
            $status = $this->client->getCheckStatus($checkId);
            
            if ($status['status_id'] == 4) { // Completed
                echo "Analysis completed!" . PHP_EOL;
                return $this->client->getOverview($checkId);
            }
            
            $currentStatus = $status['message'] ?? 'Processing...';
            if ($currentStatus !== $lastStatus) {
                echo "Status: {$currentStatus}" . PHP_EOL;
                $lastStatus = $currentStatus;
            }
            
            sleep(30);
        }
        
        throw new Exception("Analysis did not complete within {$timeout} seconds");
    }
    
    public function generateReport($checkId, $format = 'json')
    {
        $overview = $this->client->getOverview($checkId);
        
        switch ($format) {
            case 'csv':
                return $this->generateCsvReport($overview);
            case 'html':
                return $this->generateHtmlReport($overview);
            default:
                return $overview;
        }
    }
    
    private function generateCsvReport($overview)
    {
        $csv = "Filename,Total Similarity,Web Matches,Peer Matches\n";
        
        foreach ($overview['submissions'] as $submission) {
            $csv .= sprintf(
                "%s,%.2f%%,%d,%d\n",
                $submission['filename'],
                $submission['total_result'],
                $submission['web_matches'] ?? 0,
                $submission['peer_matches'] ?? 0
            );
        }
        
        return $csv;
    }
}

// Usage
try {
    $checker = new RobustPlagiarismChecker(getenv('CODEQUIRY_API_KEY'));
    
    $results = $checker->checkWithRetry([
        'name' => 'Final Project - E-commerce Site',
        'language' => 3, // PHP
        'files' => [
            'student1/index.php',
            'student2/index.php',
            'student3/index.php'
        ],
        'check_web' => true,
        'check_database' => true
    ]);
    
    // Generate CSV report
    $csvReport = $checker->generateReport($results['check_id'], 'csv');
    file_put_contents('plagiarism_report.csv', $csvReport);
    
    echo "Check completed and report saved!" . PHP_EOL;
    
} catch (Exception $e) {
    error_log("Plagiarism check failed: " . $e->getMessage());
    echo "Error: " . $e->getMessage() . PHP_EOL;
}
        
Error Handling

📚 Framework Examples

Laravel Package

Full Laravel integration with Eloquent models, jobs, and notifications.

Laravel Package
Symfony Bundle

Symfony integration with services, commands, and configuration.

Symfony Bundle