Google Docs to Forms - Formswrite.com logo
BlogPricing

Canvas API: Complete Guide with Examples (REST, Authentication, Endpoints)

Formswrite Team

February 15, 2026

Canvas API: Complete Guide with Examples (REST, Authentication, Endpoints)

Canvas API: Complete Guide with Examples

The Canvas REST API is one of the most comprehensive LMS APIs available. It gives you full programmatic access to courses, users, enrollments, assignments, quizzes, grades, and nearly every feature in Canvas LMS.
This guide covers authentication, key endpoints, and working code examples.

API Overview

PropertyValue
Base URLhttps://yourschool.instructure.com/api/v1
ProtocolREST over HTTPS
AuthenticationBearer token (Access Token)
Response FormatJSON
PaginationLink header-based
Rate Limit700 requests per 10 minutes

Canvas API Authentication

Generate an Access Token

  1. Log in to Canvas
  2. Go to AccountSettings
  3. Scroll to Approved Integrations
  4. Click "+ New Access Token"
  5. Enter a purpose (e.g., "API Integration") and optional expiry
  6. Click "Generate Token"
  7. Copy the token immediately — it won't be shown again

Use the Token

bash# Authorization header (recommended)
curl -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  https://yourschool.instructure.com/api/v1/courses

Key Canvas API Endpoints

Courses

MethodEndpointDescription
GET/api/v1/coursesList your courses
GET/api/v1/courses/:idGet a specific course
POST/api/v1/accounts/:account_id/coursesCreate a course
PUT/api/v1/courses/:idUpdate a course
DELETE/api/v1/courses/:idDelete/conclude a course

Users

MethodEndpointDescription
GET/api/v1/users/selfGet current user
GET/api/v1/accounts/:id/usersList users in account
POST/api/v1/accounts/:id/usersCreate a user
PUT/api/v1/users/:idUpdate a user

Enrollments

MethodEndpointDescription
GET/api/v1/courses/:id/enrollmentsList enrollments
POST/api/v1/courses/:id/enrollmentsEnroll a user
DELETE/api/v1/courses/:id/enrollments/:idRemove enrollment

Assignments

MethodEndpointDescription
GET/api/v1/courses/:id/assignmentsList assignments
GET/api/v1/courses/:id/assignments/:idGet assignment details
POST/api/v1/courses/:id/assignmentsCreate an assignment
PUT/api/v1/courses/:id/assignments/:idUpdate an assignment

Quizzes

MethodEndpointDescription
GET/api/v1/courses/:id/quizzesList quizzes
GET/api/v1/courses/:id/quizzes/:idGet quiz details
POST/api/v1/courses/:id/quizzesCreate a quiz
GET/api/v1/courses/:id/quizzes/:id/questionsList quiz questions
POST/api/v1/courses/:id/quizzes/:id/questionsAdd a question

Submissions & Grades

MethodEndpointDescription
GET/api/v1/courses/:id/assignments/:id/submissionsList submissions
PUT/api/v1/courses/:id/assignments/:id/submissions/:user_idGrade a submission

Modules

MethodEndpointDescription
GET/api/v1/courses/:id/modulesList modules
POST/api/v1/courses/:id/modulesCreate a module
POST/api/v1/courses/:id/modules/:id/itemsAdd item to module

Code Examples

Python: List All Courses

pythonimport requests

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

headers = {"Authorization": f"Bearer {TOKEN}"}

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

courses = response.json()
for course in courses:
    print(f"{course['id']}: {course['name']}")

Python: Create a User

pythonresponse = requests.post(
    f"{CANVAS_URL}/api/v1/accounts/1/users",
    headers=headers,
    json={
        "user": {
            "name": "Jane Smith",
            "short_name": "Jane",
            "sortable_name": "Smith, Jane"
        },
        "pseudonym": {
            "unique_id": "[email protected]",
            "password": "SecurePass123!"
        }
    }
)

