Forming calls with GraphQL
Learn how to authenticate to the GraphQL API, then learn how to create and run queries and mutations.
Authenticating with GraphQL
To communicate with the GraphQL server, you'll need a user token.
Follow the steps in "Creating a personal access token" to create a token. The token is linked to your user account.
The GraphQL endpoint
The REST API has numerous endpoints; the GraphQL API has a single endpoint:
https://*.sirius.press/api/public/graphql
The endpoint remains constant no matter what operation you perform.
Communicating with GraphQL
Because GraphQL operations consist of multiline JSON, Sirius recommends using the Explorer available at the GraphQL endpoint to make GraphQL calls. You can also use cURL or any other HTTP-speaking library.
In REST, HTTP verbs determine the operation performed. In GraphQL, you'll provide a JSON-encoded body whether you're performing a query or a mutation, so the HTTP verb is POST.
To query GraphQL using cURL, make a POST request with a JSON payload. The payload must contain a string called query:
curl -H "Authorization: bearer token" -X POST -d " \\{ \\\\"query\\": \\"query { user { email }}\\" \\} \\" https://*.sirius.press/api/public/graphql
Note: The string value of
"query"must escape newline characters or the schema will not parse it correctly. For thePOSTbody, use outer double quotes and escaped inner double quotes.
About query and mutation operations
The two types of allowed operations in GraphQL API are queries and mutations. Comparing GraphQL to REST, queries operate like GET requests, while mutations operate like POST/PATCH/DELETE. The mutation name determines which modification is executed.
For information about rate limiting, see "Rate limiting."
Queries and mutations share similar forms, with some important differences.
About queries
GraphQL queries return only the data you specify. To form a query, you must specify fields within fields (also known as nested subfields) until you return only scalars.
Queries are structured like this:
query { JSON objects to return }
For a real-world example, see "Example query."
About mutations
To form a mutation, you must specify three things:
- Mutation name. The type of modification you want to perform.
- Input object. The data you want to send to the server, composed of input fields. Pass it as an argument to the mutation name.
- Payload object. The data you want to return from the server, composed of return fields. Pass it as the body of the mutation name. Mutations are structured like this:
mutation {mutationName(input: {MutationNameInput!}) {MutationNamePayload}}
The input object in this example is MutationNameInput, and the payload object is MutationNamePayload.
In the mutations reference, the listed input fields are what you pass as the input object. The listed return fields are what you pass as the payload object.
For a real-world example, see "Example mutation."
Working with variables
Variables can make queries more dynamic and powerful, and they can reduce complexity when passing mutation input objects.
Note: If you're using the Explorer, make sure to enter variables in the separate query variables pane, and do not include the word
variablesbefore the JSON object.
Example query
Let's walk through a more complex query and put this information in context.
The following query looks up the logged in user email:
query {user {id}}
Looking at the composition line by line:
query {Because we want to read data from the server, not modify it,queryis the root operation. (If you don't specify an operation,queryis also the default.)user {To begin the query, we want to find the user object.idWe want theidfield of theUserobject returns byuserfield, it is aIntscalar, so it is a leaf.emailWe want the
emailfield of theUserobject returns byuserfield, it is aStringscalar, so it is a leaf.
Example mutation
Mutations often require information that you can only find out by performing a query first. This example shows two operations:
- A query to get an issue ID.
- A mutation to add an emoji reaction to the issue.
mutation ($liveId: Int!, $text: String!) {createLiveContribution(input: { liveId: $liveId, text: $text }) {idcontribution {idtext}}}
Looking at the composition line by line:
mutation($liveId: ID!, $text: String!) {Here we're performing a mutation. Two variables are specified:$liveId: ID!and$text: String!. The variables type should match the expected input type.createLiveContribution(input: { liveId: $liveId, text: $text }) {Let's examine this line:createLiveContributionis the name of the mutation.inputis the required argument key. This will always beinputfor a mutation.{ liveId: $liveId, text: $text }is the required argument value. This will always be an input object (hence the curly braces) composed of input fields (liveIdandtextin this case) for a mutation. How do we know which value to use for theliveIdand thetext? ThecreateLiveContributiondocs tell us theliveIdfield has the typeID!and thetexthas the typeString!. The!means that the value cannot be ommitted or null.
- The rest of the call is composed of the payload object. This is where we specify the data we want the server to return after we've performed the mutation. These lines come from the
createLiveContributiondocs, which three possible return fields:id(ID!)contribution(Contribution!) In this example, we return the two required fields (idandcontribution), contribution has required subfields (idandtext). When we run the mutation, this is the response:
{"data": {"createLiveContribution": {"id": "2399","contribution": {"id": "1203","text": "HOORAY"}}}}
Rate limiting
A rate limit is the number of API calls user can make within a given time period. If this limit is exceeded requests will fail.
Use the HTTP headers in order to understand where the application is at for a given rate limit.
X-RateLimit-Limit: the rate limit ceiling (default: 10000)X-RateLimit-Remaining: the number of requests left for the minute windowX-RateLimit-Reset: the remaining window before the rate limit resets, in seconds
When a user exceeds the rate limit, the API will return a HTTP 429 “Too Many Requests” response code
Further reading
There is a lot more you can do when forming GraphQL calls. Here are some places to look next:
Edit this page on GitHub