API Documentation

PaperScorer Core API

A machine-to-machine REST API for generating answer sheets, scanning paper assessments, and syncing scored results into your platform. JWT bearer auth, snake_case envelopes, and a documented async polling model.

Overview

The PaperScorer Core API exposes the full assessment lifecycle as a REST surface: mint a token from your API key and secret, generate answer sheets, queue scanned PDFs for OCR + scoring, read captured bubbles, correct flagged sheets, and pull scored attempts ready to push into your LMS.

Base URL

https://api-v2.paperscorer.com/PaperScorerWebServices/

Discovery Lookups

Two read-only endpoints scope your tenant. Call them when you need to populate dropdowns or reconcile state — they don't change the engine's record, only mirror it.

List AssessmentsGET /rest/ps/assessments
List Form StudentsGET /rest/ps/form-students

Integration Workflow

Follow these steps to integrate PaperScorer into your platform

1

Authentication

Every Core API call carries a Bearer access token. Exchange your PaperScorer-issued API key and secret for a short-lived JWT via the OAuth2 client_credentials grant, then reuse it across calls until it expires.

  • POST /rest/auth/token with Authorization: Basic base64(key_id:secret). Response is a Bearer token valid for 1 hour.
  • There is no refresh endpoint — re-mint via the same call when the token expires. Cache the token for its full TTL; do not mint per request.
  • Optional GET /rest/auth/tokeninfo introspects a token without making a real API call — useful for debugging.
  • Access tokens are RS256-signed JWTs carrying your institution_id, so every authenticated request is scoped to your tenant automatically.

Relevant Endpoints

Generate Access TokenPOST /rest/auth/token
Inspect TokenGET /rest/auth/tokeninfo
Teacher's BrowserYour PlatformPaperScorerTeacher chooses to print an answer sheetPOST /rest/auth/tokenSend API key + secret as HTTP Basic auth to mint a Bearer access token.{ access_token, expires_in: 3600 }Cache the access token for its full 1-hour TTL.There is no refresh endpoint — re-mint with the same credentials on expiry.Call subsequent endpoints with Authorization: Bearer <access_token>The access token is an RS256-signed JWT carrying your institution_id —every authenticated request is automatically scoped to your tenant.Teacher's BrowserYour PlatformPaperScorer
2

Sheet Generation

Generate the printable bubble sheet (PDF) and the matching question paper (HTML) from a pre-configured assessment. Both generators share the same envelope shape and return the form_id you reuse for every downstream operation.

  • Generate Answer Sheet returns a PDF URL that students can fill in and a form_id you should persist alongside the assessment.
  • Generate Question Paper returns the readable question paper as HTML for printing or web display.

Relevant Endpoints

Generate Answer SheetPOST /rest/ps/generate-answer-sheet
Generate Question PaperPOST /rest/ps/generate-question-paper
Teacher's BrowserYour PlatformPaperScorerTeacher chooses to print an answer sheetPOST /rest/ps/generate-answer-sheetSend assessment data and student roster as JSON.Authorization: Bearer <access_token>Answer Sheet URL + form_idSave form_id with assessment ID so student scores can be retrieved later.Answer Sheet URLDownload URLURLNo authentication, obfuscated URL.Tests and printed answer sheets are given to students. Students fill in answer sheetsand return them to the teacher, or scan them in directly using the PaperScorer mobile app.Teacher's BrowserYour PlatformPaperScorer
3

Submitting Sheets

Four submission paths cover synchronous single-sheet scans and asynchronous batches. Pick the path that matches the size of the upload and whether your caller can block on the response.

  • Scan Sheet and Scan Uploaded Sheet are synchronous — the engine returns the captured bubbles and per-page result in a single round trip.
  • Queue Scanned Sheet is asynchronous — the engine returns a job_id immediately and processes pages in the background. Use it for multi-page PDFs.
  • Bulk Upload accepts a batch of files in one request. Returns a job_id for the batch and per-file token_ids for tracking.
  • Auto-sync is opt-in (is_auto_sync_enabled=true on queue or bulk uploads) — scored results push to your callback URL when scanning completes.

