Skip to main content
Safe Online Exam exposes all instructor-facing operations under the /api/quizzes prefix. This page covers every route an instructor’s browser calls when managing SEB policy for Classic Quizzes and New Quizzes in their Canvas course — from reading the cached assessment list through enabling SEB and rotating access codes to the short-lived password reveal flow.
Every route in this group requires a verified LTI instructor principal stored in the Express session. That principal is created only after a successful, fully-validated LTI 1.3 launch from Canvas; query parameters and request bodies cannot substitute for it. Mutation routes (marked with a below) additionally require the request to pass the same-origin Fetch Metadata integrity check enforced by the application’s HTTP middleware.

Discovery Routes

These read-only endpoints return assessment data cached from the most recent Canvas discovery run. They do not make live Canvas API calls.

GET /api/quizzes

Returns all Classic Quizzes and New Quizzes cached for the instructor’s current course. The response is a bare JSON array — there is no success envelope. Auth: Verified instructor principal. No action token required.

GET /api/quizzes/:quizId

Returns one cached assessment. The :quizId parameter accepts either a canonical content ID (classicquiz_{id} or newquiz:{courseId}:{assignmentId}) or a bare numeric Canvas quiz ID for Classic Quizzes. Auth: Verified instructor principal. The server re-checks that the requested assessment belongs to the session course.
string
required
Canonical content ID or bare Canvas quiz ID for a Classic Quiz.

GET /api/quizzes/seb-settings

Returns a map of SEB settings keyed by quiz ID for every assessment in the current course. Each value is a redacted settings view — access codes and passwords are not included in this response. Auth: Verified instructor principal.

POST /api/quizzes/course/:courseId/refresh

Triggers a fresh Classic Quiz and New Quiz discovery from Canvas for the given course. Uses the instructor’s stored Canvas OAuth grant to call the Canvas REST and New Quiz APIs. On success, returns the updated quiz list with counts. Auth: Verified instructor principal scoped to :courseId. Requires Canvas OAuth authorization.
string
required
Numeric Canvas course ID.
If Canvas authorization has expired, the response includes requiresAuth: true and an authUrl for the reauthorization flow rather than a hard error.

Course Defaults Routes

GET /api/quizzes/course/:courseId/defaults

Returns the course-level SEB defaults: URL policy, exit and start passwords (redacted), and the exam-tool catalog. Passwords in this response are never revealed — use the password reveal endpoint to read them. Auth: Verified instructor principal scoped to :courseId.
string
required
Numeric Canvas course ID.

PUT /api/quizzes/course/:courseId/defaults

Saves updated course defaults. Accepts URL policy rules, exit and start password values, and the full exam-tool catalog. All URL rules must be exact HTTPS URLs or concrete domains — regex and wildcard patterns are rejected. When externalTools is present in the body, the server replaces the course catalog with the supplied list after normalization. Auth: Verified instructor principal scoped to :courseId. Mutation guard required.
string
required
Numeric Canvas course ID.
Request body fields:
SebUrlRule[]
Array of URL policy rules. Each rule must be an exact HTTPS URL or a concrete domain without wildcards.
ExternalToolConfig[]
Replacement exam-tool catalog for the course. Each tool requires an exact HTTPS launch URL and explicit resource access rules.
string | null
New exit password, or null to remove the course-level override.
string | null
New start password, or null to remove the course-level override.
boolean
When false, marks course setup as incomplete.

SEB Management Routes

These routes commit or remove Canvas access codes and update SEB state. Each mutation acquires a short-lived PostgreSQL operation lock on the assessment record; overlapping requests for the same assessment are rejected with 409.

PUT /api/quizzes/:quizId/seb

Enables or disables SEB for the session-course assessment identified by :quizId. When enabling (required: true), the server creates a Canvas access code and persists SEB state only after the Canvas mutation succeeds. When disabling (required: false), the access code is removed from Canvas before local state is cleared. Auth: Verified instructor principal. The server re-validates that :quizId belongs to the session course.
string
required
Canonical content ID or bare Classic Quiz ID.
boolean
required
true to enable SEB; false to disable.

POST /api/quizzes/seb-config-structured

A structured alternative to the simple enable/disable toggle. Accepts a StructuredSebConfigRequest body and saves URL policy, password overrides, quiz-only tool definitions, and tool-ID selections for a single assessment without changing the sebRequired state. Exam-tool definitions (externalTools) are managed at the course level; submitting that field returns 400. Auth: Verified instructor principal. Optional userId query parameter is validated against the session user.
string
Canvas user ID. When present, must match the session principal’s user ID.
string
Canonical New Quiz content ID (newquiz:{courseId}:{assignmentId}). Use quizId for Classic Quizzes.
string
Canonical Classic Quiz content ID or bare Canvas quiz ID.
SebUrlRule[]
Per-assessment URL policy rules. Overrides course defaults when usesCourseDefaults is false.
string | null
Exit password override. Only applied when quitPasswordOverride is true.
string | null
Start password override. Only applied when startPasswordOverride is true.
boolean
When true, the assessment inherits URL policy and tool catalog from course defaults.
boolean
When true, uses the assessment-level exit password instead of the course default.
boolean
When true, uses the assessment-level start password instead of the course default.
string[] | null
Explicit allowlist of course-tool IDs to enable for this assessment. null means inherit the full course catalog.
ExternalToolConfig[]
Assessment-scoped tool definitions that are merged with the course catalog. These are never stored as course tools.

