Skip to main content
Safe Online Exam exposes a layered set of student-facing routes that carry a student from a signed Canvas LTI launch through encrypted SEB configuration download, Config Key proof, access-code release, and finally a settings-bound exit. This page documents every endpoint involved in that flow — configuration grants, .seb file delivery, public encryption certificate access, the proof/redemption cycle, session readiness, setup-check, assessment launch handoff, and the exit surface — together with the security constraints the server enforces at each step.

Content ID Formats

Every student route that accepts a contentId or quizId parameter expects one of two canonical formats. The server normalises incoming values to these forms before any database lookup. Identifiers outside these patterns return 403 or 404 without a lookup. Both formats are listed in the Compatibility Contracts section of the README and are treated as stable public identifiers.

Configuration Download Flow

Students do not use a static or reusable .seb link. The server issues a one-time, short-lived capability grant from a verified LTI session. The SEB client then presents that grant token as a query parameter when downloading the encrypted file.

POST /api/seb/config-grant/:courseId/:contentId

Mints a one-time configuration download grant bound to the verified LTI principal, course, content ID, and current settings fingerprint.
The grant expires after 120 seconds and can be consumed exactly once. A HEAD request from Windows SEB validates the grant URL without consuming it, so the single GET download retains its one-time claim.
Authentication: Requires an active verified LTI principal for the given courseId. The request must also carry a valid SEB config-grant action token in the request body and pass Fetch Metadata integrity checks. Students who require a Canvas session handoff must have an authorised Canvas OAuth grant before a configuration grant is issued. Path parameters
string
required
Canvas course ID. Must match the courseId on the verified LTI principal stored in the Express session.
string
required
Canonical content ID: classicquiz_{quizId} for Classic Quizzes or newquiz:{courseId}:{assignmentId} for New Quizzes.
Request body
string
Optional launch purpose override. Accepts "student-list" to change the browser handoff label; any other value defaults to "assessment".
Success response — 200
string
A sebs:// URL pointing to the .seb download endpoint. The browser hands this to the OS to open SEB directly.
string
Path to the browser-side handoff page (/seb/launch-handoff?key=…) that redirects the normal browser while SEB opens.
number
Token lifetime in seconds. Always 120.
Error responses

GET /seb/config/:courseId/:contentId.seb

Consumes a configuration grant and streams the encrypted SEB configuration file to the client. The server validates the grant token, confirms the current settings fingerprint has not changed since the grant was minted, obtains a fresh Canvas session URL for the student, builds the complete SEB plist (assessment start URL, URL filter, Config Key salt, HMAC-bound quit URL), and encrypts it with the configured public certificate before sending the response. Authentication: No session required. The one-time grant token in the grant query parameter is the sole credential for this endpoint. Path parameters
string
required
Canvas course ID.
string
required
Canonical content ID (without the .seb extension as a path segment — the .seb suffix is part of the route pattern, not a query parameter).
Query parameters
string
required
One-time grant token returned by POST /api/seb/config-grant. Must be a 43-character base64url string.
Success response — 200
The response body is the binary encrypted SEB configuration file. Error responses
Windows SEB issues a HEAD request before downloading. The server validates but does not consume the grant on HEAD, preserving the one-time claim for the subsequent GET.

Public Encryption Certificate Endpoints

These routes serve the public X.509 certificate used to encrypt .seb configurations. They carry no authentication requirement and are intended for device administrators who need to distribute the decryption identity.

GET /seb/config-encryption-certificate.pem

Downloads the active encryption certificate in PEM format. Success response — 200
Error response

GET /seb/config-encryption-certificate.cer

Downloads the same certificate in DER (binary) format, suitable for direct import into Windows Certificate Manager or macOS Keychain. Success response — 200

Requirement Check

GET /api/seb/requirement/:courseId/:quizId

Returns whether SEB is currently required for the given assessment. This endpoint is called by the Canvas detector and the Canvas theme loader before loading the full detector script. Authentication: None. This endpoint is public and unauthenticated. Path parameters
string
required
Canvas course ID.
string
required
Content ID in canonical form.
Success response — 200
or
The response is always success: true. A sebRequired: false result means SEB enforcement is absent, disabled, misconfigured, or unverifiable — the detector never shows a prompt on false. The server performs one exact primary-key lookup against the assessments table and coalesces concurrent identical requests through a short, bounded in-memory promise cache. The cache prevents a burst of simultaneous student page loads from all hitting the database; the result is always private and not cached by the browser (cache-control: private, no-store).

Config Key Proof and Access-Code Redemption

