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 ConnectedConnect 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
Manual Installation
git clone https://github.com/cqchecker/codequiry-php.git
cd codequiry-php
composer install
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;
}
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;
🔧 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
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()
{
//
}
}
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);
}
}
}
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
}
}
}
🔧 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;
});
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'
]);
🛠️ 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;
}
📚 Framework Examples
Laravel Package
Full Laravel integration with Eloquent models, jobs, and notifications.
Laravel Package