POST /api/quizzes/:courseId/:quizId/seb/enable

Enables SEB for a specific assessment and sets the Canvas access code. The server dispatches to the Classic Quiz or New Quiz Canvas API based on the content ID format. Requires an effective exit password (assessment override, course default, or configured managed default) or the request is rejected. Auth: Verified instructor principal scoped to :courseId and :quizId.
string
required
Numeric Canvas course ID.
string
required
Canonical content ID (classicquiz_{id} or newquiz:{courseId}:{assignmentId}).

POST /api/quizzes/:courseId/:quizId/seb/disable

Disables SEB for a specific assessment and removes the Canvas access code. Auth: Verified instructor principal scoped to :courseId and :quizId.
string
required
Numeric Canvas course ID.
string
required
Canonical content ID.

POST /api/quizzes/:courseId/:quizId/seb/reset-defaults

Returns one assessment to course defaults. Clears any assessment-level URL policy, password overrides, and tool-ID selections so the assessment inherits the course catalog. Auth: Verified instructor principal scoped to :courseId and :quizId.
string
required
Numeric Canvas course ID.
string
required
Canonical content ID.

POST /api/quizzes/:courseId/:quizId/seb/regenerate-code

Generates a new Canvas access code and applies it to the Canvas assessment. Students already on the quiz page must reload — the previous access code is immediately invalid. Returns only a success message; the new code is not included in the response. Auth: Verified instructor principal scoped to :courseId and :quizId. Requires Canvas OAuth authorization.
string
required
Numeric Canvas course ID.
string
required
Canonical content ID.

GET /api/quizzes/:courseId/:quizId/seb/config

Redirects (HTTP 302) to the current SEB configuration flow at /seb/launch/:quizId. This is an instructor convenience shortcut; it does not require Canvas OAuth. Auth: Verified instructor principal. No mutation guard.
string
required
Numeric Canvas course ID (used for route matching; not included in the redirect target).
string
required
Canonical content ID. Used as the redirect target.

GET /api/quizzes/:courseId/:quizId/seb/status

Returns a secret-free status view for one assessment: whether SEB is enabled and required, whether an access code exists, and whether the current configuration is valid (has a required exit password). Access codes and passwords are not included. Auth: Verified instructor principal. No mutation guard.
string
required
Numeric Canvas course ID.
string
required
Canonical content ID.

Exam Tool Routes

GET /api/quizzes/course/:courseId/exam-tools/:toolId/copy-targets

Returns a list of other Canvas courses where the instructor is a teacher and where the specified exam tool can be copied. The picker list is a convenience view; the server re-authorizes the live Canvas list before any copy operation. Auth: Verified instructor principal. Requires Canvas OAuth. School-managed tools (managedByAdmin: true) cannot be copied; the route returns 409 for those.
string
required
Numeric Canvas course ID of the source course.
string
required
Local tool ID from the course exam-tool catalog.

POST /api/quizzes/course/:courseId/exam-tools/:toolId/copy

Copies one instructor-owned exam tool into one or more target courses. Before writing, the server:
  1. Snapshots the reset generation for every target course.
  2. Re-reads the live Canvas teacher-course list for the user.
  3. Rejects any target not present in the live Canvas response.
  4. Rejects any target whose reset generation has advanced since the snapshot.
The copy appends a local tool definition without replacing the target catalog and preserves an existing equivalent definition on retry. Auth: Verified instructor principal scoped to :courseId. Mutation guard required. Maximum 100 targets per request.
string
required
Numeric Canvas course ID of the source course.
string
required
Local tool ID from the source course catalog.
string[]
required
Array of numeric Canvas course IDs to receive the tool. The source course ID must not appear in this list.

Password Reveal Routes

Password reveal responses are short-lived and no-store. The server sets Cache-Control: no-store and related security response headers on every reveal response. The client receives a 30-second expiry hint in expiresInSeconds. Managed server-default exit passwords are deliberately never returned to the browser — only course-level and assessment-level overrides are revealed.

POST /api/quizzes/course/:courseId/passwords/reveal

Reveals the course-level start and exit passwords for the given course. If the exit password source is "managed" (a server-configured default), the value is returned as null even though an effective password exists. Auth: Verified instructor principal scoped to :courseId. Mutation guard required.
string
required
Numeric Canvas course ID.
The source field indicates where the password originates: "assessment" (assessment-level override), "course" (course-level override), "managed" (server-configured default, value withheld), or "none" (no password set).

POST /api/quizzes/:courseId/:quizId/passwords/reveal

Reveals the start and exit passwords for a single assessment. The source field distinguishes whether each password is inherited from the course or set as an assessment-level override. Auth: Verified instructor principal scoped to :courseId and :quizId. Mutation guard required.
string
required
Numeric Canvas course ID.
string
required
Canonical content ID.

Content ID Reference

Safe Online Exam uses canonical content IDs as stable assessment identifiers in URL path segments and request/response bodies.
Example: classicquiz_123Bare numeric IDs (e.g. 123) are accepted as path parameters for backward compatibility and are normalized internally to the canonical form.

Common Error Codes

When Canvas rejects the stored OAuth token, mutation routes return success: false with requiresAuth: true and an authUrl that opens the reauthorization flow in a popup. The LTI session page remains open.
URL rules, domain lists, and exam-tool definitions are validated before any database write. Common error codes:
When a Canvas mutation is already in progress for an assessment, subsequent requests return 409 with one of: