Google Docs to Forms - Formswrite.com logo
BlogPricing

Canvas API: Create Users, Courses, and Enroll Students (Code Examples)

Formswrite Team

February 15, 2026

Canvas API: Create Users, Courses, and Enroll Students (Code Examples)

Canvas API: Create Users, Courses, and Enroll Students

This guide covers the most common Canvas API operations with complete code examples: creating users, building courses, enrolling students, and managing grades.

Prerequisites

  1. A Canvas LMS instance (institutional or free teacher account)
  2. An Access Token (Account → Settings → Approved Integrations → New Access Token)
  3. Admin permissions for user creation (or use the free teacher account for course management)

Create Users

POST /api/v1/accounts/:account_id/users

Requires admin permissions.
bashcurl -X POST "https://yourschool.instructure.com/api/v1/accounts/1/users" \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "user": {
      "name": "Jane Smith",
      "short_name": "Jane",
      "sortable_name": "Smith, Jane",
      "terms_of_use": true,
      "skip_registration": true
    },
    "pseudonym": {
      "unique_id": "[email protected]",
      "password": "SecurePass123!",
      "sis_user_id": "STU-2026-001",
      "send_confirmation": false
    }
  }'

Response

json{
  "id": 142,
  "name": "Jane Smith",
  "short_name": "Jane",
  "sortable_name": "Smith, Jane",
  "email": "[email protected]",
  "login_id": "[email protected]",
  "created_at": "2026-02-15T10:30:00Z"
}

Python: Create Multiple Users

pythonimport requests

CANVAS_URL = "https://yourschool.instructure.com"
TOKEN = "your_access_token"
ACCOUNT_ID = 1

headers = {
    "Authorization": f"Bearer {TOKEN}",
    "Content-Type": "application/json"
}

students = [
    {"name": "Alice Johnson", "email": "[email protected]", "sis_id": "STU-001"},
    {"name": "Bob Williams", "email": "[email protected]", "sis_id": "STU-002"},
    {"name": "Carol Davis", "email": "[email protected]", "sis_id": "STU-003"},
]

created_users = []
for student in students:
    response = requests.post(
        f"{CANVAS_URL}/api/v1/accounts/{ACCOUNT_ID}/users",
        headers=headers,
        json={
            "user": {
                "name": student["name"],
                "terms_of_use": True,
                "skip_registration": True
            },
            "pseudonym": {
                "unique_id": student["email"],
                "password": "Welcome2026!",
                "sis_user_id": student["sis_id"],
                "send_confirmation": False
            }
        }
    )
    user = response.json()
    created_users.append(user)
    print(f"Created: {user['name']} (ID: {user['id']})")

Get All Users

GET /api/v1/accounts/:account_id/users

bashcurl "https://yourschool.instructure.com/api/v1/accounts/1/users?per_page=100" \
  -H "Authorization: Bearer YOUR_TOKEN"

Python: Search Users

python# Search by email
response = requests.get(
    f"{CANVAS_URL}/api/v1/accounts/{ACCOUNT_ID}/users",
    headers=headers,
    params={
        "search_term": "[email protected]",
        "per_page": 10
    }
)
users = response.json()

# List all users with pagination
def get_all_users():
    url = f"{CANVAS_URL}/api/v1/accounts/{ACCOUNT_ID}/users?per_page=100"
    all_users = []
    while url:
        response = requests.get(url, headers=headers)
        all_users.extend(response.json())
        links = response.headers.get("Link", "")
        url = None
        for link in links.split(","):
            if 'rel="next"' in link:
                url = link.split(";")[0].strip("<> ")
    return all_users

Create Courses

POST /api/v1/accounts/:account_id/courses

bashcurl -X POST "https://yourschool.instructure.com/api/v1/accounts/1/courses" \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "course": {
      "name": "Biology 101 - Spring 2026",
      "course_code": "BIO101-SP26",
      "start_at": "2026-01-15T00:00:00Z",
      "end_at": "2026-05-15T00:00:00Z",
      "license": "private",
      "is_public": false,
      "default_view": "modules"
    }
  }'

Python: Create Multiple Courses

pythoncourses = [
    {"name": "Biology 101", "code": "BIO101"},
    {"name": "Chemistry 201", "code": "CHEM201"},
    {"name": "Physics 301", "code": "PHYS301"},
]

for c in courses:
    response = requests.post(
        f"{CANVAS_URL}/api/v1/accounts/{ACCOUNT_ID}/courses",
        headers=headers,
        json={
            "course": {
                "name": c["name"],
                "course_code": c["code"],
                "default_view": "modules"
            },
            "offer": True  # Publish immediately
        }
    )
    course = response.json()
    print(f"Created course: {course['name']} (ID: {course['id']})")

Get All Courses

pythonresponse = requests.get(
    f"{CANVAS_URL}/api/v1/courses",
    headers=headers,
    params={"per_page": 100}
)

for course in response.json():
    print(f"{course['id']}: {course['name']} ({course.get('course_code', 'N/A')})")

Enroll Students

POST /api/v1/courses/:course_id/enrollments

Enrollment Types

TypeRole
StudentEnrollmentStudent
TeacherEnrollmentTeacher
TaEnrollmentTeaching Assistant
ObserverEnrollmentObserver
DesignerEnrollmentDesigner

cURL: Enroll a Student

bashcurl -X POST "https://yourschool.instructure.com/api/v1/courses/5/enrollments" \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "enrollment": {
      "user_id": 142,
      "type": "StudentEnrollment",
      "enrollment_state": "active",
      "notify": false
    }
  }'

Python: Bulk Enroll Students

pythoncourse_id = 5
student_ids = [142, 143, 144, 145, 146]

for uid in student_ids:
    response = requests.post(
        f"{CANVAS_URL}/api/v1/courses/{course_id}/enrollments",
        headers=headers,
        json={
            "enrollment": {
                "user_id": uid,
                "type": "StudentEnrollment",
                "enrollment_state": "active",
                "notify": False
            }
        }
    )
    enrollment = response.json()
    print(f"Enrolled user {uid}: {enrollment.get('id', 'error')}")

Enroll by SIS ID

bashcurl -X POST "https://yourschool.instructure.com/api/v1/courses/5/enrollments" \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "enrollment": {
      "user_id": "sis_user_id:STU-001",
      "type": "StudentEnrollment",
      "enrollment_state": "active"
    }
  }'

Complete Workflow: Course Setup

pythonimport requests

CANVAS_URL = "https://yourschool.instructure.com"
TOKEN = "your_token"
ACCOUNT_ID = 1
headers = {
    "Authorization": f"Bearer {TOKEN}",
    "Content-Type": "application/json"
}

# Step 1: Create the course
course = requests.post(
    f"{CANVAS_URL}/api/v1/accounts/{ACCOUNT_ID}/courses",
    headers=headers,
    json={
        "course": {
            "name": "Biology 101 - Spring 2026",
            "course_code": "BIO101",
            "default_view": "modules"
        },
        "offer": True
    }
).json()
course_id = course["id"]
print(f"Course created: {course_id}")

# Step 2: Create students
students = [
    {"name": "Alice", "email": "[email protected]"},
    {"name": "Bob", "email": "[email protected]"},
]

user_ids = []
for s in students:
    user = requests.post(
        f"{CANVAS_URL}/api/v1/accounts/{ACCOUNT_ID}/users",
        headers=headers,
        json={
            "user": {"name": s["name"], "skip_registration": True},
            "pseudonym": {"unique_id": s["email"], "password": "Welcome2026!"}
        }
    ).json()
    user_ids.append(user["id"])
    print(f"User created: {user['name']} ({user['id']})")

# Step 3: Enroll students
for uid in user_ids:
    requests.post(
        f"{CANVAS_URL}/api/v1/courses/{course_id}/enrollments",
        headers=headers,
        json={
            "enrollment": {
                "user_id": uid,
                "type": "StudentEnrollment",
                "enrollment_state": "active"
            }
        }
    )
print(f"Enrolled {len(user_ids)} students in course {course_id}")

# Step 4: Create a module
module = requests.post(
    f"{CANVAS_URL}/api/v1/courses/{course_id}/modules",
    headers=headers,
    json={"module": {"name": "Week 1: Introduction", "position": 1}}
).json()
print(f"Module created: {module['id']}")

Adding Quizzes to Your Courses

Once your course structure is set up, you'll want to add assessments. Creating quizzes through the Canvas API requires building each question individually with complex JSON — for a 50-question quiz, that's 50+ API calls.
A faster approach: use Formswrite to convert a Google Doc into a Canvas QTI package, then import it.
bash# 1. Convert Google Doc to Canvas QTI via Formswrite
curl -X POST https://api.formswrite.com/api/v1/convert \
  -H "Authorization: Bearer FORMSWRITE_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"documentId": "DOC_ID", "format": "canvas"}'

# 2. Download the QTI .zip file from the response URL

# 3. Import into Canvas via Settings → Import Course Content → QTI .zip file
This approach: write questions naturally in a Google Doc, let AI handle the conversion, and import into Canvas in seconds.

FAQ

How do I get a Canvas API access token?

Account → Settings → Approved Integrations → New Access Token. Copy it immediately — it won't be shown again.

Can I create users without admin permissions?

No. User creation requires account-level admin access. Individual teachers can manage enrollments in their own courses.

What enrollment types are available?

StudentEnrollment, TeacherEnrollment, TaEnrollment, ObserverEnrollment, and DesignerEnrollment.

Can I enroll users by email instead of user ID?

Not directly. You need the user's Canvas ID or SIS ID. Search for the user first with the users API, then enroll by ID.

Summary

The Canvas API makes it straightforward to automate user creation, course setup, and enrollments. For quiz content, pair it with Formswrite to convert Google Docs into Canvas QTI packages — significantly faster than building quizzes through the API.

Share this post with your network


Formswrite - Google Docs to Forms Converter

Create forms in seconds, not hours

Convert Google Docs to Forms with one click

Save hours on quiz creation every month.

No more manual form creation. No more formatting hassles.

We care about your data in our privacy policy

© 2026 Formswrite. All Rights Reserved.