The two-step proof/redemption cycle is the central enforcement point. SEB obtains a Config Key hash from its JavaScript API, sends it to the proof endpoint, receives a one-time proof token, and immediately redeems that token for the Canvas access code.

POST /api/seb/access-proof/:courseId/:quizId

Validates that SEB is running the current configuration for this assessment and mints a one-time proof token. The server checks that the assessment exists, SEB is enabled and required, the effective exit password is set, and either the configKeyHash in the request body matches the expected Config Key for the current settings fingerprint, or the x-safeexambrowser-configkeyhash request header carries a valid hash. For session-handoff configurations the server can also validate through the handoff Config Key. Authentication: None (public endpoint). Identity comes entirely from the Config Key hash and URL proof. Path parameters
string
required
Canvas course ID.
string
required
Content ID in canonical form.
Request body
string
SHA-256 hash of the SEB Config Key for the current browser URL, as provided by the SEB JavaScript API (SafeExamBrowser.security.configKeyHash).
string
Current browser URL reported by SEB. Must be a valid HTTPS URL on the configured Canvas origin, matching the Classic Quiz take page or New Quiz assignment page for this course and content ID.
Success response — 200
string
A 43-character base64url one-time token. Pass this token in the x-seb-proof-token header of POST /api/seb/access-code.
number
Proof token lifetime. Always 120.
Error responses The response carries cache-control: no-store, pragma: no-cache, and related sensitive-response headers on every response.

POST /api/seb/access-code/:courseId/:quizId

Redeems a proof token and returns the Canvas access code, approved exam tool list, and an exit grant. The server atomically consumes the proof token, verifies the course, content, and settings fingerprint match, confirms the access code is still set, and generates an exit grant before returning the response. Authentication: None (public endpoint). The proof token is the only credential. Path parameters
string
required
Canvas course ID.
string
required
Content ID in canonical form.
Request headers
string
required
The proofToken value returned by POST /api/seb/access-proof. Must be a 43-character base64url string. The server rejects requests without a syntactically valid token before any database access.
Success response — 200
string
The current Canvas access code for this assessment. The detector fills only an unambiguous Canvas access-code prompt and never treats DOM content as authorisation.
string
A 43-character base64url token used to validate the post-submission exit page and the quit redirect. Valid for 12 hours (43 200 seconds).
number
Exit grant lifetime. Always 43200 (12 hours).
array
Approved external tools for this assessment. Each entry has id, label, and url. Empty array when no tools are configured or the SEB setting is not fully active.
Error responses The response carries sensitive no-store response headers.

GET /api/seb/access-code/:courseId/:quizId

Returns a 405 error. Redemption is always POST-only; this route exists to provide an explicit method error rather than a generic 404.

Approved Tools Under Session Boundary

GET /api/seb/tools/:courseId/:quizId

Returns the current approved tool list for an assessment while a verified LTI session is active. The detector uses this to refresh tool availability after an access-code redemption. Authentication: Requires a verified LTI principal for the given courseId. Path parameters
string
required
Canvas course ID.
string
required
Content ID in canonical form.
Success response — 200
Returns tools: [] when no tools are configured, or when SEB is not required, not enabled, or the effective quit password is absent.

Session Readiness

These two endpoints support an optional prompt that asks students to verify their Canvas session connection before the exam configuration is downloaded.

POST /api/seb/session-readiness

Checks whether the student’s stored Canvas OAuth grant can produce a session URL. A successful response proves the Canvas connection is ready without retaining or exposing the session URL itself. Authentication: Requires a verified student LTI principal. Success response — 200
Error responses

POST /api/seb/session-readiness/dismiss

Records the student’s preference to dismiss the readiness prompt. This preference is stored per Canvas user and is not a device trust record. Authentication: Requires a verified student LTI principal. Success response — 200

Setup Check Flow

The setup check is a separate SEB configuration that verifies certificate decryption, SEB detection, connectivity, and Config Key proof without releasing any assessment access code or establishing device trust.

GET /seb/check/config.seb

Downloads the setup-check SEB configuration. Unlike assessment configurations, this file is generated once and reused from an in-process cache across requests (the encrypted bytes are stable because the setup-check settings never change). Certificate readiness is re-verified on every response even when the cached bytes are served. The setup-check configuration starts at /seb/check, allows quit without an assessment exit password, and cannot be used to redeem an access-code proof. Authentication: None. Rate-limited per process and per IP.

GET /seb/check

Renders the setup-check page inside SEB. The page runs a Config Key proof against /api/seb/check-proof and reports the results to the student.

POST /api/seb/check-proof

