{"openapi":"3.1.0","info":{"title":"WriteGuard API","version":"1.0.0","description":"Check text for plagiarism and AI-generated content.\n\n**Authentication** — every request needs an API key sent as a bearer token:\n\n```\nAuthorization: Bearer wgk_your_key_here\n```\n\nCreate keys in **Settings → API**. The key is shown once at creation;\nit is stored only as a hash and cannot be retrieved again.\n\n**Paid plans only** — these docs are public, but calls require a paid plan.\nA key on the free plan authenticates and then returns `403 plan_required`.\n\n**Rate limit** — 60 requests per minute per key. Responses carry\n`X-RateLimit-Limit` and `X-RateLimit-Remaining`; exceeding it returns `429`\nwith `Retry-After`.\n\n**Billing** — a scan costs its word count once per tool selected. 800 words\nchecked for both plagiarism and AI costs 1,600 words. Words come from your\nmonthly allowance first, then your purchased balance. If a scan cannot be\nqueued, its words are refunded automatically.\n\n**Minimum length** — text must be at least 50 words. Shorter texts are\nrejected with `400 text_too_short` and nothing is charged.\n\n**Scans are asynchronous** — `POST /scans` returns `202` immediately. Poll\n`GET /scans/{id}` until `status` is `completed` (typically 30–90s depending\non length)."},"servers":[{"url":"https://app.plagiarismcheckerplus.com/api/public/v1","description":"Production"}],"security":[{"apiKey":[]}],"tags":[{"name":"Scans","description":"Submit text and retrieve results."},{"name":"Account","description":"Plan and remaining word balance."}],"components":{"securitySchemes":{"apiKey":{"type":"http","scheme":"bearer","description":"Your API key, e.g. `wgk_...`. Create one in Settings → API."}},"schemas":{"Error":{"type":"object","properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Stable machine-readable error code.","examples":["insufficient_words"]},"message":{"type":"string"}}}}},"ScanSummary":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":["string","null"]},"status":{"type":"string","enum":["pending","processing","completed","failed"]},"wordCount":{"type":"integer","description":"Words in the submitted text."},"wordsCharged":{"type":"integer","description":"Words billed — wordCount × number of tools."},"tools":{"type":"array","items":{"type":"string","enum":["plagiarism","ai_detect"]}},"createdAt":{"type":"string","format":"date-time"},"completedAt":{"type":["string","null"],"format":"date-time"}}},"ScanDetail":{"allOf":[{"$ref":"#/components/schemas/ScanSummary"},{"type":"object","properties":{"text":{"type":"string","description":"Only present when `include_text=true`."},"progress":{"type":"object","properties":{"percent":{"type":"integer","minimum":0,"maximum":100},"tools":{"type":"array","items":{"type":"object","properties":{"tool":{"type":"string"},"status":{"type":"string"},"percent":{"type":"integer"}}}}}},"results":{"type":"object","description":"Populated as each tool finishes; null until then.","properties":{"plagiarism":{"type":["object","null"],"properties":{"score":{"type":"number","description":"Percentage of the text matched to sources."},"uniqueSources":{"type":"integer"},"sources":{"type":"array","items":{"type":"object","properties":{"url":{"type":"string","format":"uri"},"domain":{"type":"string"},"matchPercentage":{"type":"number"},"matchedText":{"type":"string","description":"The passage from your text that matched."},"excerpt":{"type":["string","null"],"description":"Surrounding text from the source page."}}}}}},"aiDetection":{"type":["object","null"],"properties":{"score":{"type":"number","description":"Percentage of the text judged AI-generated."},"summary":{"type":["string","null"]},"sentences":{"type":"array","description":"Per-sentence verdicts. Sentences too short to judge are omitted.","items":{"type":"object","properties":{"text":{"type":"string"},"probability":{"type":"number","description":"0–1 likelihood the sentence is AI-generated."},"offset":{"type":"integer","description":"Character offset into the submitted text."},"length":{"type":"integer"}}}}}}}}}}]},"Account":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"email":{"type":"string","format":"email"},"plan":{"type":"string","examples":["professional"]},"words":{"type":"object","properties":{"monthlyLimit":{"type":"integer"},"monthlyUsed":{"type":"integer"},"monthlyRemaining":{"type":"integer"},"bonusBalance":{"type":"integer","description":"Purchased words, used after the monthly allowance."}}},"limits":{"type":"object","properties":{"maxDocumentWords":{"type":["integer","null"],"description":"Longest text you may submit; null means unlimited."}}},"monthlyResetAt":{"type":["string","null"],"format":"date-time"}}}}},"paths":{"/scans":{"post":{"tags":["Scans"],"summary":"Submit text for checking","description":"Queues a scan and returns immediately. Poll `GET /scans/{id}` for results.","operationId":"createScan","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["text","tools"],"properties":{"text":{"type":"string","description":"The text to check. Must be at least 50 words."},"tools":{"type":"array","minItems":1,"items":{"type":"string","enum":["plagiarism","ai_detect"]},"description":"Each tool is billed at the full word count."},"name":{"type":"string","description":"Optional label to identify the scan later."}}},"examples":{"both":{"summary":"Plagiarism + AI detection","value":{"text":"The mitochondrion is the powerhouse of the cell.","tools":["plagiarism","ai_detect"],"name":"essay-draft-1"}},"plagiarismOnly":{"summary":"Plagiarism only","value":{"text":"The mitochondrion is the powerhouse of the cell.","tools":["plagiarism"]}}}}}},"responses":{"202":{"description":"Scan accepted and queued.","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"status":{"type":"string","examples":["processing"]},"wordCount":{"type":"integer"},"wordsCharged":{"type":"integer"},"tools":{"type":"array","items":{"type":"string"}}}}}}},"400":{"description":"Invalid body, text shorter than 50 words (text_too_short), or longer than your plan allows (doc_too_long).","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Stable machine-readable error code.","examples":["insufficient_words"]},"message":{"type":"string"}}}}}}}},"401":{"description":"Missing, malformed, unknown or revoked API key.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Stable machine-readable error code.","examples":["insufficient_words"]},"message":{"type":"string"}}}}}}}},"402":{"description":"Not enough words remaining.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Stable machine-readable error code.","examples":["insufficient_words"]},"message":{"type":"string"}}}}}}}},"403":{"description":"Free plan — API access requires a paid plan.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Stable machine-readable error code.","examples":["insufficient_words"]},"message":{"type":"string"}}}}}}}},"429":{"description":"Rate limit exceeded.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Stable machine-readable error code.","examples":["insufficient_words"]},"message":{"type":"string"}}}}}}}},"503":{"description":"Scan workers unavailable; words were refunded.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Stable machine-readable error code.","examples":["insufficient_words"]},"message":{"type":"string"}}}}}}}}}},"get":{"tags":["Scans"],"summary":"List scans","operationId":"listScans","parameters":[{"name":"page","in":"query","schema":{"type":"integer","minimum":1,"default":1}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":20}}],"responses":{"200":{"description":"A page of scans, newest first.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/ScanSummary"}},"pagination":{"type":"object","properties":{"page":{"type":"integer"},"limit":{"type":"integer"},"total":{"type":"integer"},"totalPages":{"type":"integer"}}}}}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Stable machine-readable error code.","examples":["insufficient_words"]},"message":{"type":"string"}}}}}}}},"403":{"description":"Free plan — API access requires a paid plan.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Stable machine-readable error code.","examples":["insufficient_words"]},"message":{"type":"string"}}}}}}}},"429":{"description":"Rate limit exceeded.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Stable machine-readable error code.","examples":["insufficient_words"]},"message":{"type":"string"}}}}}}}}}}},"/scans/{id}":{"get":{"tags":["Scans"],"summary":"Get a scan and its results","description":"Poll this until `status` is `completed`. Results appear per tool as each finishes.","operationId":"getScan","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"include_text","in":"query","description":"Return the originally submitted text alongside results.","schema":{"type":"boolean","default":false}}],"responses":{"200":{"description":"The scan.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScanDetail"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Stable machine-readable error code.","examples":["insufficient_words"]},"message":{"type":"string"}}}}}}}},"403":{"description":"Free plan — API access requires a paid plan.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Stable machine-readable error code.","examples":["insufficient_words"]},"message":{"type":"string"}}}}}}}},"404":{"description":"No such scan on this account.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Stable machine-readable error code.","examples":["insufficient_words"]},"message":{"type":"string"}}}}}}}},"429":{"description":"Rate limit exceeded.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Stable machine-readable error code.","examples":["insufficient_words"]},"message":{"type":"string"}}}}}}}}}}},"/account":{"get":{"tags":["Account"],"summary":"Plan and remaining words","operationId":"getAccount","responses":{"200":{"description":"Account details.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Account"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Stable machine-readable error code.","examples":["insufficient_words"]},"message":{"type":"string"}}}}}}}},"403":{"description":"Free plan — API access requires a paid plan.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Stable machine-readable error code.","examples":["insufficient_words"]},"message":{"type":"string"}}}}}}}},"429":{"description":"Rate limit exceeded.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Stable machine-readable error code.","examples":["insufficient_words"]},"message":{"type":"string"}}}}}}}}}}}}}