Goal
Push grades directly from Chickadee to UWaterloo LEARN (Brightspace/D2L) — the same grade sync capability that tools like Akindi provide.
Options Considered
Option 1: D2L Valence REST API (recommended)
Use D2L's Valence REST API with OAuth2 client credentials (server-to-server). Instructor links each Chickadee course and assignment to the corresponding LEARN org unit and grade item, then clicks "Push to LEARN" to sync grades. Students never change their workflow.
Key endpoints:
GET /d2l/api/lp/1.48/orgstructure/?orgUnitName=<name> — look up course by name
GET /d2l/api/le/1.71/{orgUnitId}/grades/ — list grade items in a course
PUT /d2l/api/le/1.71/{orgUnitId}/grades/{gradeObjectId}/values/{userId} — write a student's grade
- Scopes needed:
grades:gradevalues:read, grades:gradevalues:write, core:*:*:*
Design sketch:
- New env vars:
LEARN_BASE_URL, LEARN_CLIENT_ID, LEARN_CLIENT_SECRET, LEARN_USER_ID_FIELD
LEARNTokenStore actor — caches OAuth2 bearer token
LEARNService.swift — Valence REST calls (lookup, list, push)
AddLEARNFields migration — learn_org_unit_id on courses, learn_grade_object_id + learn_last_pushed_at on assignments
- "Link to LEARN" flow on course/assignment edit pages — queries D2L by name, instructor confirms
- "Push to LEARN" button on the grades/submissions view
- Grade calculation reuses existing
gradePercentFromCollectionJSON logic
Open questions before building:
- Which user identifier does UWaterloo LEARN accept? (
studentID → orgDefinedId, username, or externalSubject from SSO sub claim) — needs confirmation from UW LEARN API docs
- Is the OAuth2 client credentials grant available for grade write scopes, or does UW require a different flow?
Option 2: LTI (Learning Tools Interoperability)
LTI embeds Chickadee inside LEARN — students launch Chickadee from within a course. This is how Akindi works. Not suitable here: it would require students to change their workflow (launch from LEARN rather than going directly to Chickadee), and it restructures the entire auth flow.
Option 3: Route through Akindi
Since Akindi already has LEARN integration, could Chickadee push grades to Akindi, which then syncs to LEARN? Not viable — Akindi's integrations are all outbound (Akindi → LMS). There is no inbound API for external systems to push grades into Akindi. Akindi is an exam grading tool, not a grade aggregation hub.
Option 4: Odyssey
UWaterloo's Odyssey system is focused on exam management, TA assignments, and graduate admissions — not course grades. Not relevant for this feature.
Recommendation
Direct D2L Valence REST API (Option 1) is the right approach. Main prerequisite: confirm the user identity field and OAuth flow from the UW LEARN API documentation before starting implementation.
Goal
Push grades directly from Chickadee to UWaterloo LEARN (Brightspace/D2L) — the same grade sync capability that tools like Akindi provide.
Options Considered
Option 1: D2L Valence REST API (recommended)
Use D2L's Valence REST API with OAuth2 client credentials (server-to-server). Instructor links each Chickadee course and assignment to the corresponding LEARN org unit and grade item, then clicks "Push to LEARN" to sync grades. Students never change their workflow.
Key endpoints:
GET /d2l/api/lp/1.48/orgstructure/?orgUnitName=<name>— look up course by nameGET /d2l/api/le/1.71/{orgUnitId}/grades/— list grade items in a coursePUT /d2l/api/le/1.71/{orgUnitId}/grades/{gradeObjectId}/values/{userId}— write a student's gradegrades:gradevalues:read,grades:gradevalues:write,core:*:*:*Design sketch:
LEARN_BASE_URL,LEARN_CLIENT_ID,LEARN_CLIENT_SECRET,LEARN_USER_ID_FIELDLEARNTokenStoreactor — caches OAuth2 bearer tokenLEARNService.swift— Valence REST calls (lookup, list, push)AddLEARNFieldsmigration —learn_org_unit_idon courses,learn_grade_object_id+learn_last_pushed_aton assignmentsgradePercentFromCollectionJSONlogicOpen questions before building:
studentID→orgDefinedId,username, orexternalSubjectfrom SSO sub claim) — needs confirmation from UW LEARN API docsOption 2: LTI (Learning Tools Interoperability)
LTI embeds Chickadee inside LEARN — students launch Chickadee from within a course. This is how Akindi works. Not suitable here: it would require students to change their workflow (launch from LEARN rather than going directly to Chickadee), and it restructures the entire auth flow.
Option 3: Route through Akindi
Since Akindi already has LEARN integration, could Chickadee push grades to Akindi, which then syncs to LEARN? Not viable — Akindi's integrations are all outbound (Akindi → LMS). There is no inbound API for external systems to push grades into Akindi. Akindi is an exam grading tool, not a grade aggregation hub.
Option 4: Odyssey
UWaterloo's Odyssey system is focused on exam management, TA assignments, and graduate admissions — not course grades. Not relevant for this feature.
Recommendation
Direct D2L Valence REST API (Option 1) is the right approach. Main prerequisite: confirm the user identity field and OAuth flow from the UW LEARN API documentation before starting implementation.