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.
GET /rest/ps/assessmentsGET /rest/ps/form-studentsIntegration Workflow
Follow these steps to integrate PaperScorer into your platform
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
POST /rest/auth/tokenGET /rest/auth/tokeninfoSheet 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
POST /rest/ps/generate-answer-sheetPOST /rest/ps/generate-question-paperSubmitting 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
POST /rest/ps/scan-sheetPOST /rest/ps/scan-uploaded-sheetPOST /rest/ps/queue-scanned-sheetPOST /rest/ps/bulk-uploadPolling 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
GET /rest/ps/job-statusGET /rest/ps/task-statusReading 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
GET /rest/ps/scanned-sheetsGET /rest/ps/scanned-sheet-dataGET /rest/ps/upload-errorsGET /rest/ps/essay-image-detailsManaging 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
POST /rest/ps/submit-scanned-sheet-correctionPOST /rest/ps/skip-scanned-sheetScoring & 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
GET /rest/ps/form-scoresGET /rest/ps/form-scores-summaryGET /rest/ps/student-scoresGET /rest/ps/student-form-answersGET /rest/ps/sync-student-scoresPOST /rest/ps/acknowledge-sync-student-scoresBuilt 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.