{"components":{"schemas":{"Error":{"properties":{"code":{"type":"string"},"error":{"type":"string"},"request_id":{"type":"string"},"status":{"type":"integer"}},"required":["error","code","status"],"type":"object"}},"securitySchemes":{"ApiKeyAuth":{"in":"header","name":"X-API-Key","type":"apiKey"}}},"info":{"contact":{"url":"https://feedbackflows.org/contact"},"description":"Programmatic access to Feedback Flows marking, feedback and integrity tools.\n\nAuthenticate with an `X-API-Key` header. Long-running work is submitted to a `/jobs` endpoint that returns `202` with a `job_id`; poll the status endpoint or supply a `callback_url` to receive a signed webhook.\n\nWebhook signatures use the `X-FeedbackFlows-Signature` header in the form `t=<unix-timestamp>,v1=<hex>`, where the HMAC-SHA256 is computed over `<timestamp>.<raw-body>` with your key's webhook secret. Reject any delivery whose timestamp is more than five minutes old.","title":"Feedback Flows API","version":"1.1"},"openapi":"3.1.0","paths":{"/account/status":{"get":{"operationId":"account_status","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"Success"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Malformed request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Missing, invalid, or expired API key"},"402":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Insufficient credits"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Key lacks the required scope"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Resource not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Request body too large"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Rate limit exceeded; see the Retry-After header"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Internal error"}},"summary":"Account status and remaining credits","tags":["Account"]}},"/ai-detector":{"post":{"deprecated":true,"description":"Requires the `integrity` scope.","operationId":"ai_detector_hybrid","requestBody":{"content":{"application/json":{"schema":{"properties":{"academic_mode":{"type":"boolean"},"document_text":{"type":"string"}},"required":["document_text"],"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"Success"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Malformed request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Missing, invalid, or expired API key"},"402":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Insufficient credits"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Key lacks the required scope"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Resource not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Request body too large"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Rate limit exceeded; see the Retry-After header"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Internal error"}},"summary":"Hybrid AI detector (synchronous, detailed response)","tags":["Integrity"]}},"/ai-detector/jobs":{"post":{"description":"Requires one of the following scopes: `integrity` or `marking`.","operationId":"create_ai_detector_job","requestBody":{"content":{"application/json":{"schema":{"properties":{"academic_mode":{"type":"boolean"},"callback_url":{"description":"HTTPS URL to receive the signed completion webhook.","format":"uri","type":"string"},"document_text":{"type":"string"}},"required":["document_text"],"type":"object"}}},"required":true},"responses":{"202":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"Success"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Malformed request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Missing, invalid, or expired API key"},"402":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Insufficient credits"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Key lacks the required scope"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Resource not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Request body too large"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Rate limit exceeded; see the Retry-After header"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Internal error"}},"summary":"Queue AI detection (preferred over the synchronous endpoint)","tags":["Jobs"]}},"/ai-detector/jobs/{job_id}":{"get":{"description":"Requires one of the following scopes: `integrity` or `marking`.","operationId":"get_ai_detector_job","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"Success"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Malformed request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Missing, invalid, or expired API key"},"402":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Insufficient credits"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Key lacks the required scope"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Resource not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Request body too large"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Rate limit exceeded; see the Retry-After header"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Internal error"}},"summary":"AI detection job status and results","tags":["Jobs"]},"parameters":[{"in":"path","name":"job_id","required":true,"schema":{"type":"integer"}}]},"/ai-tutor":{"post":{"description":"Requires the `marking` scope.","operationId":"ai_tutor","requestBody":{"content":{"application/json":{"schema":{"properties":{"marking_rubric":{"type":"string"},"mode":{"enum":["general","rubric"],"type":"string"},"persona":{"type":"string"},"student_draft":{"type":"string"}},"required":["student_draft"],"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"Success"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Malformed request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Missing, invalid, or expired API key"},"402":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Insufficient credits"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Key lacks the required scope"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Resource not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Request body too large"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Rate limit exceeded; see the Retry-After header"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Internal error"}},"summary":"Formative tutor feedback on a draft","tags":["Marking"]}},"/ai-tutor/jobs":{"post":{"description":"Requires the `marking` scope.","operationId":"create_ai_tutor_job","requestBody":{"content":{"application/json":{"schema":{"properties":{"callback_url":{"description":"HTTPS URL to receive the signed completion webhook.","format":"uri","type":"string"},"marking_rubric":{"type":"string"},"mode":{"type":"string"},"persona":{"type":"string"},"student_draft":{"type":"string"}},"required":["student_draft"],"type":"object"}}},"required":true},"responses":{"202":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"Success"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Malformed request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Missing, invalid, or expired API key"},"402":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Insufficient credits"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Key lacks the required scope"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Resource not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Request body too large"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Rate limit exceeded; see the Retry-After header"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Internal error"}},"summary":"Queue AI tutor feedback","tags":["Jobs"]}},"/ai-tutor/jobs/{job_id}":{"get":{"description":"Requires the `marking` scope.","operationId":"get_ai_tutor_job","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"Success"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Malformed request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Missing, invalid, or expired API key"},"402":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Insufficient credits"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Key lacks the required scope"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Resource not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Request body too large"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Rate limit exceeded; see the Retry-After header"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Internal error"}},"summary":"AI tutor job status and result","tags":["Jobs"]},"parameters":[{"in":"path","name":"job_id","required":true,"schema":{"type":"integer"}}]},"/automarking/jobs":{"post":{"description":"Requires the `marking` scope.","operationId":"create_automarking_job","requestBody":{"content":{"application/json":{"schema":{"properties":{"callback_url":{"description":"HTTPS URL to receive the signed completion webhook.","format":"uri","type":"string"},"credit_check_only":{"type":"boolean"},"filename":{"type":"string"},"mark_mode":{"type":"string"},"question_template_id":{"type":"integer"},"questions":{"items":{"type":"object"},"type":"array"},"zip_base64":{"description":"Base64-encoded ZIP archive.","format":"byte","type":"string"}},"required":["zip_base64"],"type":"object"}}},"required":true},"responses":{"202":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"Success"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Malformed request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Missing, invalid, or expired API key"},"402":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Insufficient credits"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Key lacks the required scope"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Resource not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Request body too large"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Rate limit exceeded; see the Retry-After header"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Internal error"}},"summary":"Queue question-by-question automarking","tags":["Jobs"]}},"/automarking/jobs/{job_id}":{"get":{"operationId":"get_automarking_job","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"Success"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Malformed request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Missing, invalid, or expired API key"},"402":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Insufficient credits"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Key lacks the required scope"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Resource not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Request body too large"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Rate limit exceeded; see the Retry-After header"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Internal error"}},"summary":"Automarking job status, progress and results","tags":["Jobs"]},"parameters":[{"in":"path","name":"job_id","required":true,"schema":{"type":"integer"}}]},"/automarking/jobs/{job_id}/export.csv":{"get":{"description":"Requires the `marking` scope.","operationId":"export_automarking_job_csv","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"Success"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Malformed request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Missing, invalid, or expired API key"},"402":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Insufficient credits"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Key lacks the required scope"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Resource not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Request body too large"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Rate limit exceeded; see the Retry-After header"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Internal error"}},"summary":"Export automarking results as CSV","tags":["Exports"]},"parameters":[{"in":"path","name":"job_id","required":true,"schema":{"type":"integer"}}]},"/automarking/results/{result_id}/export.pdf":{"get":{"description":"Requires the `marking` scope.","operationId":"export_automarking_result_pdf","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"Success"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Malformed request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Missing, invalid, or expired API key"},"402":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Insufficient credits"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Key lacks the required scope"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Resource not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Request body too large"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Rate limit exceeded; see the Retry-After header"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Internal error"}},"summary":"Export one automarking result as PDF","tags":["Exports"]},"parameters":[{"in":"path","name":"result_id","required":true,"schema":{"type":"integer"}}]},"/batch-style/jobs":{"post":{"description":"Requires the `integrity` scope.","operationId":"create_batch_style_job","requestBody":{"content":{"application/json":{"schema":{"properties":{"callback_url":{"description":"HTTPS URL to receive the signed completion webhook.","format":"uri","type":"string"},"credit_check_only":{"type":"boolean"},"filename":{"type":"string"},"zip_base64":{"description":"Base64-encoded ZIP archive.","format":"byte","type":"string"}},"required":["zip_base64"],"type":"object"}}},"required":true},"responses":{"202":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"Success"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Malformed request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Missing, invalid, or expired API key"},"402":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Insufficient credits"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Key lacks the required scope"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Resource not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Request body too large"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Rate limit exceeded; see the Retry-After header"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Internal error"}},"summary":"Queue a batch style comparison","tags":["Jobs"]}},"/batch-style/jobs/{job_id}":{"get":{"operationId":"get_batch_style_job","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"Success"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Malformed request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Missing, invalid, or expired API key"},"402":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Insufficient credits"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Key lacks the required scope"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Resource not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Request body too large"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Rate limit exceeded; see the Retry-After header"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Internal error"}},"summary":"Batch style job status and comparisons","tags":["Jobs"]},"parameters":[{"in":"path","name":"job_id","required":true,"schema":{"type":"integer"}}]},"/classes":{"get":{"operationId":"list_classes","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"Success"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Malformed request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Missing, invalid, or expired API key"},"402":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Insufficient credits"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Key lacks the required scope"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Resource not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Request body too large"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Rate limit exceeded; see the Retry-After header"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Internal error"}},"summary":"List classes","tags":["Data"]},"post":{"description":"Requires the `marking` scope.","operationId":"create_class","requestBody":{"content":{"application/json":{"schema":{"properties":{"name":{"type":"string"},"subject":{"type":"string"}},"required":["name"],"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"Success"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Malformed request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Missing, invalid, or expired API key"},"402":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Insufficient credits"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Key lacks the required scope"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Resource not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Request body too large"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Rate limit exceeded; see the Retry-After header"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Internal error"}},"summary":"Create a class","tags":["Data"]}},"/classes/{class_id}":{"parameters":[{"in":"path","name":"class_id","required":true,"schema":{"type":"integer"}}],"patch":{"description":"Requires the `marking` scope.","operationId":"update_class","requestBody":{"content":{"application/json":{"schema":{"properties":{"concluded":{"type":"boolean"},"name":{"type":"string"},"subject":{"type":"string"}},"type":"object"}}},"required":false},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"Success"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Malformed request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Missing, invalid, or expired API key"},"402":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Insufficient credits"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Key lacks the required scope"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Resource not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Request body too large"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Rate limit exceeded; see the Retry-After header"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Internal error"}},"summary":"Update a class","tags":["Data"]}},"/classes/{class_id}/assignments":{"get":{"operationId":"list_class_assignments","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"Success"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Malformed request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Missing, invalid, or expired API key"},"402":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Insufficient credits"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Key lacks the required scope"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Resource not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Request body too large"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Rate limit exceeded; see the Retry-After header"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Internal error"}},"summary":"List assignments for a class","tags":["Data"]},"parameters":[{"in":"path","name":"class_id","required":true,"schema":{"type":"integer"}}]},"/classes/{class_id}/assignments/{assignment_id}/analyze":{"parameters":[{"in":"path","name":"assignment_id","required":true,"schema":{"type":"integer"}},{"in":"path","name":"class_id","required":true,"schema":{"type":"integer"}}],"post":{"description":"Requires the `analytics` scope.","operationId":"class_assignment_analyze","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"Success"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Malformed request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Missing, invalid, or expired API key"},"402":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Insufficient credits"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Key lacks the required scope"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Resource not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Request body too large"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Rate limit exceeded; see the Retry-After header"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Internal error"}},"summary":"Cohort analysis for one assignment","tags":["Analytics"]}},"/classes/{class_id}/export.csv":{"get":{"description":"Requires the `analytics` scope.","operationId":"export_class_csv","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"Success"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Malformed request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Missing, invalid, or expired API key"},"402":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Insufficient credits"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Key lacks the required scope"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Resource not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Request body too large"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Rate limit exceeded; see the Retry-After header"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Internal error"}},"summary":"Export a class roster as CSV","tags":["Exports"]},"parameters":[{"in":"path","name":"class_id","required":true,"schema":{"type":"integer"}}]},"/classes/{class_id}/results":{"get":{"description":"Requires the `analytics` scope.","operationId":"class_results_export","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"Success"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Malformed request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Missing, invalid, or expired API key"},"402":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Insufficient credits"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Key lacks the required scope"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Resource not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Request body too large"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Rate limit exceeded; see the Retry-After header"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Internal error"}},"summary":"Bulk export marking outcomes for a class","tags":["Data"]},"parameters":[{"in":"path","name":"class_id","required":true,"schema":{"type":"integer"}}]},"/classes/{class_id}/students":{"parameters":[{"in":"path","name":"class_id","required":true,"schema":{"type":"integer"}}],"patch":{"description":"Requires the `marking` scope.","operationId":"update_class_enrolment","requestBody":{"content":{"application/json":{"schema":{"properties":{"add_student_ids":{"items":{"type":"integer"},"type":"array"},"remove_student_ids":{"items":{"type":"integer"},"type":"array"}},"type":"object"}}},"required":false},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"Success"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Malformed request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Missing, invalid, or expired API key"},"402":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Insufficient credits"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Key lacks the required scope"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Resource not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Request body too large"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Rate limit exceeded; see the Retry-After header"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Internal error"}},"summary":"Add or remove students from a class","tags":["Data"]}},"/exam-marker/jobs":{"post":{"description":"Requires the `marking` scope.","operationId":"create_exam_marker_job","requestBody":{"content":{"application/json":{"schema":{"properties":{"callback_url":{"description":"HTTPS URL to receive the signed completion webhook.","format":"uri","type":"string"},"filename":{"type":"string"},"student_id":{"type":"integer"},"zip_base64":{"description":"Base64-encoded ZIP archive.","format":"byte","type":"string"}},"required":["student_id","zip_base64"],"type":"object"}}},"required":true},"responses":{"202":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"Success"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Malformed request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Missing, invalid, or expired API key"},"402":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Insufficient credits"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Key lacks the required scope"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Resource not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Request body too large"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Rate limit exceeded; see the Retry-After header"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Internal error"}},"summary":"Queue exam script marking for one student","tags":["Jobs"]}},"/full-reference-check":{"post":{"description":"Requires the `integrity` scope.","operationId":"full_reference_check","requestBody":{"content":{"application/json":{"schema":{"properties":{"document_text":{"type":"string"},"enable_semantic_check":{"type":"boolean"},"style":{"enum":["APA","Harvard","MLA","Chicago"],"type":"string"}},"required":["document_text"],"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"Success"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Malformed request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Missing, invalid, or expired API key"},"402":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Insufficient credits"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Key lacks the required scope"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Resource not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Request body too large"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Rate limit exceeded; see the Retry-After header"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Internal error"}},"summary":"Bibliography and citation checker","tags":["Integrity"]}},"/interactive-feedback":{"post":{"description":"Requires the `marking` scope.","operationId":"interactive_feedback","requestBody":{"content":{"application/json":{"schema":{"properties":{"marking_criteria":{"items":{"type":"string"},"type":"array"},"student_text":{"type":"string"}},"required":["student_text","marking_criteria"],"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"Success"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Malformed request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Missing, invalid, or expired API key"},"402":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Insufficient credits"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Key lacks the required scope"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Resource not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Request body too large"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Rate limit exceeded; see the Retry-After header"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Internal error"}},"summary":"Inline feedback against a list of criteria","tags":["Marking"]}},"/interactive-feedback/jobs":{"post":{"description":"Requires the `marking` scope.","operationId":"create_interactive_feedback_job","requestBody":{"content":{"application/json":{"schema":{"properties":{"callback_url":{"description":"HTTPS URL to receive the signed completion webhook.","format":"uri","type":"string"},"marking_criteria":{"items":{"type":"string"},"type":"array"},"student_text":{"type":"string"}},"required":["student_text","marking_criteria"],"type":"object"}}},"required":true},"responses":{"202":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"Success"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Malformed request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Missing, invalid, or expired API key"},"402":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Insufficient credits"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Key lacks the required scope"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Resource not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Request body too large"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Rate limit exceeded; see the Retry-After header"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Internal error"}},"summary":"Queue interactive feedback","tags":["Jobs"]}},"/interactive-feedback/jobs/{job_id}":{"get":{"description":"Requires the `marking` scope.","operationId":"get_interactive_feedback_job","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"Success"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Malformed request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Missing, invalid, or expired API key"},"402":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Insufficient credits"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Key lacks the required scope"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Resource not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Request body too large"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Rate limit exceeded; see the Retry-After header"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Internal error"}},"summary":"Interactive-feedback job status and result","tags":["Jobs"]},"parameters":[{"in":"path","name":"job_id","required":true,"schema":{"type":"integer"}}]},"/jobs/estimate-cost":{"post":{"operationId":"estimate_job_cost_endpoint","requestBody":{"content":{"application/json":{"schema":{"properties":{"file_count":{"type":"integer"},"job_type":{"type":"string"},"student_count":{"type":"integer"}},"required":["job_type"],"type":"object"}}},"required":true},"responses":{"202":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"Success"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Malformed request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Missing, invalid, or expired API key"},"402":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Insufficient credits"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Key lacks the required scope"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Resource not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Request body too large"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Rate limit exceeded; see the Retry-After header"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Internal error"}},"summary":"Estimate the credit cost of an async job","tags":["Jobs"]}},"/learner-packs/jobs":{"post":{"description":"Requires the `marking` scope.","operationId":"create_learner_pack_job","requestBody":{"content":{"application/json":{"schema":{"properties":{"callback_url":{"description":"HTTPS URL to receive the signed completion webhook.","format":"uri","type":"string"},"generation_options":{"type":"object"},"selected_result_refs":{"items":{"type":"object"},"type":"array"},"student_id":{"type":"integer"},"template_id":{"type":"integer"}},"required":["student_id"],"type":"object"}}},"required":true},"responses":{"202":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"Success"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Malformed request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Missing, invalid, or expired API key"},"402":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Insufficient credits"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Key lacks the required scope"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Resource not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Request body too large"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Rate limit exceeded; see the Retry-After header"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Internal error"}},"summary":"Queue a learner pack build","tags":["Jobs"]}},"/learner-packs/jobs/{job_id}":{"get":{"description":"Requires the `marking` scope.","operationId":"get_learner_pack_job","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"Success"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Malformed request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Missing, invalid, or expired API key"},"402":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Insufficient credits"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Key lacks the required scope"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Resource not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Request body too large"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Rate limit exceeded; see the Retry-After header"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Internal error"}},"summary":"Learner pack job status and rendered document","tags":["Jobs"]},"parameters":[{"in":"path","name":"job_id","required":true,"schema":{"type":"integer"}}]},"/learner-packs/jobs/{job_id}/export.pdf":{"get":{"description":"Requires the `marking` scope.","operationId":"export_learner_pack_job_pdf","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"Success"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Malformed request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Missing, invalid, or expired API key"},"402":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Insufficient credits"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Key lacks the required scope"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Resource not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Request body too large"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Rate limit exceeded; see the Retry-After header"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Internal error"}},"summary":"Export a learner pack as PDF","tags":["Exports"]},"parameters":[{"in":"path","name":"job_id","required":true,"schema":{"type":"integer"}}]},"/media-marker/jobs":{"post":{"description":"Requires the `media` scope.","operationId":"create_media_marker_job","requestBody":{"content":{"application/json":{"schema":{"properties":{"callback_url":{"description":"HTTPS URL to receive the signed completion webhook.","format":"uri","type":"string"},"criteria":{"type":"string"},"education_level":{"type":"string"},"filename":{"type":"string"},"media_base64":{"format":"byte","type":"string"},"persona":{"type":"string"},"presentation_type":{"type":"string"}},"required":["criteria","media_base64"],"type":"object"}}},"required":true},"responses":{"202":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"Success"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Malformed request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Missing, invalid, or expired API key"},"402":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Insufficient credits"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Key lacks the required scope"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Resource not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Request body too large"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Rate limit exceeded; see the Retry-After header"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Internal error"}},"summary":"Queue video or audio marking","tags":["Jobs"]}},"/media-marker/jobs/{job_id}":{"get":{"description":"Requires the `media` scope.","operationId":"get_media_marker_job","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"Success"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Malformed request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Missing, invalid, or expired API key"},"402":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Insufficient credits"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Key lacks the required scope"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Resource not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Request body too large"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Rate limit exceeded; see the Retry-After header"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Internal error"}},"summary":"Media marking job status and feedback","tags":["Jobs"]},"parameters":[{"in":"path","name":"job_id","required":true,"schema":{"type":"integer"}}]},"/media-marker/jobs/{job_id}/export.pdf":{"get":{"description":"Requires the `media` scope.","operationId":"export_media_marker_job_pdf","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"Success"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Malformed request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Missing, invalid, or expired API key"},"402":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Insufficient credits"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Key lacks the required scope"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Resource not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Request body too large"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Rate limit exceeded; see the Retry-After header"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Internal error"}},"summary":"Export a media-marker report","tags":["Exports"]},"parameters":[{"in":"path","name":"job_id","required":true,"schema":{"type":"integer"}}]},"/openapi.json":{"get":{"operationId":"openapi_spec","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"Success"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Malformed request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Missing, invalid, or expired API key"},"402":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Insufficient credits"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Key lacks the required scope"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Resource not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Request body too large"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Rate limit exceeded; see the Retry-After header"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Internal error"}},"summary":"This document (no API key required)","tags":["Account"]}},"/question-templates":{"get":{"description":"Requires the `marking` scope.","operationId":"list_question_templates","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"Success"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Malformed request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Missing, invalid, or expired API key"},"402":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Insufficient credits"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Key lacks the required scope"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Resource not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Request body too large"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Rate limit exceeded; see the Retry-After header"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Internal error"}},"summary":"List question templates","tags":["Data"]}},"/reference-check":{"post":{"deprecated":true,"description":"Requires the `integrity` scope.","operationId":"reference_check","requestBody":{"content":{"application/json":{"schema":{"properties":{"document_text":{"type":"string"}},"required":["document_text"],"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"Success"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Malformed request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Missing, invalid, or expired API key"},"402":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Insufficient credits"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Key lacks the required scope"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Resource not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Request body too large"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Rate limit exceeded; see the Retry-After header"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Internal error"}},"summary":"Legacy AI detector (simplified response)","tags":["Integrity"]}},"/reference-check/jobs":{"post":{"description":"Requires the `integrity` scope.","operationId":"create_reference_check_job","requestBody":{"content":{"application/json":{"schema":{"properties":{"callback_url":{"description":"HTTPS URL to receive the signed completion webhook.","format":"uri","type":"string"},"document_text":{"type":"string"},"enable_semantic_check":{"type":"boolean"},"match_refs":{"type":"boolean"},"style":{"type":"string"}},"required":["document_text"],"type":"object"}}},"required":true},"responses":{"202":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"Success"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Malformed request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Missing, invalid, or expired API key"},"402":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Insufficient credits"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Key lacks the required scope"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Resource not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Request body too large"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Rate limit exceeded; see the Retry-After header"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Internal error"}},"summary":"Queue the full reference-check web pipeline","tags":["Jobs"]}},"/reference-check/jobs/{job_id}":{"get":{"description":"Requires the `integrity` scope.","operationId":"get_reference_check_job","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"Success"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Malformed request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Missing, invalid, or expired API key"},"402":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Insufficient credits"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Key lacks the required scope"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Resource not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Request body too large"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Rate limit exceeded; see the Retry-After header"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Internal error"}},"summary":"Reference-check job status and report","tags":["Jobs"]},"parameters":[{"in":"path","name":"job_id","required":true,"schema":{"type":"integer"}}]},"/reference-check/jobs/{job_id}/export.pdf":{"get":{"description":"Requires the `integrity` scope.","operationId":"export_reference_check_job_pdf","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"Success"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Malformed request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Missing, invalid, or expired API key"},"402":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Insufficient credits"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Key lacks the required scope"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Resource not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Request body too large"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Rate limit exceeded; see the Retry-After header"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Internal error"}},"summary":"Export a reference-check report as PDF","tags":["Exports"]},"parameters":[{"in":"path","name":"job_id","required":true,"schema":{"type":"integer"}}]},"/rubric-marking/jobs":{"post":{"description":"Requires the `marking` scope.","operationId":"create_rubric_marking_job","requestBody":{"content":{"application/json":{"schema":{"properties":{"callback_url":{"description":"HTTPS URL to receive the signed completion webhook.","format":"uri","type":"string"},"credit_check_only":{"type":"boolean"},"filename":{"type":"string"},"grading_system":{"type":"string"},"marking_style":{"type":"string"},"rubric_id":{"type":"integer"},"zip_base64":{"description":"Base64-encoded ZIP archive.","format":"byte","type":"string"}},"required":["rubric_id","zip_base64"],"type":"object"}}},"required":true},"responses":{"202":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"Success"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Malformed request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Missing, invalid, or expired API key"},"402":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Insufficient credits"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Key lacks the required scope"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Resource not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Request body too large"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Rate limit exceeded; see the Retry-After header"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Internal error"}},"summary":"Queue rubric marking for a class ZIP","tags":["Jobs"]}},"/rubric-marking/jobs/{job_id}":{"get":{"operationId":"get_rubric_marking_job","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"Success"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Malformed request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Missing, invalid, or expired API key"},"402":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Insufficient credits"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Key lacks the required scope"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Resource not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Request body too large"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Rate limit exceeded; see the Retry-After header"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Internal error"}},"summary":"Rubric marking job status and results","tags":["Jobs"]},"parameters":[{"in":"path","name":"job_id","required":true,"schema":{"type":"integer"}}]},"/rubric-marking/jobs/{job_id}/cancel":{"parameters":[{"in":"path","name":"job_id","required":true,"schema":{"type":"integer"}}],"post":{"description":"Requires the `marking` scope.","operationId":"cancel_rubric_marking_job","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"Success"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Malformed request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Missing, invalid, or expired API key"},"402":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Insufficient credits"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Key lacks the required scope"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Resource not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Request body too large"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Rate limit exceeded; see the Retry-After header"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Internal error"}},"summary":"Cancel a rubric marking job and refund unused credits","tags":["Jobs"]}},"/rubric-marking/jobs/{job_id}/export.csv":{"get":{"description":"Requires the `marking` scope.","operationId":"export_rubric_marking_job_csv","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"Success"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Malformed request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Missing, invalid, or expired API key"},"402":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Insufficient credits"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Key lacks the required scope"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Resource not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Request body too large"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Rate limit exceeded; see the Retry-After header"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Internal error"}},"summary":"Export rubric batch results as CSV","tags":["Exports"]},"parameters":[{"in":"path","name":"job_id","required":true,"schema":{"type":"integer"}}]},"/rubric-marking/results/{result_id}/export.pdf":{"get":{"description":"Requires the `marking` scope.","operationId":"export_rubric_marking_result_pdf","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"Success"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Malformed request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Missing, invalid, or expired API key"},"402":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Insufficient credits"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Key lacks the required scope"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Resource not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Request body too large"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Rate limit exceeded; see the Retry-After header"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Internal error"}},"summary":"Export one rubric result as PDF","tags":["Exports"]},"parameters":[{"in":"path","name":"result_id","required":true,"schema":{"type":"integer"}}]},"/rubrics":{"get":{"operationId":"list_rubrics","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"Success"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Malformed request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Missing, invalid, or expired API key"},"402":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Insufficient credits"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Key lacks the required scope"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Resource not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Request body too large"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Rate limit exceeded; see the Retry-After header"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Internal error"}},"summary":"List rubrics","tags":["Data"]},"post":{"description":"Requires the `marking` scope.","operationId":"create_rubric","requestBody":{"content":{"application/json":{"schema":{"properties":{"criteria":{"type":"string"},"marking_guidance":{"type":"string"},"max_attempts":{"type":"integer"},"name":{"type":"string"},"pass_rate":{"type":"integer"}},"required":["name","criteria"],"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"Success"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Malformed request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Missing, invalid, or expired API key"},"402":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Insufficient credits"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Key lacks the required scope"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Resource not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Request body too large"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Rate limit exceeded; see the Retry-After header"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Internal error"}},"summary":"Create a rubric","tags":["Data"]}},"/rubrics/{rubric_id}":{"get":{"operationId":"get_rubric_detail","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"Success"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Malformed request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Missing, invalid, or expired API key"},"402":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Insufficient credits"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Key lacks the required scope"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Resource not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Request body too large"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Rate limit exceeded; see the Retry-After header"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Internal error"}},"summary":"Get one rubric with its criteria","tags":["Data"]},"parameters":[{"in":"path","name":"rubric_id","required":true,"schema":{"type":"integer"}}]},"/smart-essay-marker":{"post":{"deprecated":true,"description":"Requires the `marking` scope.","operationId":"smart_essay_marker","requestBody":{"content":{"application/json":{"schema":{"properties":{"essay_text":{"type":"string"},"marking_criteria":{"items":{"type":"string"},"type":"array"}},"required":["essay_text","marking_criteria"],"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"Success"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Malformed request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Missing, invalid, or expired API key"},"402":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Insufficient credits"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Key lacks the required scope"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Resource not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Request body too large"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Rate limit exceeded; see the Retry-After header"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Internal error"}},"summary":"Mark one essay against criteria (synchronous)","tags":["Marking"]}},"/smart-essay/jobs":{"post":{"description":"Requires the `marking` scope.","operationId":"create_smart_essay_job","requestBody":{"content":{"application/json":{"schema":{"properties":{"callback_url":{"description":"HTTPS URL to receive the signed completion webhook.","format":"uri","type":"string"},"education_level":{"type":"string"},"essay_text":{"type":"string"},"marking_criteria":{"type":"string"},"persona":{"type":"string"}},"required":["essay_text","marking_criteria"],"type":"object"}}},"required":true},"responses":{"202":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"Success"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Malformed request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Missing, invalid, or expired API key"},"402":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Insufficient credits"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Key lacks the required scope"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Resource not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Request body too large"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Rate limit exceeded; see the Retry-After header"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Internal error"}},"summary":"Queue essay marking (preferred over the synchronous endpoint)","tags":["Jobs"]}},"/smart-essay/jobs/{job_id}":{"get":{"description":"Requires the `marking` scope.","operationId":"get_smart_essay_job","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"Success"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Malformed request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Missing, invalid, or expired API key"},"402":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Insufficient credits"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Key lacks the required scope"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Resource not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Request body too large"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Rate limit exceeded; see the Retry-After header"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Internal error"}},"summary":"Essay marking job status and feedback","tags":["Jobs"]},"parameters":[{"in":"path","name":"job_id","required":true,"schema":{"type":"integer"}}]},"/smart-essay/jobs/{job_id}/export.pdf":{"get":{"description":"Requires the `marking` scope.","operationId":"export_smart_essay_job_pdf","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"Success"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Malformed request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Missing, invalid, or expired API key"},"402":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Insufficient credits"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Key lacks the required scope"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Resource not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Request body too large"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Rate limit exceeded; see the Retry-After header"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Internal error"}},"summary":"Export a smart-essay report as PDF","tags":["Exports"]},"parameters":[{"in":"path","name":"job_id","required":true,"schema":{"type":"integer"}}]},"/stats/users":{"get":{"operationId":"stats_users","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"Success"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Malformed request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Missing, invalid, or expired API key"},"402":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Insufficient credits"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Key lacks the required scope"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Resource not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Request body too large"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Rate limit exceeded; see the Retry-After header"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Internal error"}},"summary":"Total user count (requires an admin-owned key)","tags":["Account"]}},"/students":{"get":{"operationId":"list_students","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"Success"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Malformed request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Missing, invalid, or expired API key"},"402":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Insufficient credits"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Key lacks the required scope"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Resource not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Request body too large"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Rate limit exceeded; see the Retry-After header"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Internal error"}},"summary":"List students","tags":["Data"]},"post":{"description":"Requires the `marking` scope.","operationId":"create_student","requestBody":{"content":{"application/json":{"schema":{"properties":{"class_ids":{"items":{"type":"integer"},"type":"array"},"name":{"type":"string"},"uln":{"type":"string"}},"required":["name"],"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"Success"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Malformed request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Missing, invalid, or expired API key"},"402":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Insufficient credits"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Key lacks the required scope"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Resource not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Request body too large"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Rate limit exceeded; see the Retry-After header"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Internal error"}},"summary":"Create a student","tags":["Data"]}},"/students/{student_id}":{"parameters":[{"in":"path","name":"student_id","required":true,"schema":{"type":"integer"}}],"patch":{"description":"Requires the `marking` scope.","operationId":"update_student","requestBody":{"content":{"application/json":{"schema":{"properties":{"class_ids":{"items":{"type":"integer"},"type":"array"},"name":{"type":"string"},"uln":{"type":"string"}},"type":"object"}}},"required":false},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"Success"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Malformed request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Missing, invalid, or expired API key"},"402":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Insufficient credits"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Key lacks the required scope"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Resource not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Request body too large"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Rate limit exceeded; see the Retry-After header"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Internal error"}},"summary":"Update a student","tags":["Data"]}},"/students/{student_id}/ai-history":{"get":{"operationId":"student_ai_history","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"Success"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Malformed request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Missing, invalid, or expired API key"},"402":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Insufficient credits"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Key lacks the required scope"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Resource not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Request body too large"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Rate limit exceeded; see the Retry-After header"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Internal error"}},"summary":"AI detection history for one student","tags":["Data"]},"parameters":[{"in":"path","name":"student_id","required":true,"schema":{"type":"integer"}}]},"/students/{student_id}/progress-report":{"parameters":[{"in":"path","name":"student_id","required":true,"schema":{"type":"integer"}}],"post":{"description":"Requires the `analytics` scope.","operationId":"student_progress_report","requestBody":{"content":{"application/json":{"schema":{"properties":{"end_date":{"format":"date","type":"string"},"start_date":{"format":"date","type":"string"}},"type":"object"}}},"required":false},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"Success"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Malformed request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Missing, invalid, or expired API key"},"402":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Insufficient credits"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Key lacks the required scope"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Resource not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Request body too large"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Rate limit exceeded; see the Retry-After header"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Internal error"}},"summary":"Generate a progress report for one student","tags":["Analytics"]}},"/students/{student_id}/worksheet":{"parameters":[{"in":"path","name":"student_id","required":true,"schema":{"type":"integer"}}],"post":{"description":"Requires the `marking` scope.","operationId":"generate_student_worksheet","requestBody":{"content":{"application/json":{"schema":{"properties":{"format":{"type":"string"},"level":{"type":"string"},"num_questions":{"type":"integer"},"weaknesses_list":{"items":{"type":"string"},"type":"array"}},"type":"object"}}},"required":false},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"Success"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Malformed request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Missing, invalid, or expired API key"},"402":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Insufficient credits"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Key lacks the required scope"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Resource not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Request body too large"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Rate limit exceeded; see the Retry-After header"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Internal error"}},"summary":"Generate a targeted practice worksheet","tags":["Marking"]}},"/style-comparison":{"post":{"description":"Requires the `integrity` scope.","operationId":"style_comparison_sync","requestBody":{"content":{"application/json":{"schema":{"properties":{"student_id":{"type":"integer"},"submission_text":{"type":"string"}},"required":["student_id","submission_text"],"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"Success"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Malformed request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Missing, invalid, or expired API key"},"402":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Insufficient credits"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Key lacks the required scope"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Resource not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Request body too large"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Rate limit exceeded; see the Retry-After header"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Internal error"}},"summary":"Compare one submission against a student's writing samples","tags":["Integrity"]}},"/test":{"get":{"operationId":"test_endpoint","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"Success"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Malformed request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Missing, invalid, or expired API key"},"402":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Insufficient credits"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Key lacks the required scope"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Resource not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Request body too large"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Rate limit exceeded; see the Retry-After header"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Internal error"}},"summary":"Validate API key","tags":["Account"]}},"/worksheets/jobs":{"post":{"description":"Requires the `marking` scope.","operationId":"create_worksheet_job","requestBody":{"content":{"application/json":{"schema":{"properties":{"callback_url":{"description":"HTTPS URL to receive the signed completion webhook.","format":"uri","type":"string"},"format":{"type":"string"},"level":{"type":"string"},"num_questions":{"type":"integer"},"student_id":{"type":"integer"},"weaknesses_list":{"items":{"type":"string"},"type":"array"}},"required":["student_id"],"type":"object"}}},"required":true},"responses":{"202":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"Success"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Malformed request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Missing, invalid, or expired API key"},"402":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Insufficient credits"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Key lacks the required scope"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Resource not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Request body too large"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Rate limit exceeded; see the Retry-After header"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Internal error"}},"summary":"Queue worksheet generation","tags":["Jobs"]}},"/worksheets/jobs/{job_id}":{"get":{"description":"Requires the `marking` scope.","operationId":"get_worksheet_job","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"Success"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Malformed request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Missing, invalid, or expired API key"},"402":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Insufficient credits"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Key lacks the required scope"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Resource not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Request body too large"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Rate limit exceeded; see the Retry-After header"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Internal error"}},"summary":"Worksheet job status and result","tags":["Jobs"]},"parameters":[{"in":"path","name":"job_id","required":true,"schema":{"type":"integer"}}]},"/worksheets/jobs/{job_id}/export.pdf":{"get":{"description":"Requires the `marking` scope.","operationId":"export_worksheet_job_pdf","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"Success"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Malformed request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Missing, invalid, or expired API key"},"402":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Insufficient credits"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Key lacks the required scope"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Resource not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Request body too large"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Rate limit exceeded; see the Retry-After header"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Internal error"}},"summary":"Export a completed worksheet as PDF","tags":["Exports"]},"parameters":[{"in":"path","name":"job_id","required":true,"schema":{"type":"integer"}}]}},"security":[{"ApiKeyAuth":[]}],"servers":[{"url":"https://feedbackflows.org/api/v1"}],"x-scopes":["admin","analytics","integrity","marking","media"]}
