Legal

Canvas access

Status: Published. Retention periods, credential handling and security commitments on this page are sourced from the production codebase and reviewed by Fjordbyte.

Last updated: 2 September 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–15 minutes for your Canvas admin) or the Personal Access Token quickstart (single-teacher pilot, no IT involvement).


At a glance

QuestionAnswer
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?For the active duration of the contract or pilot. Deleted within 30 days of termination or of a deletion request. Operational and billing records are kept for the lifetime of the organization; see Retention for the detail.
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:

  1. Generates a Personal Access Token in Canvas (Account → Settings → "+ New Access Token").
  2. Pastes the token into Lectora's onboarding screen.
  3. Lectora verifies the token by calling GET /api/v1/users/self against 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 profile
  • GET /api/v1/users/self/enrollments — find which courses the user can access
  • GET /api/v1/users/:id and /api/v1/users/:id/profile — student names/emails for the courses being graded
  • GET /api/v1/users/:id/communication_channels — fallback lookup for a student's primary email when the profile endpoint does not expose it
  • GET /api/v1/accounts/self and /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/courses and /api/v1/courses/:id — course list, course details (including term metadata)
  • GET /api/v1/courses/:id/users — roster
  • GET /api/v1/courses/:id/enrollments (and ?user_id=self) — full enrollment list, plus the caller's own per-course role
  • GET /api/v1/courses/:id/assignments, /api/v1/courses/:id/assignments/:id, and /api/v1/courses/:id/assignment_groups — assignment metadata and grouping
  • GET /api/v1/courses/:id/assignments/:id/submissions and GET /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/rubrics and /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 metadata
  • GET /api/v1/courses/:id/quizzes/:id/questions — question text and options
  • GET /api/v1/courses/:id/quizzes/:id/submissions — list of student attempts
  • GET /api/v1/courses/:id/quizzes/:id/submissions/:id/events — per-attempt event log (timestamps, navigation, autosaves) used to flag anomalies
  • GET /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/groups and /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 optional comment[file_ids][] for attached files, comment[group_comment] for group assignments, and submission[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 /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 (no Authorization header 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 DELETE endpoint 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 categoryStorage locationProviderRegion
PAT mode — encrypted Canvas PATPostgreSQL account tableSupabaseEU — Frankfurt
LTI mode — RSA tool key pair (public + AES-256-GCM-encrypted private key) used to sign LTI JWTsPostgreSQL lti_key_pairs tableSupabaseEU — 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 tableSupabaseEU — Frankfurt
LTI mode — per-launch single-use OIDC nonces and OAuth state tokens (auto-expire)PostgreSQL lti_nonces tableSupabaseEU — Frankfurt
Instructor profile (name, email, avatar URL)PostgreSQL user tableSupabaseEU — Frankfurt
Course / assignment / enrolment metadata — synced via LTI launch claims, REST bulk, or REST live (cache miss)PostgreSQL courses, assignments, enrollment tablesSupabaseEU — Frankfurt
Student names + emails (for the rosters of synced courses)PostgreSQL user and enrollment tablesSupabaseEU — Frankfurt
Submission content (text bodies, attachment files)Object storage + transient working copiesVercel BlobEU — Stockholm
Grading drafts (AI-suggested grade + rationale + per-rubric scores)PostgreSQL grading tableSupabaseEU — Frankfurt
AI inference (prompts + responses)Not persisted at the provider — zero data retentionOpenAI EU / Google Vertex EUEU

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/jwks endpoint. Possession of the private key lets Lectora prove identity to Canvas at launch time. It is Lectora's own service credential rather than an institution-scoped one: a single active key pair signs launches for every install, and it carries no institution or student data. The private half is encrypted at the application layer (AES-256-GCM) and never leaves the database. There is no automated rotation today — rotating the key is a manual operator procedure — and we would rather say so than imply a schedule we do not run.
  • 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_credentials to 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

Durations below reflect what the platform actually enforces today. Where no automated deletion job exists, that is stated plainly rather than expressed as a period we do not enforce; those categories are deleted when the organization is deleted, or on request.

PAT-mode credentials

  • Encrypted Canvas PAT: retained encrypted (AES-256-GCM, application-layer) until the user replaces it with a new token, or until the user's Lectora account is deleted — at which point it is removed with the account, 30 days after the deletion request. Revoking the token in Canvas makes it inert immediately (Lectora can no longer use it), but does not by itself remove the encrypted value from our database.

    We are candid that this is weaker than it should be: there is currently no in-product "disconnect Canvas" action, and the automated token-cleanup job does not cover manually entered tokens. Adding a disconnect path that clears the credential on demand is on our roadmap. Until it ships, the reliable way to end Lectora's access immediately is to revoke the token in Canvas (Settings → Approved Integrations), and to request account deletion if you also want the stored value removed.

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 30 days of the trigger. The encrypted OAuth Developer Key secret is stored as a required field, so it is removed by deleting the registration row rather than being cleared in place — removal of the row is the mechanism.
  • Tool RSA key pair (lti_key_pairs) is Lectora's own signing material and is not institution-scoped. One active key pair serves all installs. It is retained for the life of the service: no automated rotation, expiry or deletion job exists, so no rotation interval is claimed here. The JWKS endpoint publishes every active public key, so a rotation can overlap the old and new key without breaking in-flight launches when we do perform one. 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 30 days. This deletion is operator-initiated on request; there is no automated calendar-based purge of course content, and none is implied here. 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 the lifetime of the organization and deleted together with it; no fixed calendar period is enforced. Includes the trial / entitlement / license audit logs that record sysadmin-initiated billing changes. Two related records do carry fixed periods: data-subject-request records are deleted after 3 years, and erasure-proof records are kept for 10 years so we can evidence that a deletion was carried out.
  • Stripe webhook event records (stripe_webhook_events) — billing and idempotency records, retained without a fixed deletion period at present. They contain no student data and are stripped of personal fields when written; what remains is Stripe identifiers and amounts.
  • 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. We complete deletion within 30 days of the request, in line with the one-month response period in GDPR Article 12(3), and confirm in writing when it is done. The one exception is a legal hold: where a record is pinned by an active data-subject request or a litigation/regulatory hold, deletion of that record completes when the hold lifts, and everything not under the hold is still deleted on schedule.


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/self to 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 Authorization header.
  • Vulnerability management: dependency scanning on every commit; for critical CVEs we commit to applying security updates to the running service within 7 days of an upstream fix being available, and sooner where a vulnerability is actively exploited.

Access control — who at Fjordbyte can see institutional data

  • 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

  1. 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.
  2. 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:

  1. 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.
  2. 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 30 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 — a revoked token cannot be used, whether or not the stored value has yet been removed. Removal of the stored PAT itself follows the account-deletion path described under Retention. LTI registration records and encrypted OAuth Developer Key secrets are removed within 30 days of the deletion request. Synced Canvas data (rosters, submissions, grading drafts, published feedback) follows the retention policy above — deleted within 30 days of contract termination for institutional accounts, or within 30 days of an explicit deletion request for PAT-mode users.


For institutional engagements

Institutions deploying Lectora beyond a single-instructor pilot should:

  1. 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.
  2. Use LTI 1.3, not PAT. LTI gives the institution full visibility into Lectora's installation, scope grants, and removal.
  3. Review the Subprocessors page and (for the canonical version) Bilag B of the DPA.
  4. 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 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