{
  "openapi": "3.1.0",
  "info": {
    "title": "Codequiry API",
    "version": "1.0.0",
    "summary": "Source-code plagiarism, peer similarity, web/database matching, and AI-generated-code detection.",
    "description": "Programmatic access to Codequiry. The typical flow is: create a check, upload one or more ZIP submissions, start the check, then poll status and read the overview / detailed results.\n\nAll endpoints are under the base URL `https://codequiry.com/api/v1` and authenticate with an `apikey` request header (your 64-character key from the dashboard). There is no OAuth and no Bearer token.\n\nMany check-scoped operations expose two equivalent forms: a POST form that takes `check_id` in the body, and a RESTful form that takes the id in the URL (e.g. `POST /check/status` and `GET /checks/{checkId}/status`). They are interchangeable.\n\n**Rate limit:** 60 requests per minute, counted per client IP address (not per API key) and shared across every endpoint. The limit is the same on all plans. Failed calls, including 401s, count against it. Over the limit the API returns 429 with a `Retry-After` header.\n\n**Timestamps** are UTC strings formatted `YYYY-MM-DD HH:MM:SS`.\n\n**Polling:** analysis is asynchronous. After `POST /check/start`, poll `POST /check/status` until `status_id` is 4 (completed) or 3 (failed); results endpoints return 409 until then. Poll every 20-30 seconds — a tight loop will exhaust the rate limit long before a check finishes.",
    "contact": { "name": "Codequiry Support", "url": "https://codequiry.com/contact", "email": "support@codequiry.com" },
    "license": { "name": "Proprietary", "url": "https://codequiry.com/terms-of-service" }
  },
  "servers": [
    { "url": "https://codequiry.com/api/v1", "description": "Production" }
  ],
  "security": [ { "apikey": [] } ],
  "tags": [
    { "name": "Auth", "description": "Validate credentials and read account/quota." },
    { "name": "Reference", "description": "Languages and engine (test type) catalogs." },
    { "name": "Checks", "description": "Create, list, update, and delete checks." },
    { "name": "Submissions", "description": "Upload code and manage submissions within a check." },
    { "name": "Run", "description": "Start analysis and track progress." },
    { "name": "Results", "description": "Overview, detailed matches, AI detection, summaries, and exports." }
  ],
  "paths": {
    "/auth/validate": {
      "get": { "tags": ["Auth"], "operationId": "validateApiKeyGet", "summary": "Validate API key", "description": "Confirms the supplied `apikey` header is valid and returns the owning account.", "responses": { "200": { "description": "Key is valid", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/KeyValidation" } } } }, "401": { "$ref": "#/components/responses/InvalidKey" }, "429": { "$ref": "#/components/responses/RateLimited" } } },
      "post": { "tags": ["Auth"], "operationId": "validateApiKeyPost", "summary": "Validate API key (POST)", "description": "Identical to the GET form.", "responses": { "200": { "description": "Key is valid", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/KeyValidation" } } } }, "401": { "$ref": "#/components/responses/InvalidKey" }, "429": { "$ref": "#/components/responses/RateLimited" } } }
    },
    "/account": {
      "get": { "tags": ["Auth"], "operationId": "getAccount", "summary": "Get account & quota", "description": "Returns the authenticated user's profile, plan, and remaining check quota.", "responses": { "200": { "description": "Account info", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Account" } } } }, "401": { "$ref": "#/components/responses/InvalidKey" }, "429": { "$ref": "#/components/responses/RateLimited" } } },
      "post": { "tags": ["Auth"], "operationId": "getAccountPost", "summary": "Get account & quota (POST)", "responses": { "200": { "description": "Account info", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Account" } } } }, "401": { "$ref": "#/components/responses/InvalidKey" }, "429": { "$ref": "#/components/responses/RateLimited" } } }
    },
    "/languages": {
      "get": { "tags": ["Reference"], "operationId": "getLanguages", "summary": "List supported languages", "description": "Languages you may pass to `language` when creating a check. Each entry includes the numeric `id` used by the API.", "responses": { "200": { "description": "Language catalog", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/LanguageList" } } } }, "401": { "$ref": "#/components/responses/InvalidKey" }, "429": { "$ref": "#/components/responses/RateLimited" } } },
      "post": { "tags": ["Reference"], "operationId": "getLanguagesPost", "summary": "List supported languages (POST)", "responses": { "200": { "description": "Language catalog", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/LanguageList" } } } }, "401": { "$ref": "#/components/responses/InvalidKey" }, "429": { "$ref": "#/components/responses/RateLimited" } } }
    },
    "/test-types": {
      "get": { "tags": ["Reference"], "operationId": "getTestTypes", "summary": "List engines (test types)", "description": "Returns the analysis engines available to your account. Use a returned `id` as `test_type` on create/start/quick. `default_test_type` is 1 and `recommended_test_type` is 9 (Group Similarity). Engine `id`s are live database ids, not a fixed sequence.", "responses": { "200": { "description": "Engine catalog and your access", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/TestTypeList" } } } }, "401": { "$ref": "#/components/responses/InvalidKey" }, "429": { "$ref": "#/components/responses/RateLimited" }, "500": { "$ref": "#/components/responses/ServerError" } } },
      "post": { "tags": ["Reference"], "operationId": "getTestTypesPost", "summary": "List engines (test types) (POST)", "responses": { "200": { "description": "Engine catalog and your access", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/TestTypeList" } } } }, "401": { "$ref": "#/components/responses/InvalidKey" }, "429": { "$ref": "#/components/responses/RateLimited" }, "500": { "$ref": "#/components/responses/ServerError" } } }
    },
    "/checks": {
      "get": { "tags": ["Checks"], "operationId": "listChecks", "summary": "List your checks", "description": "Returns every check (assignment) owned by the account, newest first, each with its status object.", "responses": { "200": { "description": "Array of checks", "content": { "application/json": { "schema": { "type": "array", "items": { "$ref": "#/components/schemas/Check" } } } } }, "401": { "$ref": "#/components/responses/InvalidKey" }, "429": { "$ref": "#/components/responses/RateLimited" } } },
      "post": { "tags": ["Checks"], "operationId": "listChecksPost", "summary": "List your checks (POST)", "responses": { "200": { "description": "Array of checks", "content": { "application/json": { "schema": { "type": "array", "items": { "$ref": "#/components/schemas/Check" } } } } }, "401": { "$ref": "#/components/responses/InvalidKey" }, "429": { "$ref": "#/components/responses/RateLimited" } } }
    },
    "/check/create": {
      "post": { "tags": ["Checks"], "operationId": "createCheck", "summary": "Create a check", "description": "Creates an empty check. Only `name` is required; `language` and `test_type` are optional and default to 13 and 1 respectively.", "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": ["name"], "properties": { "name": { "type": "string", "minLength": 3, "maxLength": 255, "description": "Check name." }, "language": { "type": "integer", "default": 13, "description": "Language id from GET /languages. Use 999 for Auto Detect; an unknown/invalid id falls back to Auto Detect instead of returning an error." }, "test_type": { "type": "integer", "minimum": 1, "default": 1, "description": "Engine id from GET /test-types." }, "ai_run": { "type": "boolean", "default": true, "description": "Run AI-generated-code detection on this check. Accepts true/false/1/0." }, "base_code_detection": { "type": "boolean", "default": false, "description": "Detect shared base/boilerplate (starter) code." } } } } } }, "responses": { "201": { "description": "Created check", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CheckCreated" } } } }, "401": { "$ref": "#/components/responses/InvalidKey" }, "429": { "$ref": "#/components/responses/RateLimited" }, "422": { "$ref": "#/components/responses/ValidationError" } } }
    },
    "/check/upload": {
      "post": { "tags": ["Submissions"], "operationId": "uploadFile", "summary": "Upload a submission (ZIP)", "description": "Uploads one ZIP archive of source code into a check. Max 10 MB. Call once per submission, or use /check/upload-batch.", "requestBody": { "required": true, "content": { "multipart/form-data": { "schema": { "type": "object", "required": ["check_id", "file"], "properties": { "check_id": { "type": "integer", "description": "Target check id." }, "file": { "type": "string", "format": "binary", "description": "ZIP archive (mimes:zip, max 10 MB)." } } } } } }, "responses": { "200": { "description": "Upload accepted", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/UploadResult" } } } }, "401": { "$ref": "#/components/responses/InvalidKey" }, "429": { "$ref": "#/components/responses/RateLimited" }, "403": { "$ref": "#/components/responses/Forbidden" }, "422": { "$ref": "#/components/responses/ValidationError" }, "500": { "$ref": "#/components/responses/ServerError" } } }
    },
    "/check/upload-batch": {
      "post": { "tags": ["Submissions"], "operationId": "batchUpload", "summary": "Upload many submissions", "description": "Uploads 1–50 ZIP files into a check in one request. Per-file failures are reported in `failed_uploads` with a 200 response.", "requestBody": { "required": true, "content": { "multipart/form-data": { "schema": { "type": "object", "required": ["check_id", "files"], "properties": { "check_id": { "type": "integer" }, "files": { "type": "array", "minItems": 1, "maxItems": 50, "items": { "type": "string", "format": "binary" }, "description": "1–50 ZIP archives (each mimes:zip, max 10 MB)." } } } } } }, "responses": { "200": { "description": "Batch processed", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BatchUploadResult" } } } }, "401": { "$ref": "#/components/responses/InvalidKey" }, "429": { "$ref": "#/components/responses/RateLimited" }, "403": { "$ref": "#/components/responses/Forbidden" }, "422": { "$ref": "#/components/responses/ValidationError" }, "500": { "$ref": "#/components/responses/ServerError" } } }
    },
    "/check/get": {
      "post": { "tags": ["Checks"], "operationId": "getCheck", "summary": "Get a check", "description": "Returns a check with its status, submission count, and submissions.", "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": ["check_id"], "properties": { "check_id": { "type": "integer", "minimum": 1 } } } } } }, "responses": { "200": { "description": "Check detail", "content": { "application/json": { "schema": { "type": "object", "properties": { "check": { "$ref": "#/components/schemas/Check" }, "status": { "type": "string" }, "submission_count": { "type": "integer" }, "submissions": { "type": "array", "items": { "$ref": "#/components/schemas/Submission" } } } } } } }, "401": { "$ref": "#/components/responses/InvalidKey" }, "429": { "$ref": "#/components/responses/RateLimited" }, "422": { "$ref": "#/components/responses/ValidationError" } } }
    },
    "/check/start": {
      "post": { "tags": ["Run"], "operationId": "startChecking", "summary": "Start a check", "description": "Queues analysis for a check that already has submissions. `webcheck` and `dbcheck` only take effect when BOTH are supplied (both true → engine 1, both false → engine 9); otherwise the check's existing engine is used. The check is set to status_id 7 (queued).", "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": ["check_id"], "properties": { "check_id": { "type": "integer", "minimum": 1 }, "webcheck": { "type": "boolean", "description": "Enable internet/web matching." }, "dbcheck": { "type": "boolean", "description": "Enable Codequiry database matching." }, "test_type": { "type": "integer", "minimum": 1, "description": "Approved engine id (overrides webcheck/dbcheck mapping)." }, "ai_run": { "type": "boolean", "default": true, "description": "Run AI-generated-code detection on this check. Accepts true/false/1/0." }, "base_code_detection": { "type": "boolean", "default": false, "description": "Detect shared base/boilerplate (starter) code." } } } } } }, "responses": { "200": { "description": "Check queued", "content": { "application/json": { "schema": { "type": "object", "properties": { "success": { "type": "boolean" }, "check": { "$ref": "#/components/schemas/Check" }, "status": { "type": "string" }, "submission_count": { "type": "integer" }, "checkURL": { "type": "string" } } } } } }, "401": { "$ref": "#/components/responses/InvalidKey" }, "429": { "$ref": "#/components/responses/RateLimited" }, "403": { "$ref": "#/components/responses/Forbidden" }, "409": { "$ref": "#/components/responses/Conflict" }, "422": { "$ref": "#/components/responses/ValidationError" }, "503": { "description": "Analysis services are temporarily offline.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } } }
    },
    "/check/quick": {
      "post": { "tags": ["Run"], "operationId": "quickCheck", "summary": "Quick check (all-in-one)", "description": "Creates a check, uploads files, and starts analysis in a single authenticated call. Distinct from the public website Quick Check widget.", "requestBody": { "required": true, "content": { "multipart/form-data": { "schema": { "type": "object", "required": ["name", "files"], "properties": { "name": { "type": "string", "minLength": 3, "maxLength": 255 }, "language": { "type": "integer", "default": 13, "description": "Language id from GET /languages. Use 999 for Auto Detect; an unknown/invalid id falls back to Auto Detect." }, "files": { "type": "array", "items": { "type": "string", "format": "binary" }, "description": "One or more ZIP archives (each mimes:zip, max 10 MB)." }, "webcheck": { "type": "boolean" }, "dbcheck": { "type": "boolean" }, "test_type": { "type": "integer", "minimum": 1 }, "ai_run": { "type": "boolean", "default": true, "description": "Run AI-generated-code detection on this check. Accepts true/false/1/0." }, "base_code_detection": { "type": "boolean", "default": false, "description": "Detect shared base/boilerplate (starter) code." } } } } } }, "responses": { "201": { "description": "Created and started", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/QuickCheckResult" } } } }, "401": { "$ref": "#/components/responses/InvalidKey" }, "429": { "$ref": "#/components/responses/RateLimited" }, "422": { "$ref": "#/components/responses/ValidationError" }, "500": { "$ref": "#/components/responses/ServerError" }, "503": { "description": "Analysis services are temporarily offline.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } } }
    },
    "/check/status": {
      "post": { "tags": ["Run"], "operationId": "getCheckStatusPost", "summary": "Get check status", "description": "Polling endpoint. Equivalent to GET /checks/{checkId}/status.", "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": ["check_id"], "properties": { "check_id": { "type": "integer" } } } } } }, "responses": { "200": { "description": "Status", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CheckStatus" } } } }, "401": { "$ref": "#/components/responses/InvalidKey" }, "429": { "$ref": "#/components/responses/RateLimited" }, "404": { "$ref": "#/components/responses/NotFound" }, "422": { "$ref": "#/components/responses/ValidationError" } } }
    },
    "/checks/{checkId}/status": {
      "get": { "tags": ["Run"], "operationId": "getCheckStatus", "summary": "Get check status (REST)", "parameters": [ { "$ref": "#/components/parameters/CheckId" } ], "responses": { "200": { "description": "Status", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CheckStatus" } } } }, "401": { "$ref": "#/components/responses/InvalidKey" }, "429": { "$ref": "#/components/responses/RateLimited" }, "404": { "$ref": "#/components/responses/NotFound" }, "422": { "$ref": "#/components/responses/ValidationError" } } }
    },
    "/check/overview": {
      "post": { "tags": ["Results"], "operationId": "getOverview", "summary": "Get results overview", "description": "Per-submission similarity scores and bar-chart data. The check must be completed (status_id 4) or you get 409.", "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": ["check_id"], "properties": { "check_id": { "type": "integer", "minimum": 1 } } } } } }, "responses": { "200": { "description": "Overview", "content": { "application/json": { "schema": { "type": "object", "properties": { "overviewURL": { "type": "string" }, "submissions": { "type": "array", "items": { "$ref": "#/components/schemas/Submission" } }, "bardata": { "type": "array", "items": { "type": "object", "properties": { "submission": { "type": "string" }, "score": { "type": "number" } } } } } } } } }, "401": { "$ref": "#/components/responses/InvalidKey" }, "429": { "$ref": "#/components/responses/RateLimited" }, "409": { "$ref": "#/components/responses/Conflict" }, "422": { "$ref": "#/components/responses/ValidationError" } } }
    },
    "/check/overviewCSV": {
      "post": { "tags": ["Results"], "operationId": "getOverviewCSV", "summary": "Get overview as CSV", "description": "Streams a CSV download with columns Submission,Score. Requires a completed check.", "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": ["check_id"], "properties": { "check_id": { "type": "integer" } } } } } }, "responses": { "200": { "description": "CSV file", "content": { "text/csv": { "schema": { "type": "string" } } } }, "401": { "$ref": "#/components/responses/InvalidKey" }, "429": { "$ref": "#/components/responses/RateLimited" }, "409": { "$ref": "#/components/responses/Conflict" }, "422": { "$ref": "#/components/responses/ValidationError" } } }
    },
    "/check/results": {
      "post": { "tags": ["Results"], "operationId": "getResult", "summary": "Get detailed results", "description": "Full match detail for one submission, including peer, web/external, and AI matches.", "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": ["check_id", "submission_id"], "properties": { "check_id": { "type": "integer", "minimum": 1 }, "submission_id": { "type": "integer" } } } } } }, "responses": { "200": { "description": "Detailed results", "content": { "application/json": { "schema": { "type": "object", "properties": { "submission": { "$ref": "#/components/schemas/Submission" }, "avg": { "type": "number" }, "max": { "type": "number" }, "min": { "type": "number" }, "other_matches": { "type": "array", "items": { "$ref": "#/components/schemas/Match" } }, "related_submissions": { "type": "array", "items": { "$ref": "#/components/schemas/Submission" } }, "related_files": { "type": "array", "items": { "type": "object" } } } } } } }, "401": { "$ref": "#/components/responses/InvalidKey" }, "429": { "$ref": "#/components/responses/RateLimited" }, "409": { "$ref": "#/components/responses/Conflict" }, "422": { "$ref": "#/components/responses/ValidationError" } } }
    },
    "/check/getRemoteFile": {
      "post": { "tags": ["Results"], "operationId": "getRemoteFile", "summary": "Get a matched web file", "description": "Fetches the stored content of an external/web match. `location` and `source` come verbatim from a match object in /check/results.", "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": ["location", "source"], "properties": { "location": { "type": "string" }, "source": { "type": "string" } } } } } }, "responses": { "200": { "description": "Stored web file", "content": { "application/json": { "schema": { "type": "object", "properties": { "file": { "$ref": "#/components/schemas/RemoteFile" } } } } } }, "401": { "$ref": "#/components/responses/InvalidKey" }, "429": { "$ref": "#/components/responses/RateLimited" }, "403": { "$ref": "#/components/responses/Forbidden" }, "404": { "$ref": "#/components/responses/NotFound" }, "422": { "$ref": "#/components/responses/ValidationError" } } }
    },
    "/ai-results": {
      "get": { "tags": ["Results"], "operationId": "getAIResults", "summary": "Get AI detection results", "description": "AI-generated-code detection and code-quality analysis for every submission in a check.", "parameters": [ { "name": "assignment_id", "in": "query", "required": true, "schema": { "type": "integer", "minimum": 1 }, "description": "Check id." } ], "responses": { "200": { "description": "AI results", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/AIResults" } } } }, "401": { "$ref": "#/components/responses/InvalidKey" }, "429": { "$ref": "#/components/responses/RateLimited" }, "404": { "$ref": "#/components/responses/NotFound" }, "422": { "$ref": "#/components/responses/ValidationError" } } },
      "post": { "tags": ["Results"], "operationId": "getAIResultsPost", "summary": "Get AI detection results (POST)", "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": ["assignment_id"], "properties": { "assignment_id": { "type": "integer", "minimum": 1 } } } } } }, "responses": { "200": { "description": "AI results", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/AIResults" } } } }, "401": { "$ref": "#/components/responses/InvalidKey" }, "429": { "$ref": "#/components/responses/RateLimited" }, "404": { "$ref": "#/components/responses/NotFound" }, "422": { "$ref": "#/components/responses/ValidationError" } } }
    },
    "/check/summary": {
      "post": { "tags": ["Results"], "operationId": "getCheckSummaryPost", "summary": "Get check summary", "description": "Aggregate stats for a check. Equivalent to GET /checks/{checkId}/summary.", "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": ["check_id"], "properties": { "check_id": { "type": "integer" } } } } } }, "responses": { "200": { "description": "Summary", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CheckSummary" } } } }, "401": { "$ref": "#/components/responses/InvalidKey" }, "429": { "$ref": "#/components/responses/RateLimited" }, "404": { "$ref": "#/components/responses/NotFound" }, "422": { "$ref": "#/components/responses/ValidationError" } } }
    },
    "/checks/{checkId}/summary": {
      "get": { "tags": ["Results"], "operationId": "getCheckSummary", "summary": "Get check summary (REST)", "parameters": [ { "$ref": "#/components/parameters/CheckId" } ], "responses": { "200": { "description": "Summary", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CheckSummary" } } } }, "401": { "$ref": "#/components/responses/InvalidKey" }, "429": { "$ref": "#/components/responses/RateLimited" }, "404": { "$ref": "#/components/responses/NotFound" }, "422": { "$ref": "#/components/responses/ValidationError" } } }
    },
    "/check/export": {
      "post": { "tags": ["Results"], "operationId": "exportCheckResultsPost", "summary": "Export results", "description": "Exports a completed check as JSON or CSV (`format`, default csv). Equivalent to GET /checks/{checkId}/export.", "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": ["check_id"], "properties": { "check_id": { "type": "integer" }, "format": { "type": "string", "enum": ["csv", "json"], "default": "csv" } } } } } }, "responses": { "200": { "description": "Export (JSON body or CSV download)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ExportResult" } }, "text/csv": { "schema": { "type": "string" } } } }, "401": { "$ref": "#/components/responses/InvalidKey" }, "429": { "$ref": "#/components/responses/RateLimited" }, "404": { "$ref": "#/components/responses/NotFound" }, "409": { "$ref": "#/components/responses/Conflict" }, "422": { "$ref": "#/components/responses/ValidationError" } } }
    },
    "/checks/{checkId}/export": {
      "get": { "tags": ["Results"], "operationId": "exportCheckResults", "summary": "Export results (REST)", "parameters": [ { "$ref": "#/components/parameters/CheckId" }, { "name": "format", "in": "query", "required": false, "schema": { "type": "string", "enum": ["csv", "json"], "default": "csv" } } ], "responses": { "200": { "description": "Export (JSON body or CSV download)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ExportResult" } }, "text/csv": { "schema": { "type": "string" } } } }, "401": { "$ref": "#/components/responses/InvalidKey" }, "429": { "$ref": "#/components/responses/RateLimited" }, "404": { "$ref": "#/components/responses/NotFound" }, "409": { "$ref": "#/components/responses/Conflict" }, "422": { "$ref": "#/components/responses/ValidationError" } } }
    },
    "/check/update": {
      "post": { "tags": ["Checks"], "operationId": "updateCheckPost", "summary": "Update a check", "description": "Renames a check and/or changes its language. Equivalent to PATCH /checks/{checkId}.", "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": ["check_id"], "properties": { "check_id": { "type": "integer" }, "name": { "type": "string", "minLength": 3, "maxLength": 255 }, "language": { "type": "integer" } } } } } }, "responses": { "200": { "description": "Updated check", "content": { "application/json": { "schema": { "type": "object", "properties": { "success": { "type": "boolean" }, "message": { "type": "string" }, "check": { "$ref": "#/components/schemas/Check" } } } } } }, "401": { "$ref": "#/components/responses/InvalidKey" }, "429": { "$ref": "#/components/responses/RateLimited" }, "403": { "$ref": "#/components/responses/Forbidden" }, "404": { "$ref": "#/components/responses/NotFound" }, "422": { "$ref": "#/components/responses/ValidationError" } } }
    },
    "/checks/{checkId}": {
      "get": { "tags": ["Checks"], "operationId": "getCheckRest", "summary": "Get a check (REST)", "description": "Retrieves a check with its status, submission count, and submissions. Equivalent to POST /check/get.", "parameters": [ { "$ref": "#/components/parameters/CheckId" } ], "responses": { "200": { "description": "Check detail", "content": { "application/json": { "schema": { "type": "object", "properties": { "check": { "$ref": "#/components/schemas/Check" }, "status": { "type": "string" }, "submission_count": { "type": "integer" }, "submissions": { "type": "array", "items": { "$ref": "#/components/schemas/Submission" } } } } } } }, "401": { "$ref": "#/components/responses/InvalidKey" }, "429": { "$ref": "#/components/responses/RateLimited" }, "422": { "$ref": "#/components/responses/ValidationError" } } },
      "patch": { "tags": ["Checks"], "operationId": "updateCheck", "summary": "Update a check (REST)", "parameters": [ { "$ref": "#/components/parameters/CheckId" } ], "requestBody": { "required": false, "content": { "application/json": { "schema": { "type": "object", "properties": { "name": { "type": "string", "minLength": 3, "maxLength": 255 }, "language": { "type": "integer" } } } } } }, "responses": { "200": { "description": "Updated check", "content": { "application/json": { "schema": { "type": "object", "properties": { "success": { "type": "boolean" }, "message": { "type": "string" }, "check": { "$ref": "#/components/schemas/Check" } } } } } }, "401": { "$ref": "#/components/responses/InvalidKey" }, "429": { "$ref": "#/components/responses/RateLimited" }, "403": { "$ref": "#/components/responses/Forbidden" }, "404": { "$ref": "#/components/responses/NotFound" }, "422": { "$ref": "#/components/responses/ValidationError" } } },
      "delete": { "tags": ["Checks"], "operationId": "deleteCheck", "summary": "Delete a check (REST)", "parameters": [ { "$ref": "#/components/parameters/CheckId" } ], "responses": { "200": { "description": "Deleted", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/DeleteResult" } } } }, "401": { "$ref": "#/components/responses/InvalidKey" }, "429": { "$ref": "#/components/responses/RateLimited" }, "403": { "$ref": "#/components/responses/Forbidden" }, "404": { "$ref": "#/components/responses/NotFound" }, "409": { "$ref": "#/components/responses/Conflict" } } }
    },
    "/check/delete": {
      "post": { "tags": ["Checks"], "operationId": "deleteCheckPost", "summary": "Delete a check", "description": "Equivalent to DELETE /checks/{checkId}. Free-trial and demo checks cannot be deleted (403); a processing check cannot be deleted (409).", "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": ["check_id"], "properties": { "check_id": { "type": "integer" } } } } } }, "responses": { "200": { "description": "Deleted", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/DeleteResult" } } } }, "401": { "$ref": "#/components/responses/InvalidKey" }, "429": { "$ref": "#/components/responses/RateLimited" }, "403": { "$ref": "#/components/responses/Forbidden" }, "404": { "$ref": "#/components/responses/NotFound" }, "409": { "$ref": "#/components/responses/Conflict" }, "422": { "$ref": "#/components/responses/ValidationError" } } }
    },
    "/check/deleteSubmission": {
      "post": { "tags": ["Submissions"], "operationId": "deleteSubmission", "summary": "Delete a submission", "description": "Removes one submission from a check. Not available on free trials (403) or demo checks (403).", "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": ["check_id", "submission_id"], "properties": { "check_id": { "type": "integer" }, "submission_id": { "type": "integer", "minimum": 1 } } } } } }, "responses": { "200": { "description": "Deleted", "content": { "application/json": { "schema": { "type": "object", "properties": { "success": { "type": "boolean" }, "message": { "type": "string" } } } } } }, "401": { "$ref": "#/components/responses/InvalidKey" }, "429": { "$ref": "#/components/responses/RateLimited" }, "403": { "$ref": "#/components/responses/Forbidden" }, "422": { "$ref": "#/components/responses/ValidationError" }, "500": { "$ref": "#/components/responses/ServerError" } } }
    }
  },
  "components": {
    "securitySchemes": {
      "apikey": { "type": "apiKey", "in": "header", "name": "apikey", "description": "Your 64-character API key from the Codequiry dashboard." }
    },
    "parameters": {
      "CheckId": { "name": "checkId", "in": "path", "required": true, "schema": { "type": "integer" }, "description": "The check (assignment) id." }
    },
    "responses": {
      "RateLimited": { "description": "Rate limit exceeded: more than 60 requests in one minute from this IP. Retry after the number of seconds in the Retry-After header.", "headers": { "Retry-After": { "description": "Seconds to wait before retrying.", "schema": { "type": "integer" } }, "X-RateLimit-Limit": { "description": "Always 60.", "schema": { "type": "integer" } }, "X-RateLimit-Remaining": { "description": "Calls left in the window (0 here).", "schema": { "type": "integer" } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the window reopens. Sent only on 429.", "schema": { "type": "integer" } } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } },
      "InvalidKey": { "description": "Missing or invalid API key.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" }, "example": { "error": "Invalid API key" } } } },
      "ValidationError": { "description": "Request validation failed.", "content": { "application/json": { "schema": { "type": "object", "properties": { "error": { "type": "string" }, "validation_errors": { "type": "object", "additionalProperties": { "type": "array", "items": { "type": "string" } } } } } } } },
      "NotFound": { "description": "Resource not found or not owned by this account.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } },
      "Forbidden": { "description": "Not permitted (e.g. free-trial limitation, or a read-only demo check).", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } },
      "Conflict": { "description": "Check is in a state that does not allow this operation (e.g. still processing, or not yet completed).", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } },
      "ServerError": { "description": "Unexpected server error.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }
    },
    "schemas": {
      "Error": { "type": "object", "properties": { "error": { "type": "string" } } },
      "KeyValidation": { "type": "object", "properties": { "valid": { "type": "boolean" }, "user_id": { "type": "integer" }, "email": { "type": "string" }, "name": { "type": "string" } } },
      "Account": { "type": "object", "properties": { "id": { "type": "integer" }, "name": { "type": "string" }, "email": { "type": "string" }, "quota": { "type": "object", "properties": { "remaining": { "type": "integer" }, "total": { "type": "integer" }, "unlimited": { "type": "boolean" }, "checks_remaining": { "type": "integer" }, "reset_date": { "type": "string", "nullable": true } } }, "submissions": { "type": "integer" }, "is_pro": { "type": "boolean" }, "plan_id": { "type": "integer", "nullable": true }, "edu_verified": { "type": "boolean" } } },
      "LanguageList": { "type": "object", "properties": { "success": { "type": "boolean" }, "count": { "type": "integer" }, "languages": { "type": "array", "items": { "type": "object", "properties": { "id": { "type": "integer" }, "language": { "type": "string" }, "extensions": { "type": "string" } } } } } },
      "TestTypeList": { "type": "object", "properties": { "success": { "type": "boolean" }, "test_types": { "type": "array", "items": { "type": "object", "properties": { "id": { "type": "integer" }, "name": { "type": "string" }, "description": { "type": "string" }, "features": { "type": "array", "items": { "type": "string" } }, "consumption": { "type": "integer" }, "peer_only": { "type": "boolean" }, "auto_detect_base_code": { "type": "boolean" }, "available": { "type": "boolean" } } } }, "user_access": { "type": "object", "properties": { "has_full_access": { "type": "boolean" }, "is_pro": { "type": "boolean" }, "is_edu_verified": { "type": "boolean" }, "is_enterprise": { "type": "boolean" } } }, "default_test_type": { "type": "integer", "example": 1 }, "recommended_test_type": { "type": "integer", "example": 9 }, "note": { "type": "string" } } },
      "Check": { "type": "object", "description": "A check (internally an assignment). Endpoints return the full assignment row, so more fields are present than are listed here; only the stable, documented ones are shown.", "properties": { "id": { "type": "integer" }, "name": { "type": "string" }, "status_id": { "type": "integer" }, "language_id": { "type": "integer" }, "test_type": { "type": "integer" }, "ai_run": { "type": "integer", "description": "1 if AI-generated-code detection runs for this check." }, "base_code_detection": { "type": "integer", "description": "1 if base/boilerplate-code detection is enabled." }, "created_at": { "type": "string" }, "updated_at": { "type": "string" }, "assignmentstatuses": { "type": "object", "description": "Expanded status, included only by GET/POST /checks. Not returned by /check/create, /check/get or /check/update - use status_id there, or the top-level status string that /check/get returns.", "properties": { "id": { "type": "integer" }, "status": { "type": "string" } } } } },
      "CheckCreated": { "type": "object", "description": "The check as returned by /check/create. Same row as Check but without the expanded assignmentstatuses relation.", "properties": { "id": { "type": "integer", "description": "Save this - it is the check_id every other endpoint takes." }, "name": { "type": "string" }, "status_id": { "type": "integer", "description": "Always 1 (new) on creation." }, "language_id": { "type": "integer" }, "test_type": { "type": "integer" }, "ai_run": { "type": "integer" }, "base_code_detection": { "type": "integer" }, "job_id": { "type": "integer", "description": "0 until the check is started." }, "created_at": { "type": "string" }, "updated_at": { "type": "string" } } },
      "Submission": { "type": "object", "properties": { "id": { "type": "integer" }, "assignment_id": { "type": "integer" }, "filename": { "type": "string" }, "status_id": { "type": "integer" }, "total_result": { "type": "number" }, "result_web": { "type": "number" }, "submissionresults": { "type": "array", "items": { "type": "object" } } } },
      "Match": { "type": "object", "description": "A matched code region. match_type 1 = peer, >1 = external/web, 10 = AI.", "properties": { "id": { "type": "integer" }, "submission_id": { "type": "integer" }, "submission_id_matched": { "type": "integer" }, "similarity": { "type": "number" }, "matched_similarity": { "type": "number" }, "file": { "type": "string" }, "file_matched": { "type": "string" }, "line_start": { "type": "integer" }, "line_end": { "type": "integer" }, "line_matched_start": { "type": "integer" }, "line_matched_end": { "type": "integer" }, "tokens": { "type": "integer" }, "match_type": { "type": "integer" }, "location": { "type": "string" }, "source": { "type": "string" } } },
      "RemoteFile": { "type": "object", "properties": { "id": { "type": "integer" }, "filedir": { "type": "string" }, "content": { "type": "string" }, "location": { "type": "string" }, "source": { "type": "string" }, "submission_id": { "type": "integer" }, "created_at": { "type": "string" }, "updated_at": { "type": "string" } } },
      "UploadResult": { "type": "object", "properties": { "data": { "type": "string" }, "file": { "type": "string" }, "file_size": { "type": "integer" }, "submission_count": { "type": "integer" }, "check": { "$ref": "#/components/schemas/Check" } } },
      "BatchUploadResult": { "type": "object", "properties": { "success": { "type": "boolean" }, "message": { "type": "string" }, "uploaded": { "type": "array", "items": { "type": "object", "properties": { "id": { "type": "integer" }, "filename": { "type": "string" }, "file_size": { "type": "integer" }, "status_id": { "type": "integer" } } } }, "uploaded_count": { "type": "integer" }, "failed_count": { "type": "integer" }, "failed_uploads": { "type": "array", "items": { "type": "object", "properties": { "file": { "type": "string" }, "error": { "type": "string" } } } }, "check": { "$ref": "#/components/schemas/Check" } } },
      "CheckStatus": { "type": "object", "properties": { "check_id": { "type": "integer" }, "status_id": { "type": "integer" }, "status": { "type": "string" }, "status_message": { "type": "string" }, "progress": { "type": "number" }, "submissions_total": { "type": "integer" }, "submissions_completed": { "type": "integer" }, "estimated_completion": { "type": "string", "nullable": true, "description": "ISO-8601, set only while status_id is 6 or 7." } } },
      "CheckSummary": { "type": "object", "properties": { "check_id": { "type": "integer" }, "check_name": { "type": "string" }, "status": { "type": "string" }, "status_id": { "type": "integer" }, "submission_count": { "type": "integer" }, "completed_submissions": { "type": "integer" }, "plagiarism_stats": { "type": "object", "properties": { "avg": { "type": "number" }, "max": { "type": "number" }, "min": { "type": "number" } } }, "ai_detection_stats": { "type": "object", "properties": { "avg": { "type": "number" }, "max": { "type": "number" } } }, "flagged_submissions": { "type": "integer", "description": "Count where plagiarism total > 75 OR avg AI > 75." }, "processing_time_seconds": { "type": "integer", "nullable": true }, "created_at": { "type": "string" }, "updated_at": { "type": "string" } } },
      "ExportResult": { "type": "object", "properties": { "check_id": { "type": "integer" }, "check_name": { "type": "string" }, "export_date": { "type": "string" }, "submissions": { "type": "array", "items": { "type": "object", "properties": { "submission_id": { "type": "integer" }, "filename": { "type": "string" }, "status": { "type": "string" }, "plagiarism_local": { "type": "number" }, "plagiarism_web": { "type": "number" }, "plagiarism_total": { "type": "number" }, "matches_local": { "type": "integer" }, "matches_web": { "type": "integer" }, "ai_detection_avg": { "type": "number" }, "ai_detection_max": { "type": "number" }, "code_quality_avg": { "type": "number" }, "file_size": { "type": "integer" }, "created_at": { "type": "string" }, "updated_at": { "type": "string" } } } } } },
      "DeleteResult": { "type": "object", "properties": { "success": { "type": "boolean" }, "message": { "type": "string" }, "check_id": { "type": "integer" }, "check_name": { "type": "string" } } },
      "QuickCheckResult": { "type": "object", "properties": { "success": { "type": "boolean" }, "message": { "type": "string" }, "data": { "type": "object", "properties": { "check_id": { "type": "integer" }, "check_name": { "type": "string" }, "language": { "type": "string" }, "language_id": { "type": "integer" }, "status": { "type": "string" }, "status_id": { "type": "integer" }, "test_type": { "type": "integer" }, "submissions": { "type": "object", "properties": { "uploaded": { "type": "integer" }, "failed": { "type": "integer" }, "total": { "type": "integer" }, "details": { "type": "array", "items": { "type": "object" } } } }, "failed_uploads": { "type": "array", "items": { "type": "object" } }, "detection_settings": { "type": "object" }, "check_url": { "type": "string" }, "execution_time_ms": { "type": "number" } } }, "next_steps": { "type": "object" } } },
      "AIResults": { "type": "object", "properties": { "success": { "type": "boolean" }, "assignment_status": { "type": "integer", "description": "Numeric status_id." }, "statistics": { "type": "object", "properties": { "total_submissions": { "type": "integer" }, "submissions_with_ai_detection": { "type": "integer" }, "submissions_with_code_quality": { "type": "integer" }, "avg_ai_detection": { "type": "number" }, "avg_code_quality": { "type": "number" }, "high_ai_risk_count": { "type": "integer" }, "medium_ai_risk_count": { "type": "integer" }, "low_ai_risk_count": { "type": "integer" } } }, "submissions": { "type": "array", "items": { "type": "object", "properties": { "submission_id": { "type": "integer" }, "filename": { "type": "string" }, "status": { "type": "string" }, "status_id": { "type": "integer" }, "plagiarism_score": { "type": "object", "properties": { "local": { "type": "number" }, "web": { "type": "number" }, "total": { "type": "number" } } }, "matches": { "type": "object", "properties": { "local": { "type": "integer" }, "web": { "type": "integer" } } }, "ai_detection": { "type": "object", "nullable": true }, "ai_code_quality": { "type": "object", "nullable": true }, "file_size": { "type": "integer" }, "created_at": { "type": "string" }, "updated_at": { "type": "string" } } } } } }
    }
  }
}
