/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.
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.
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 with409.
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:
- Snapshots the reset generation for every target course.
- Re-reads the live Canvas teacher-course list for the user.
- Rejects any target not present in the live Canvas response.
- Rejects any target whose reset generation has advanced since the snapshot.
: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
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.
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.- Classic Quiz
- New Quiz
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
Policy validation errors
Policy validation errors
URL rules, domain lists, and exam-tool definitions are validated before any database write. Common error codes:
Operation lock conflicts
Operation lock conflicts
When a Canvas mutation is already in progress for an assessment, subsequent requests return
409 with one of: