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 thePOST
body, 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
variables
before 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,query
is the root operation. (If you don't specify an operation,query
is also the default.)user {
To begin the query, we want to find the user object.id
We want theid
field of theUser
object returns byuser
field, it is aInt
scalar, so it is a leaf.email
We want the
email
field of theUser
object returns byuser
field, it is aString
scalar, 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:createLiveContribution
is the name of the mutation.input
is the required argument key. This will always beinput
for 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 (liveId
andtext
in this case) for a mutation. How do we know which value to use for theliveId
and thetext
? ThecreateLiveContribution
docs tell us theliveId
field has the typeID!
and thetext
has 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
createLiveContribution
docs, which three possible return fields:id
(ID!
)contribution
(Contribution!
) In this example, we return the two required fields (id
andcontribution
), contribution has required subfields (id
andtext
). 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