user = response.json()
print(f"Created user: {user['id']} - {user['name']}")

Python: Enroll a User in a Course

pythonresponse = requests.post(
    f"{CANVAS_URL}/api/v1/courses/5/enrollments",
    headers=headers,
    json={
        "enrollment": {
            "user_id": user["id"],
            "type": "StudentEnrollment",
            "enrollment_state": "active"
        }
    }
)

print(f"Enrolled: {response.json()['id']}")

Node.js: List Assignments

javascriptconst CANVAS_URL = 'https://yourschool.instructure.com';
const TOKEN = process.env.CANVAS_TOKEN;

async function getAssignments(courseId) {
  const response = await fetch(
    `${CANVAS_URL}/api/v1/courses/${courseId}/assignments?per_page=100`,
    { headers: { 'Authorization': `Bearer ${TOKEN}` } }
  );
  return response.json();
}

const assignments = await getAssignments(5);
assignments.forEach(a => console.log(`${a.id}: ${a.name} (${a.points_possible} pts)`));

cURL: Create a Quiz

bashcurl -X POST "https://yourschool.instructure.com/api/v1/courses/5/quizzes" \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "quiz": {
      "title": "Chapter 5 Quiz",
      "description": "Test your knowledge of Chapter 5",
      "quiz_type": "assignment",
      "time_limit": 30,
      "allowed_attempts": 2,
      "scoring_policy": "keep_highest",
      "published": false
    }
  }'

Handling Pagination

Canvas uses Link header pagination. When a response has more pages, the Link header contains the next page URL.
pythondef get_all_pages(url, headers):
    results = []
    while url:
        response = requests.get(url, headers=headers)
        results.extend(response.json())
        # Parse Link header for next page
        links = response.headers.get('Link', '')
        url = None
        for link in links.split(','):
            if 'rel="next"' in link:
                url = link.split(';')[0].strip('<> ')
    return results

all_users = get_all_pages(
    f"{CANVAS_URL}/api/v1/courses/5/users?per_page=100",
    headers
)

Rate Limits

Canvas enforces a rate limit of 700 requests per 10 minutes per user. The response headers include:
HeaderDescription
X-Rate-Limit-RemainingRequests remaining in current window
X-Request-CostCost of the current request
If you hit the limit, Canvas returns a 403 Forbidden with a Retry-After header.

Creating Quizzes: Canvas API vs Formswrite

Creating quizzes through the Canvas API requires multiple API calls — one to create the quiz, then one per question, with each question requiring answer options. For a 50-question quiz, that's 50+ API calls with complex JSON payloads.
Formswrite offers a much simpler alternative:
ApproachSteps for 50-Question Quiz
Canvas API50+ API calls with complex JSON for each question
Formswrite1 API call → download QTI → import into Canvas
bash# Formswrite: Convert Google Doc to Canvas QTI
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"}'
The AI reads your Google Doc, extracts all questions, and generates a valid QTI package that Canvas imports directly.

Canvas API Documentation


FAQ

How do I get a Canvas API token?

Go to AccountSettingsApproved Integrations"+ New Access Token". Copy the token immediately.

What is the Canvas API rate limit?

700 requests per 10 minutes per user. Monitor the X-Rate-Limit-Remaining response header.

Can I create quiz questions via the Canvas API?

Yes, using POST /api/v1/courses/:id/quizzes/:id/questions, but it requires complex JSON for each question. For bulk quiz creation, Formswrite is significantly faster.

Is the Canvas API free?

Yes. The API is included with any Canvas LMS instance, including the free teacher version.

Does Canvas support GraphQL?

Yes. Canvas has a GraphQL API alongside the REST API, primarily used for analytics and reporting.

Summary

The Canvas REST API is comprehensive and well-documented. For user and course management, it's excellent. For quiz creation specifically, pair it with Formswrite to convert Google Docs into Canvas QTI packages — saving dozens of API calls per quiz.

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.