That's really interesting - I had been thinking about graphql as a being an admin tool, i.e. being able to write a generic query for a user's courses or whatever, but it seems like it's limited to retrieving info for the specific user that is authenticated against it (unlike how the rest api will let an admin user query all courses, users, etc)
For people that want to poke with a command line, here's a quick recipe (using bash & jq)
bash is easy enough to get going with - set up an alias (replace `generate~your~token` & `yourCanvasServerName` natch):
gqltoken=[generate~your~token]
instance=https://yourCanvasServerName.instructure.com
alias cgql="curl -H \"Authorization: Bearer $gqltoken\" -X POST $instance/api/graphql -H \"Content-Type: application/json\""
then here's Colin's example as a one-liner piped to jq for easy readability (note: subbing _id for id will give you the canvas id of the courses)
cgql -d "{\"query\": \"{ allCourses {_id,name,courseCode,state}}\"}" | jq
you can help your explorations a bit using graphql introspection to get a list of types:
cgql -d "{\"query\": \" { __schema {types{name}}} \"}" | jq '.data.__schema.types | .[] | .name'
You can get information on a single course using legacyNode(type:Course,_id: xxx):
{
legacyNode(type: Course, _id: 20512) {
... on Course {
_id
name
}}}
Here's how to get some course information:
Enrollments is userConnection > edges > node > fieldnames
{
legacyNode(type: Course, _id: 20512) {
... on Course {
_id
name
usersConnection {
edges {
node {
name
_id
email
}}}}}}
or as a one-liner (well, a two-liner so the variable is replaceable)
course_id=20512
cgql -d "{\"query\": \" {legacyNode(type:Course,_id:$course_id){... on Course{_id name usersConnection{edges{node{name _id email}}}}}} \"}"
Sections are similar:
{
legacyNode(type: Course, _id: 20512) {
... on Course {
_id
name
sectionsConnection {
edges {
node {
name
_id
createdAt
updatedAt
}}}}}}
or
course_id=20512
cgql -d "{\"query\": \" {legacyNode(type:Course,_id:$course_id){... on Course{_id name sectionsConnection{edges{node{name _id createdAt updatedAt}}}}}} \"}" | jq
Pretty much all of the xConnection types seem to follow that basic pattern and you can end up getting pretty specific results putting it all together - here's an example that get's a single course via it's course id and get's the current user's permissions, plus the course users with grades and analytics :
{
legacyNode(type: Course, _id: 20512) {
... on Course {
_id
name
permissions {
become_user: becomeUser
manage_grades: manageGrades
send_messages: sendMessages
view_all_grades: viewAllGrades
view_analytics: viewAnalytics
}
usersConnection {
edges {
node {
name
email
analytics: summaryAnalytics(courseId: 20512) {
page_views: pageViews {
total
max
level
}
participations {
total
max
level
}
tardiness_breakdown: tardinessBreakdown {
late
missing
on_time: onTime
}
}
enrollments(courseId: 20512) {
last_activity_at: lastActivityAt
section {
name
}
grades {
current_grade: currentGrade
current_score: currentScore
}
}
}
}
}
}
}
}
Sample Output (side note - I'm am still thrilled when emoji don't break apis):
{
"data": {
"legacyNode": {
"_id": "20512",
"name": " Dank Memes and Dark Dreams",
"permissions": {
"become_user": true,
"manage_grades": true,
"send_messages": true,
"view_all_grades": true,
"view_analytics": true
},
"usersConnection": {
"edges": [
{
"node": {
"name": "Test Student",
"email": null,
"analytics": {
"page_views": {
"total": 3,
"max": 67,
"level": 2
},
"participations": {
"total": 0,
"max": 0,
"level": 0
},
"tardiness_breakdown": {
"late": 0,
"missing": 0,
"on_time": 2
}
},
"enrollments": [
{
"last_activity_at": "2017-05-02T15:14:46-04:00",
"section": {
"name": "Dank Memes ⚙♻️ "
},
"grades": {
"current_grade": null,
"current_score": 63.5
}
}
]
}
}
]
}
}
}
}