# Canvas LMS Integration The B12 SIS integrates with Instructure Canvas LMS for course management, assignments, grades, and user synchronization. ## Overview The Canvas integration supports: - **User Sync**: Students and teachers sync to Canvas users - **Course Sync**: SIS courses create/update Canvas courses - **Enrollment Sync**: Student/teacher enrollments sync to Canvas - **Assignment Sync**: Canvas assignments import to SIS assessments - **Grade Sync**: Assessment results sync from Canvas gradebook - **Blueprint Courses**: Course templates from Canvas blueprints ## Configuration ### Environment Variables ```bash # Canvas API Configuration CANVAS_API_URL=https://canvas.yourschool.edu CANVAS_API_TOKEN=your-api-token CANVAS_ACCOUNT_ID=1 CANVAS_SYNC_ENABLED=true # Sync Options CANVAS_SYNC_BATCH_SIZE=100 CANVAS_SYNC_DRY_RUN=false ``` ### Getting an API Token 1. Log into Canvas as an admin 2. Go to Account > Settings 3. Click "New Access Token" 4. Set expiration and save the token !!! warning "Token Security" Store the API token securely. Never commit it to version control. ## Sync Architecture ``` ┌─────────────────────────────────────────────────────────────┐ │ B12 SIS │ │ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────────────┐ │ │ │ Student │ │ Course │ │ Enroll │ │ Assessment │ │ │ │ Model │ │ Model │ │ Model │ │ Result Model │ │ │ └────┬────┘ └────┬────┘ └────┬────┘ └────────┬────────┘ │ │ │ │ │ │ │ │ ▼ ▼ ▼ ▲ │ │ ┌─────────────────────────────────────────────────────────┐│ │ │ Canvas Hooks ││ │ │ AfterSave → SyncIfNeeded → Canvas API Client ││ │ └─────────────────────────────────────────────────────────┘│ └─────────────────────────────────┬───────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────────┐ │ Canvas LMS │ │ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────────────┐ │ │ │ Users │ │ Courses │ │ Enroll │ │ Assignments │ │ │ └─────────┘ └─────────┘ └─────────┘ └─────────────────┘ │ └─────────────────────────────────────────────────────────────┘ ``` ## User Synchronization ### Student Sync When a student is created/updated in SIS: 1. `AfterSave` hook triggers 2. Check if `need_canvas_sync = true` 3. Create/update Canvas user via API 4. Store `lms_id` in student record 5. Set `need_canvas_sync = false` **Student → Canvas User Mapping:** | SIS Field | Canvas Field | |-----------|--------------| | `email` | `login_id`, `email` | | `first_name` | `name` (part) | | `last_name` | `sortable_name` (part) | | `code` | `sis_user_id` | ### Teacher Sync Similar to student sync, teachers sync to Canvas users with appropriate roles. ### Manual Sync Trigger Force sync a student: ```bash curl -X POST http://localhost:8080/api/students/:id/force-sync-canvas \ -H "Authorization: Bearer $TOKEN" \ -H "X-Team-ID: $TEAM_ID" ``` ## Course Synchronization ### Course Creation When a course is created in SIS: 1. Create Canvas course in the configured account 2. Store `canvas_id` in SIS course 3. Apply blueprint association if course template specified **Course → Canvas Course Mapping:** | SIS Field | Canvas Field | |-----------|--------------| | `name` | `name` | | `code` | `course_code`, `sis_course_id` | | `status` | `workflow_state` | ### Blueprint Courses Course templates sync from Canvas blueprints: 1. Blueprint courses in Canvas are tagged 2. Sync job imports blueprints as `CourseTemplate` records 3. New courses can be associated with templates 4. Template changes push to associated courses **Sync Blueprint Courses:** ```bash curl -X POST http://localhost:8080/api/course_templates/sync-canvas \ -H "Authorization: Bearer $TOKEN" \ -H "X-Team-ID: $TEAM_ID" ``` ## Enrollment Synchronization ### Student Enrollment When a student enrolls in a course: 1. `StudentEnrollCourse` created in SIS 2. Hook triggers Canvas enrollment creation 3. Store `canvas_enrollment_id` in SIS **Enrollment States:** | SIS Status | Canvas State | |------------|--------------| | `active` | `active` | | `invited` | `invited` | | `completed` | `completed` | | `inactive` | `inactive` | ### Teacher Enrollment Primary teachers enroll as `TeacherEnrollment`: ```go // Course model tracks teacher enrollment PrimaryTeacherEnrollCanvasId string NeedPrimaryTeacherEnrollCanvasSync bool ``` ## Assignment & Grade Sync ### Import Assignments Canvas assignments import to SIS assessments: **Sync Job:** `CanvasSyncAssignmentsJob` ```bash make run-job JOB=CanvasSyncAssignmentsJob ``` **Assignment → Assessment Mapping:** | Canvas Field | SIS Field | |--------------|-----------| | `id` | `canvas_assignment_id` | | `name` | `name` | | `due_at` | `due_date` | | `points_possible` | `max_score` | | `submission_types` | `type` | ### Import Grades Canvas submission grades import to SIS: **Sync Job:** `CanvasSyncGradesJob` Imports: - `score` → `AssessmentResult.score` - `grade` → `AssessmentResult.grade` - `submitted_at` → `AssessmentResult.submitted_at` - `graded_at` → `AssessmentResult.graded_at` ### Force Sync Student Assessments Trigger grade sync for a specific student: ```bash curl -X POST http://localhost:8080/api/students/:id/force-sync-canvas-assessments \ -H "Authorization: Bearer $TOKEN" \ -H "X-Team-ID: $TEAM_ID" ``` ## Background Jobs ### CanvasSyncJob Master sync job that coordinates all sync operations: - **Schedule:** Every hour - **Operations:** Users, courses, enrollments ### CanvasSyncCourseEnrollmentsJob Syncs course enrollments: - **Schedule:** Every 30 minutes - **Handles:** New enrollments, updates, deletions ### CanvasBlueprintSyncJob Syncs blueprint/template courses: - **Schedule:** Daily at 2 AM - **Handles:** Blueprint imports, associations ### Running Jobs Manually ```bash # Run specific job make run-job JOB=CanvasSyncJob # List all jobs make list-jobs ``` ## API Endpoints ### Course Template Endpoints | Endpoint | Description | |----------|-------------| | `GET /api/course_templates/blueprint` | Get blueprint courses | | `GET /api/course_templates/sync-status` | Get sync status | | `GET /api/course_templates/failed-syncs` | Get failed syncs | | `POST /api/course_templates/sync-canvas` | Trigger sync | ### Canvas Data Endpoints | Endpoint | Description | |----------|-------------| | `GET /api/canvas_assignments/list` | List imported assignments | | `GET /api/canvas_modules/list` | List imported modules | | `GET /api/canvas_module_items/list` | List module items | ## Error Handling ### Sync Errors Failed syncs are logged and can be retried: ```json { "id": "sync-error-uuid", "entity_type": "Student", "entity_id": "student-uuid", "operation": "create_user", "error": "Canvas API error: email already exists", "retry_count": 3, "last_attempt": "2024-01-15T10:30:00Z" } ``` ### Viewing Sync Errors ```bash curl http://localhost:8080/api/course_templates/failed-syncs \ -H "Authorization: Bearer $TOKEN" \ -H "X-Team-ID: $TEAM_ID" ``` ### Common Errors | Error | Cause | Solution | |-------|-------|----------| | `user already exists` | Duplicate email | Update existing user | | `course not found` | Invalid canvas_id | Re-sync course | | `enrollment exists` | Duplicate enrollment | Skip or update | | `rate limit exceeded` | Too many API calls | Reduce batch size | ## Password Synchronization Optional feature to sync passwords: 1. Enable in settings 2. When student password changes in SIS 3. Update Canvas login credentials 4. Notify student of change !!! warning "Security" Password sync should only be enabled for managed accounts. External SSO accounts should not sync passwords. ## Monitoring ### Sync Status Dashboard Monitor sync health: ```bash curl http://localhost:8080/api/course_templates/sync-status \ -H "Authorization: Bearer $TOKEN" ``` Response: ```json { "success": true, "data": { "last_sync": "2024-01-15T10:00:00Z", "status": "completed", "stats": { "users_synced": 150, "courses_synced": 25, "enrollments_synced": 500, "errors": 3 } } } ``` ### Job Logs ```bash curl -X POST http://localhost:8080/api/job_logs/list \ -H "Authorization: Bearer $TOKEN" \ -H "X-Team-ID: $TEAM_ID" \ -H "Content-Type: application/json" \ -d '{ "filter": { "conditions": [ {"field": "job_name", "operator": "contains", "value": "Canvas"} ] } }' ``` ## Best Practices 1. **Test in Sandbox**: Use Canvas sandbox for testing 2. **Batch Operations**: Use batch APIs for large syncs 3. **Monitor Logs**: Check job logs regularly 4. **Handle Failures**: Implement retry logic for transient failures 5. **Unique Identifiers**: Use SIS IDs for reliable matching 6. **Rate Limits**: Respect Canvas API rate limits (700 req/10 min)