Relevant Endpoints

Scan SheetPOST /rest/ps/scan-sheet
Scan Uploaded SheetPOST /rest/ps/scan-uploaded-sheet
Queue Scanned SheetPOST /rest/ps/queue-scanned-sheet
Bulk UploadPOST /rest/ps/bulk-upload
Teacher's BrowserYour PlatformPaperScorerTeacher chooses to upload PDFPDF files are scanned in standard scanners or document cameras and saved to PDF.POST /rest/ps/queue-scanned-sheetPaperScorer starts processing the answer sheets in the PDF using multipleservers and threads. Depending on the number of answer sheets in the PDF,this could take some time.job_idPaperScorer returns a job_id to use for retrieving processed forms later.GET /rest/ps/job-status?job_id=...Send the job_id returned by queue-scanned-sheet to retrieve theform IDs that have been processed.Processed Form IDsForm IDs and other information regarding the scanned answer sheetsare returned. You can use this info to then retrieve grades.Teacher's BrowserYour PlatformPaperScorer
4

Polling Status

Two polling endpoints, two scopes. Both are safe to call as frequently as you need — the engine returns 200 with the current lifecycle state regardless of completion.

  • GET /rest/ps/job-status returns the aggregate view of a queued or bulk upload — total pages, processed pages, completed form ids. Use it to answer "is the batch done?"
  • GET /rest/ps/task-status returns the per-page view — state of an individual scanned sheet. Use it to answer "is this specific page done?"
  • Most callers poll job-status for batches and only reach for task-status when a specific page stalls or needs to be re-driven.

Relevant Endpoints

Job StatusGET /rest/ps/job-status
Task StatusGET /rest/ps/task-status
5

Reading Scan Output

Inspect what the OCR engine actually captured before pulling scores. These read-only endpoints surface bubbles, error flags, upload-time failures, and free-response essay images.

  • Scanned Sheets lists every sheet captured under a form_id with status, student_id, and page metadata.
  • Scanned Sheet Data returns the full per-task capture — bubble selections, error flags, and a link to the sheet image.
  • Upload Errors surfaces files that never reached scanning (decode failures, unsupported formats, oversized inputs).
  • Essay Image Details returns the cropped images for free-response questions so a grader can review them in your UI.

Relevant Endpoints

List Scanned SheetsGET /rest/ps/scanned-sheets
Scanned Sheet DataGET /rest/ps/scanned-sheet-data
Upload ErrorsGET /rest/ps/upload-errors
Essay Image DetailsGET /rest/ps/essay-image-details
6

Managing Scans

When the engine flags a sheet — an unreadable student id, a question with multiple bubbles marked — fix it through a correction call. Or skip the sheet entirely if it shouldn't count toward the student's score.

  • Submit Scanned Sheet Correction supports three modes: questions-only (engine is skipped), student-only (engine re-runs to read the bubbles), or both (engine is skipped and the task is reassigned in one call).
  • The engine resolves form_id, page_number, image_url, and student association from the task — clients only send what changed.
  • Skip Scanned Sheet removes a sheet from the student's score without re-running scoring. Use for misfeeds, blank pages, or duplicates.

Relevant Endpoints

Submit Scanned Sheet CorrectionPOST /rest/ps/submit-scanned-sheet-correction
Skip Scanned SheetPOST /rest/ps/skip-scanned-sheet
Teacher's BrowserYour PlatformPaperScorerTeacher accesses scan correction pageGET /rest/ps/scanned-sheet-data?task_id=...Fetch the captured bubbles, sheet image, and engine error flagsfor the task that needs correction.Sheet image, bubbles, error flagsRender correction UITeacher fixes the student id and/or rebubbles flagged answersdirectly in your platform — no iFrame, no shared encryption key.Submit correctionsPOST /rest/ps/submit-scanned-sheet-correctionBody carries task_id plus optional student_id and/or questions.The engine re-scores the sheet and returns the new score.Re-scored resultOr POST /rest/ps/skip-scanned-sheet when the sheet shouldn't count at all.Teacher's BrowserYour PlatformPaperScorer
7

