Status: DRAFT — pending verification by Fjordbyte and (where applicable) institutional legal/IT review.
Last updated: 20 May 2026
Audience: IT, security, and data-protection reviewers at institutions evaluating Lectora; individual instructors who want to understand what connecting a Personal Access Token (PAT) does.
This page describes exactly what data Lectora reads from and writes back to your Canvas LMS, how the credential (PAT or LTI session) is stored, where the data goes after it enters Lectora, and how to revoke access. It complements — and does not replace — the Privacy Policy, Terms of Service, and Subprocessors pages, and (for institutional engagements) the signed Data Processing Agreement (DPA).
For step-by-step install walkthroughs, see the Canvas LTI 1.3 admin install guide (institution-wide, ~10 minutes for your Canvas admin) or the Personal Access Token quickstart (single-teacher pilot, no IT involvement).
At a glance
| Question | Answer |
|---|---|
| How does Lectora authenticate to Canvas? | Either an LTI 1.3 launch (institutional install) or a Canvas Personal Access Token the user generates and pastes into Lectora (individual / pilot mode). |
| What scope does the PAT have? | The PAT inherits the full scope of the user who created it. Canvas does not let users restrict a PAT to a subset of permissions — it is bearer-equivalent to that user's password. See "Personal Access Token" below for what this means in practice and how to scope it down. |
| Does Lectora write to Canvas? | Yes — but only specific operations: post grades on assignments you choose, post grading comments (with optional attached files), delete grading comments you've posted, and — for classic Canvas quizzes — score student attempts per-question, update existing quiz questions, and request quiz statistics reports. Lectora never creates new courses, assignments, or quizzes, and never deletes students, enrollments, courses, assignments, or quizzes. |
| Where is data stored after it leaves Canvas? | EU/EEA — see Subprocessors. PostgreSQL (Supabase, Frankfurt), object storage (Vercel Blob, Stockholm), application servers (Vercel, Frankfurt). |
| How long is data retained? | [FILL — confirm with Fjordbyte: typical pattern is "for the active duration of the contract / pilot, plus a defined grace period; deleted on revocation of access or termination"] |
| Who at Fjordbyte can access institutional data? | A named, documented set of Fjordbyte engineers under role-based access control; access is audit-logged. See "Access control" below. |
| What does Lectora send to AI providers? | Submission content and grading rubrics — to OpenAI (EU region) or Google Vertex AI (EU region). No direct personal identifiers (name, email, student ID); only internal pseudonymous IDs. Zero data retention, no training on customer data. See Subprocessors. |
How Lectora connects to your Canvas
Lectora supports two connection modes:
1. LTI 1.3 (institutional install)
The Canvas admin installs Lectora as an LTI 1.3 tool at the account or sub-account level. Users launch Lectora from inside Canvas; OAuth 2.0 client credentials govern Lectora's API access. Recommended for any deployment beyond a single-instructor pilot — it gives the institution full visibility and control over who can use Lectora and what scopes are granted.
The remainder of this page focuses on PAT mode, which is what most pilots use during evaluation. Most of the data-handling principles are identical between the two modes; the difference is purely how Lectora authenticates.
2. Personal Access Token (PAT) — pilot mode
The instructor:
- Generates a Personal Access Token in Canvas (Account → Settings → "+ New Access Token").
- Pastes the token into Lectora's onboarding screen.
- Lectora verifies the token by calling
GET /api/v1/users/selfagainst the institution's Canvas, then stores it encrypted at rest (see "Security" below) and starts a background sync of the instructor's enrollments.
From that point on, Lectora makes Canvas API calls on behalf of that instructor, using the same permissions Canvas grants them.
Personal Access Token — scope, sensitivity, control
A Canvas PAT is bearer-equivalent to the user's password for API purposes. Canvas does not provide a mechanism to restrict a PAT to a subset of scopes (unlike, e.g., GitHub fine-grained personal access tokens). Whoever holds the token can call any Canvas API endpoint that the user could call through the web UI.
This has two implications worth understanding:
A. The blast radius of a PAT is the blast radius of the user. An instructor's PAT can only access courses, students, and assignments the instructor can access in Canvas. A Canvas account admin's PAT can access everything in the account. Do not connect a PAT generated by a Canvas account admin to Lectora unless the institution explicitly intends Lectora to operate with admin-level scope. For pilots, use an instructor account.
B. Lectora's own access discipline matters more than the token's intrinsic scope. Lectora's code reads only the specific endpoints listed below; nothing else. Fjordbyte commits, contractually for institutional customers and as a published commitment for PAT-mode users, that Lectora will not call Canvas endpoints outside the documented set without notifying the institution and obtaining authorisation.
What Lectora reads (the actual endpoints)
The full list of Canvas API endpoints Lectora's code calls, as of the current production release:
User & enrolment context
GET /api/v1/users/self— verify the token, fetch the user's name/email/avatar to populate their Lectora profileGET /api/v1/users/self/enrollments— find which courses the user can accessGET /api/v1/users/:idand/api/v1/users/:id/profile— student names/emails for the courses being gradedGET /api/v1/users/:id/communication_channels— fallback lookup for a student's primary email when the profile endpoint does not expose itGET /api/v1/accounts/selfand/api/v1/accounts/self/admins/self— detect whether the user has account-admin role (for surfacing admin-only features in the UI)
Courses, assignments, submissions
GET /api/v1/coursesand/api/v1/courses/:id— course list, course details (including term metadata)GET /api/v1/courses/:id/users— rosterGET /api/v1/courses/:id/enrollments(and?user_id=self) — full enrollment list, plus the caller's own per-course roleGET /api/v1/courses/:id/assignments,/api/v1/courses/:id/assignments/:id, and/api/v1/courses/:id/assignment_groups— assignment metadata and groupingGET /api/v1/courses/:id/assignments/:id/submissionsandGET /api/v1/courses/:id/assignments/:id/submissions/:user_id— student work to be graded- Authenticated download of submission attachments and course files via the Canvas-issued file URLs — fetched into Lectora using the connected user's token so the file can be analysed (see "Where data is stored" below)
Rubrics
GET /api/v1/courses/:id/rubricsand/api/v1/courses/:id/rubrics/:id— rubric definitions used by the AI grader
Course files (metadata only)
GET /api/v1/courses/:id/folders,/api/v1/courses/:id/files, and/api/v1/courses/:id/files/:id— listing and metadata for course materials referenced by assignments
Classic quizzes (when you grade Canvas Quizzes through Lectora)
GET /api/v1/courses/:id/quizzes/:id— quiz metadataGET /api/v1/courses/:id/quizzes/:id/questions— question text and optionsGET /api/v1/courses/:id/quizzes/:id/submissions— list of student attemptsGET /api/v1/courses/:id/quizzes/:id/submissions/:id/events— per-attempt event log (timestamps, navigation, autosaves) used to flag anomaliesGET /api/v1/courses/:id/quizzes/:id/reports/:id— fetch a quiz statistics report Lectora has previously requested (see "What Lectora writes back" below)GET /api/v1/quiz_submissions/:id/questions— student answers, one row per question
Groups
GET /api/v1/courses/:id/groupsand/api/v1/groups/:id/users— group context and membership for group assignments
This list is exhaustive for the current production release. Future additions are governed by the change-notice clauses on the Subprocessors page and (for institutional customers) the DPA.
What Lectora writes back
Lectora makes write calls to Canvas only for the following operations, and only at the user's explicit request inside Lectora:
Grades and grading comments on regular assignments
PUT /api/v1/courses/:course_id/assignments/:assignment_id/submissions/:user_id— used for two distinct operations:- Post a grade — JSON body
{ submission: { posted_grade } }. Triggered when the instructor approves an AI-suggested grade and clicks "Post to Canvas". - Post a grading comment — form-encoded
comment[text_comment](with optionalcomment[file_ids][]for attached files,comment[group_comment]for group assignments, andsubmission[posted_grade]when grade + comment are posted together). This is the Canvas "Grade or comment on a submission" endpoint; Lectora does not use a separate comment-edit endpoint.
- Post a grade — JSON body
POST /api/v1/courses/:course_id/assignments/:assignment_id/submissions/:user_id/comments/files— initiate upload of an annotated feedback file to be attached to a submission comment. Used by Lectora's "publish feedback with attachment" flow; triggered only when the instructor includes a file with their feedback. The follow-up multipart upload goes to a Canvas-signed URL (noAuthorizationheader required and not a/api/v1/endpoint).DELETE /api/v1/courses/:course_id/assignments/:assignment_id/submissions/:user_id/comments/:id— delete a grading comment Lectora has previously posted. Triggered when the instructor unpublishes or replaces feedback. Note: editing existing comments is not supported — Lectora deletes + re-posts.
Classic quizzes
POST /api/v1/courses/:course_id/quizzes/:quiz_id/reports— request a quiz statistics report. This generates a report Lectora can subsequently GET for per-question analytics; it does not create a quiz.PUT /api/v1/courses/:course_id/quizzes/:quiz_id/submissions/:submission_id— score an existing quiz submission per-question (quiz_submissions[].questions_scores). Triggered when the instructor approves AI-suggested per-question scores for a quiz attempt.PUT /api/v1/courses/:course_id/quizzes/:quiz_id/questions/:question_id— update an existing quiz question (e.g. correct an answer key after grading reveals a mis-keyed item). Triggered only when the instructor explicitly edits the question through Lectora.
Lectora does not:
- Create new courses, assignments, or quizzes in Canvas. (Lectora can author quizzes in its own UI, but writing those back to Canvas is not an operation Lectora performs today.)
- Call any
DELETEendpoint other than the submission-comment delete listed above. In particular: no deletion of students, enrollments, courses, assignments, quizzes, or quiz questions. - Make role/permission changes, account-level administrative changes, or any change to Canvas users or settings outside the listed endpoints.
Where data is stored after it leaves Canvas
| Data category | Storage location | Provider | Region |
|---|---|---|---|
| PAT mode — encrypted Canvas PAT | PostgreSQL account table | Supabase | EU — Frankfurt |
| LTI mode — RSA tool key pair (public + AES-256-GCM-encrypted private key) used to sign LTI JWTs | PostgreSQL lti_key_pairs table | Supabase | EU — Frankfurt |
LTI mode — per-Canvas registration record: issuer, client ID, deployment ID, platform JWKS/auth/token URLs, organization link, AES-256-GCM-encrypted OAuth Developer Key secret (used for the user-facing authorization_code flow, since Canvas LTI keys themselves don't support that grant) | PostgreSQL lti_registrations table | Supabase | EU — Frankfurt |
| LTI mode — per-launch single-use OIDC nonces and OAuth state tokens (auto-expire) | PostgreSQL lti_nonces table | Supabase | EU — Frankfurt |
| Instructor profile (name, email, avatar URL) | PostgreSQL user table | Supabase | EU — Frankfurt |
| Course / assignment / enrolment metadata — synced via LTI launch claims, REST bulk, or REST live (cache miss) | PostgreSQL courses, assignments, enrollment tables | Supabase | EU — Frankfurt |
| Student names + emails (for the rosters of synced courses) | PostgreSQL user and enrollment tables | Supabase | EU — Frankfurt |
| Submission content (text bodies, attachment files) | Object storage + transient working copies | Vercel Blob | EU — Stockholm |
| Grading drafts (AI-suggested grade + rationale + per-rubric scores) | PostgreSQL grading table | Supabase | EU — Frankfurt |
| AI inference (prompts + responses) | Not persisted at the provider — zero data retention | OpenAI EU / Google Vertex EU | EU |
The two LTI mode credentials worth calling out explicitly:
- The RSA tool key pair is Lectora's own signing material — Canvas validates Lectora-issued JWTs against the public key served at Lectora's
/api/lti/jwksendpoint. Possession of the private key lets Lectora prove identity to Canvas at launch time. Lectora generates one keypair per install and rotates it on demand. - The OAuth Developer Key secret is the institution-side credential — an API key the Canvas admin generates in Developer Keys → API and pastes into the Lectora registration form. It is needed because Canvas LTI keys only grant
client_credentialsto the tool itself; user-facing OAuth (which is how Lectora obtains user-scoped Canvas API access after an LTI launch) requires a separate non-LTI Developer Key. The api_key portion is encrypted at the application layer (AES-256-GCM) before being stored.
For the canonical, contractually-binding list of subprocessors and the international-transfer posture (US providers covered by EU SCCs), see Subprocessors.
Retention
[FILL — Fjordbyte to confirm specific durations. The categorisation and trigger events below match the current production code paths; the bracketed durations are reasonable starting points pending confirmation.]
PAT-mode credentials
- Encrypted Canvas PAT: retained encrypted (AES-256-GCM, application-layer) until any of: the user disconnects Canvas inside Lectora, the user deletes the token in Canvas (Lectora detects the resulting 401 on next call and tears down the binding), or the user account is deleted. On any of these events, the encrypted credential is purged from the database within
[REVIEW — e.g. 24 hours].
LTI-mode credentials
- Per-Canvas registration record (
lti_registrations) — including the issuer, client ID, deployment ID, platform URLs, organization link, and the encrypted OAuth Developer Key secret — is retained for the lifetime of the LTI install. Removing the LTI tool from Canvas does not automatically delete this record on Lectora's side (Canvas does not notify tools on uninstall); deletion is operator-initiated by Fjordbyte on customer request or on contract termination, within[REVIEW — e.g. 7 days]of the trigger. The encrypted OAuth API key is purged together with the registration row. - Tool RSA key pair (
lti_key_pairs) is Lectora's own signing material and is not institution-scoped. Active keys are retained until rotated; rotated keys are kept inactive for at least one Canvas JWT max-age window so in-flight launches can still validate, then deleted. Encrypted private keys are never exported from the database. - Per-launch nonces and OAuth state tokens (
lti_nonces) are single-use and auto-expire (typically within minutes of issuance). Expired rows are garbage-collected by the periodic cleanup job; they carry no personal data.
Synced Canvas data (both modes)
- Course, assignment, enrolment, rubric metadata; rosters; submission content; grading drafts; published-feedback records — retained for the active duration of the pilot/contract. On termination of the pilot or contract (or on an explicit deletion request from a PAT-mode user), all institution-scoped data is deleted within
[REVIEW — e.g. 30 days]. Database backups expire per Supabase's backup retention policy; submission attachments and exported feedback files in Vercel Blob are deleted on the same schedule as the corresponding database rows.
Operational records
- Audit logs — retained for
[FILL — e.g. 12 months]for security and operational debugging, then deleted. Includes the trial / entitlement / license audit logs that record sysadmin-initiated billing changes. - Stripe webhook event records (
stripe_webhook_events) — retained per Stripe's recommended idempotency window,[FILL — e.g. 90 days]. - Anonymous / aggregated usage metrics — retained indefinitely; contain no personal data and cannot be re-identified to an institution or user.
Institutional customers can request deletion at any time by emailing lectora@fjordbyte.no. Standard turnaround: [FILL — e.g. 14 days].
Security
- Encryption in transit: all Canvas API traffic and all Lectora ↔ user / Lectora ↔ subprocessor traffic uses TLS 1.2 or higher.
- Encryption at rest: the Canvas PAT is encrypted at the application layer before being written to the database (AES-256-GCM with a 96-bit IV, 128-bit auth tag, and versioned master keys for key rotation); the database itself also encrypts at rest at the storage layer (AES-256, managed by Supabase).
- Token verification on submission: before storing a PAT, Lectora calls
/api/v1/users/selfto verify it is valid and to bind it to the correct Canvas user; invalid or wrong-base-URL tokens are rejected without being stored. - No token in logs: Canvas PATs are never written to application logs or error trackers; Lectora's logging pipeline redacts the
Authorizationheader. - Vulnerability management: dependency scanning on every commit; security updates applied to runtime within
[FILL — e.g. 7 days]of upstream release for critical CVEs.
Access control — who at Fjordbyte can see institutional data
[FILL — Fjordbyte to confirm and tighten this section. Skeleton:]
- A documented, named list of Fjordbyte engineers has production database access, granted via individual SSO accounts (not shared credentials).
- All production access is logged and reviewable.
- Access to a specific institution's data, when required for support, follows the principle of least privilege: time-bounded, purpose-bounded, and recorded.
- Lectora's AI providers (OpenAI, Google Vertex) operate under zero-data-retention contractual commitments — they cannot view, retain, or train on the prompts Lectora sends them.
Revoking access
At any time, an institution or individual user can revoke Lectora's access to their Canvas instance.
If you connected via PAT
- In Canvas: Account → Settings → Approved Integrations → find the token labelled "Lectora" (or whatever label you used when generating it) → click the trash icon to delete it.
- In Lectora: Settings → Integrations → Canvas → Disconnect.
Either action alone is sufficient to stop new API calls. Doing both removes the credential from both systems.
If you connected via LTI 1.3
The Canvas admin has two levers, and we recommend pulling both:
- In Canvas — remove or disable the LTI Developer Key and the matching API Developer Key. This immediately blocks Lectora from initiating new launches and from completing user-facing OAuth flows. Existing user sessions inside Lectora continue until they expire, but Lectora cannot mint fresh Canvas API credentials.
- By email to Fjordbyte — send a deletion request to lectora@fjordbyte.no referencing the institution. Canvas does not notify tools when an LTI install is removed, so the registration record, the encrypted OAuth Developer Key secret, and the associated organization-scoped data are deleted on Fjordbyte's side by operator action, within
[REVIEW — e.g. 7 days]of the request. The signed DPA may also specify a stricter SLA for institutional accounts.
What happens to your data after revocation
Lectora stops making Canvas API calls immediately once credentials are invalidated on the Canvas side. PAT credentials are purged within [REVIEW — e.g. 24 hours] of disconnect/revocation. LTI registration records and encrypted OAuth Developer Key secrets are purged within [REVIEW — e.g. 7 days] of the deletion request. Synced Canvas data (rosters, submissions, grading drafts, published feedback) follows the retention policy above — deleted within [REVIEW — e.g. 30 days] of contract termination for institutional accounts, or within [REVIEW — e.g. 30 days] of explicit deletion request for PAT-mode users.
For institutional engagements
Institutions deploying Lectora beyond a single-instructor pilot should:
- Sign Fjordbyte's DPA. The DPA binds Fjordbyte as a processor and includes the EU SCCs for US-based subprocessors. Contact lectora@fjordbyte.no for the current version.
- Use LTI 1.3, not PAT. LTI gives the institution full visibility into Lectora's installation, scope grants, and removal.
- Review the Subprocessors page and (for the canonical version) Bilag B of the DPA.
- Request a Transfer Impact Assessment for the US-based subprocessors (Inngest, Resend, Statsig) if your institution's legal team requires one — Fjordbyte has TIAs on file and can share them under NDA.
Open questions for IT review
If your institutional IT or security team has questions this page does not answer — e.g. about specific compliance frameworks (NSM grunnprinsipper, ISO 27001 alignment, BSI C5), penetration-test reports, business-continuity plans, or sub-processor change-notification clauses — please email lectora@fjordbyte.no with the question. We'll respond within [FILL — e.g. 5 working days] and add common questions to this page over time.
Contact
For questions about Canvas access, data handling, or to request the DPA: lectora@fjordbyte.no