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.comalias 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=20512cgql -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=20512cgql -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 } } ] } } ] } } }}