Scoring & LMS Sync

Pull per-form aggregates, per-student details, or attempts ready to push to your LMS. Per-form and per-student endpoints return the same numeric score shape — choose by the scope you need.

  • Form Scores returns per-student scores for a form. Form Scores Summary returns the aggregate roll-up (counts, averages, distribution).
  • Student Scores returns one student's scores across every form they've taken. Student Form Answers returns their per-question detail for a specific form.
  • Sync Student Scores returns attempts ready to push to your LMS; acknowledge them via Acknowledge Sync Student Scores so they drop out of future pulls.

Relevant Endpoints

Form ScoresGET /rest/ps/form-scores
Form Scores SummaryGET /rest/ps/form-scores-summary
Student ScoresGET /rest/ps/student-scores
Student Form AnswersGET /rest/ps/student-form-answers
Sync Student ScoresGET /rest/ps/sync-student-scores
Acknowledge Sync Student ScoresPOST /rest/ps/acknowledge-sync-student-scores
Teacher's BrowserYour PlatformPaperScorerTeacher requests grade information for a scanned answer sheetGET /rest/ps/form-scores?form_id=...form_id was returned earlier by job-status when the scan job completed.Per-student scoresPaperScorer returns detailed results for each student answer sheet processed.POST /rest/ps/acknowledge-sync-student-scoresAfter syncing student scores with your platform, callacknowledge-sync-student-scores. This removes synced scoresfrom subsequent sync-student-scores responses.Show student gradesTeacher's BrowserYour PlatformPaperScorer
Security & Authentication

Built for Machine-to-Machine

Every Core API call is authenticated with an RS256-signed JWT over HTTPS. There is no end-user concept at the auth layer — each integrating application gets a key + secret pair scoped to its institution and exchanges them for short-lived access tokens via the OAuth2 client_credentials grant.

OAuth2 client_credentials

Standard RFC 6749 §4.4 flow — any OAuth2 client library that supports Basic auth on the token endpoint works without custom configuration.

Institution-scoped JWTs

RS256-signed access tokens carry your institution_id as a claim, so every request is automatically tenant-isolated.

Environment-discriminated keys

Keys are prefixed with their environment (psk_dev_, psk_prod_). The server rejects mismatched-environment credentials before any database lookup.

1-hour token TTL

Access tokens expire after 1 hour. No refresh endpoint — re-mint with the same credentials when the token expires.

Revocation on demand

If a key is compromised, contact support to revoke. New token mints return 401 invalid_client immediately; in-flight access tokens expire within their 1-hour TTL.

Rate limiting

Per-tenant throttling on sheet generation and scan submission endpoints. Cache tokens for their full TTL to avoid auth-endpoint rate limits.

# 1. Mint an access token (Basic auth with your key + secret)
curl -u "$PAPERSCORER_KEY_ID:$PAPERSCORER_SECRET" \
  -X POST https://api-v2.paperscorer.com/PaperScorerWebServices/rest/auth/token

# Response (cache for the full 3600s TTL):
# {
#   "access_token": "eyJraWQiOiIyMDI2...signature",
#   "token_type": "Bearer",
#   "expires_in": 3600
# }

# 2. Use the token on every subsequent call
curl -H "Authorization: Bearer $ACCESS_TOKEN" \
  https://api-v2.paperscorer.com/PaperScorerWebServices/rest/ps/assessments

# 3. When the token expires, repeat step 1 — no refresh endpoint
#    by design (OAuth2 RFC 6749 §4.4.3, client_credentials flow).

Get Started for Free

You can create a free account with no obligation to purchase. Scan up to 100 testing sheets completely free while you test your integration.