While reviewing our Feature Options today, I was excited to notice for the first time one called "GraphQL API." It's marked beta and described as "EXPERIMENTAL GraphQL API."
I know about GraphQL but couldn't find any info at all on its use in Canvas. Has anyone heard anything about this? Thanks!
Solved! Go to Solution.
Hi --
I finally had some time to update our local Canvas instance with the latest code from GitHub and I've spent a little time poking at the graphql API. First, there's a browser-based graphql console (GraphiQL) that is installed along with Canvas, but seems to only be available to users with administrator privileges on the "Site Admin" account (we have access to this in our locally-hosted development instance of Canvas, but not in our Instructure-hosted instances). The actual graphql API endpoint (/api/graphql) is accessible by regular users in our local instance.
Here's an example of a query that I managed to get to work, sent as the body of a POST request to /api/graphql:
{"query": "
{
allCourses {
id,
name,
courseCode,
state
}
}
"}
That returns a data structure with information about the courses that are on the user's dashboard. Still trying to figure out how to drill down into sections, etc...
--Colin
Thanks for getting would out that Instructure may be taking steps toward supporting a GraphQL api. I had heard about GraphQL in a talk by David Nolan, and I recognized that it could be a benefit for some of the complex queries we need to do that span over multiple endpoints. Like you I would like to find out more about how Canvas is implementing it.
MIke
Funny coincidence - I just asked our CSR about that last week - I'll update if she's able to get any info.
BTW, you can get some clues regarding how they're using graphql here: Search · org:instructure graphql · GitHub
Hey Daniel!
I'm also very interested in the GraphQL API -- I've seen a bunch of related GitHub commits and I've been meaning to make some time to experiment with it. I'm expecting to have to read some source code to figure out how to use it 🙂
BTW -- we did learn that there's some (fairly edge-case) bug that causes problems rendering student context cards in unpublished courses and/or with inactive students when the GraphQL feature flag is turned on. It seems that Instructure engineering is aware of it, and I imagine it'll be fixed soon, but we've disabled that flag in production for now.
If I do get it working, I'll share my notes here!
--Colin
Great, thanks, Colin!
Looking forward to hearing about your experiments.
After reading your post I found the experiment graphql api setting
What happens if you turn it on?
Is it an api that I can use or is it an api that canvas uses internally.
I'm interested in what I imagine is the potential here, but I know so little about the implementation that it's dangerous
Is there any schemer or endpoint documentation?
If anyone noticed that the ability to turn it on disappeared from their beta instance, it looks like it's been turned on for everyone.... and that it'll be in production possibly soon
enable graphql feature flag · instructure/canvas-lms@c35e13f · GitHub
Test plan: * make sure graphql is turned on for accounts that previously had graphql enabled and then disabled * make sure graphql can't be turned off
Hi --
I finally had some time to update our local Canvas instance with the latest code from GitHub and I've spent a little time poking at the graphql API. First, there's a browser-based graphql console (GraphiQL) that is installed along with Canvas, but seems to only be available to users with administrator privileges on the "Site Admin" account (we have access to this in our locally-hosted development instance of Canvas, but not in our Instructure-hosted instances). The actual graphql API endpoint (/api/graphql) is accessible by regular users in our local instance.
Here's an example of a query that I managed to get to work, sent as the body of a POST request to /api/graphql:
{"query": "
{
allCourses {
id,
name,
courseCode,
state
}
}
"}
That returns a data structure with information about the courses that are on the user's dashboard. Still trying to figure out how to drill down into sections, etc...
--Colin
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
}
}
]
}
}
]
}
}
}
}