Verifies that SEB is running the setup-check configuration. Request body
string
Config Key hash from the SEB JavaScript API for the current URL.
string
Current browser URL; must match /seb/check on the configured application base URL.
Success response — 200
Error response

GET /seb/check/quit

Renders the quit page for the setup check. Sets x-seb-quit: true and x-seb-exit: setup-check response headers so SEB can close the browser after the student dismisses the page.

SEB-Required Assessment View

GET /seb/quiz/:courseId/:quizId

Renders the “Safe Exam Browser Required” download page for a Classic Quiz when the student opens a quiz URL in a normal browser. This route is only for Classic Quizzes; it rejects New Quiz content IDs and redirects non-SEB-required assessments directly to Canvas. Authentication: Requires a verified LTI principal for the given courseId. Path parameters
string
required
Canvas course ID.
string
required
Classic Quiz ID (numeric string). New Quiz content IDs return 403.
Query parameters
string
Original Canvas quiz URL, used to construct the return link.
string
Canvas user ID, passed through to the React shell.

Assessment Launch Handoff

GET /seb/launch/:contentId and POST /seb/launch/:contentId

Handles the LTI assessment launch inside SEB. The POST variant accepts an id_token and state in the request body (standard LTI 1.3 launch); the GET variant handles a session-based reload where the principal is already in the Express session. The handler validates the LTI token (RS256 signature, issuer, audience, nonce, timestamps, deployment ID, target link URI, replay claim, and browser transaction cookie), regenerates the session, stores the verified principal, and either redirects to the Canvas assessment URL (if SEB is not required or the client is already SEB) or renders the SEB-required download page with a fresh config-grant action token.
A completed SEB launch is recorded in the session for up to 24 hours. A direct LTI replay — a second load of the same seb/launch/:contentId target — redirects to Canvas course home rather than re-presenting the download prompt, preventing a back-navigation loop.

GET /seb/launch/:contentId/login

Proxies OIDC initiation parameters to /lti/login. Used when Canvas redirects to the SEB-scoped LTI target for a new OIDC login.

GET /seb/launch-handoff

Consumes a short-lived browser launch handoff token and renders the same-tab launcher page that transitions the normal browser while SEB opens. Query parameters
string
required
The handoffUrl key token issued by POST /api/seb/config-grant or POST /api/seb/session-readiness.
The handoff record is consumed on access. After consumption, only the validated Canvas course return URL remains accessible (for clean back-navigation on reload), preventing the sebs:// configuration URL from being served a second time.

Exit Flows

GET /seb/exit/session/:courseId/:quizId/:grant

Renders the post-submission exit page after a student completes an assessment. The exit grant is validated against the current SEB setting before the page is displayed. Path parameters
string
required
Canvas course ID.
string
required
Content ID in canonical form.
string
required
Exit grant token returned in the exitGrant field of the access-code response.
The page links to GET /seb/exit/quit/:courseId/:quizId/:grant for the final quit redirect. A 403 with an explanatory message is returned when the grant is missing, expired, or the SEB setting is no longer active.

GET /seb/exit/quit/:courseId/:quizId/:grant

Validates the exit grant and performs an HMAC-authenticated redirect to the SEB quit URL embedded in the assessment configuration. This is the authoritative quit path; it reads the current access code from the database and constructs the configuration-bound quit URL before redirecting. Path parameters
string
required
Canvas course ID.
string
required
Content ID in canonical form.
string
required
Exit grant token.
Response 303 redirect to the SEB quit URL on success. 403 with an error page when the grant is invalid or expired.

GET /seb/exit/complete/:courseId/:quizId/:token

Renders the quit-completion page after SEB follows the quit URL. The token in the path is validated as an HMAC token derived from the current access code; the page sets x-seb-quit: true and x-seb-exit: submitted response headers to allow SEB to close. Path parameters
string
required
Canvas course ID.
string
required
Content ID in canonical form.
string
required
HMAC quit token derived from the assessment access code.

GET /seb/exit/:courseId/:quizId

Renders a non-terminal manual exit page. Used for non-submission or mode-driven exits. No grant is required; the page does not trigger an SEB quit.

GET /seb/exit/quit/:courseId/:quizId and GET /seb/exit/manual/:courseId/:quizId

These routes deliberately return 410 Gone. Unbound quit paths — those without a valid, settings-bound exit grant — are intentionally unavailable. Students must use the quit link provided on the post-submission exit page or SEB’s native Quit command with the proctor-provided exit password. These routes exist to give a clear failure signal rather than silently succeeding or returning 404.