Scripting & Automation Tutorial¶
Learn how to automate Canvas tasks with shell scripts.
Overview¶
Canvas CLI's JSON output makes it perfect for automation:
- Integrate with shell scripts and cron jobs
- Process data with
jq - Build custom workflows
Prerequisites¶
- Canvas CLI installed and authenticated
- Basic shell scripting knowledge
jqinstalled (for JSON processing)
Basic Scripting¶
Using JSON Output¶
Always use -o json for scripting:
# Get all course IDs
canvas courses list -o json | jq '.[].id'
# Get courses as array
courses=$(canvas courses list -o json | jq -r '.[].id')
for course in $courses; do
echo "Processing course: $course"
done
Filtering with jq¶
# Find active courses
canvas courses list -o json | jq '.[] | select(.workflow_state == "available")'
# Get course names containing "CS"
canvas courses list -o json | jq '.[] | select(.name | contains("CS")) | .name'
# Count enrollments
canvas users list --course-id 123 -o json | jq length
Example Scripts¶
Export All Grades¶
Export grades for all assignments in a course:
#!/bin/bash
COURSE_ID=$1
if [ -z "$COURSE_ID" ]; then
echo "Usage: $0 <course_id>"
exit 1
fi
# Get all assignments
assignments=$(canvas assignments list --course-id $COURSE_ID -o json | jq -r '.[].id')
# Create output directory
mkdir -p grades/$COURSE_ID
# Export each assignment's submissions
for assignment in $assignments; do
echo "Exporting assignment $assignment..."
canvas submissions list \
--course-id $COURSE_ID \
--assignment-id $assignment \
-o csv > "grades/$COURSE_ID/assignment_$assignment.csv"
done
echo "Done! Grades exported to grades/$COURSE_ID/"
Bulk User Enrollment¶
Enroll users from a CSV file:
#!/bin/bash
COURSE_ID=$1
CSV_FILE=$2
if [ -z "$COURSE_ID" ] || [ -z "$CSV_FILE" ]; then
echo "Usage: $0 <course_id> <csv_file>"
exit 1
fi
# Skip header and process each line
tail -n +2 "$CSV_FILE" | while IFS=, read -r email role; do
echo "Enrolling $email as $role..."
canvas enrollments create \
--course-id $COURSE_ID \
--user-email "$email" \
--role "$role"
done
Course Health Check¶
Check course configuration and report issues:
#!/bin/bash
COURSE_ID=$1
echo "=== Course Health Check ==="
echo ""
# Get course info
course=$(canvas courses get $COURSE_ID -o json)
echo "Course: $(echo $course | jq -r '.name')"
echo "State: $(echo $course | jq -r '.workflow_state')"
echo ""
# Check modules
module_count=$(canvas modules list --course-id $COURSE_ID -o json | jq length)
echo "Modules: $module_count"
# Check assignments
assignment_count=$(canvas assignments list --course-id $COURSE_ID -o json | jq length)
echo "Assignments: $assignment_count"
# Check unpublished items
unpublished=$(canvas modules list --course-id $COURSE_ID -o json | jq '[.[] | select(.published == false)] | length')
echo "Unpublished modules: $unpublished"
# Check for missing due dates
no_due_date=$(canvas assignments list --course-id $COURSE_ID -o json | jq '[.[] | select(.due_at == null)] | length')
echo "Assignments without due date: $no_due_date"
Automated Backup¶
Back up course content daily:
#!/bin/bash
# Add to crontab: 0 2 * * * /path/to/backup.sh
BACKUP_DIR="/backups/canvas"
DATE=$(date +%Y-%m-%d)
# Get all courses
courses=$(canvas courses list -o json | jq -r '.[].id')
for course_id in $courses; do
course_name=$(canvas courses get $course_id -o json | jq -r '.name' | tr ' ' '_')
output_dir="$BACKUP_DIR/$DATE/$course_name"
mkdir -p "$output_dir"
# Export course data
canvas courses get $course_id -o json > "$output_dir/course.json"
canvas modules list --course-id $course_id -o json > "$output_dir/modules.json"
canvas assignments list --course-id $course_id -o json > "$output_dir/assignments.json"
canvas pages list --course-id $course_id -o json > "$output_dir/pages.json"
echo "Backed up: $course_name"
done
# Cleanup old backups (keep 30 days)
find $BACKUP_DIR -type d -mtime +30 -exec rm -rf {} \;
Advanced Patterns¶
Parallel Processing¶
Process multiple courses in parallel:
#!/bin/bash
# Process courses in parallel (max 4 at a time)
canvas courses list -o json | jq -r '.[].id' | \
xargs -P 4 -I {} bash -c 'process_course {}'
process_course() {
course_id=$1
canvas assignments list --course-id $course_id -o json > "course_$course_id.json"
}
export -f process_course
Error Handling¶
Robust error handling in scripts:
#!/bin/bash
set -e # Exit on error
handle_error() {
echo "Error on line $1"
exit 1
}
trap 'handle_error $LINENO' ERR
# Check if canvas CLI is available
if ! command -v canvas &> /dev/null; then
echo "Canvas CLI not found"
exit 1
fi
# Verify authentication
if ! canvas auth status &> /dev/null; then
echo "Not authenticated. Run: canvas auth login"
exit 1
fi
# Your script logic here
canvas courses list -o json
Environment-Based Configuration¶
Use different instances based on environment:
#!/bin/bash
# Set instance based on environment
case "$CANVAS_ENV" in
production)
INSTANCE="production"
;;
staging)
INSTANCE="sandbox"
;;
*)
INSTANCE="sandbox" # Default to sandbox
;;
esac
canvas courses list --instance $INSTANCE -o json
Debugging with Dry-Run Mode¶
The --dry-run flag prints the equivalent curl command instead of executing HTTP requests. This is invaluable for debugging, learning the Canvas API, and building scripts.
Basic Usage¶
# See what API call would be made
canvas --dry-run courses list
# Output:
# curl -X GET 'https://canvas.example.com/api/v1/courses' \
# -H 'Authorization: Bearer [REDACTED]' \
# -H 'Content-Type: application/json' \
# -H 'Accept: application/json' \
# -H 'User-Agent: canvas-cli/1.5.2'
Show Token for Testing¶
By default, tokens are redacted. Use --show-token to see the actual token:
Security
Only use --show-token when you need to copy the curl command for testing. Never share output containing your token.
Debug with Masquerading¶
See how masquerading affects API calls:
canvas --dry-run --as-user 12345 courses list
# Output includes the as_user_id parameter:
# curl -X GET 'https://canvas.example.com/api/v1/courses?as_user_id=12345' \
# -H 'Authorization: Bearer [REDACTED]' \
# ...
Use Cases¶
Learning the API: See exactly what endpoints and parameters Canvas CLI uses:
# See how submissions are graded
canvas --dry-run submissions grade --course-id 123 --assignment-id 456 --user-id 789 --grade "A"
Building Scripts: Generate curl commands for use in other tools:
# Generate curl command and pipe to clipboard (macOS)
canvas --dry-run --show-token courses list | pbcopy
Troubleshooting: Verify the request before it's sent:
# Check URL construction with complex options
canvas --dry-run assignments list --course-id 123 --include submissions,score_statistics
Tips¶
Test in Sandbox
Always test scripts against a sandbox instance before running on production.
Rate Limiting
Canvas CLI handles rate limiting automatically, but for large batch operations, consider adding delays.
Logging
Add timestamps and logging for long-running scripts:
Credentials
Never hardcode tokens in scripts. Use environment variables or the config file.