GraphQL API
Learn about our GraphQL API and how to query and mutate OpsLevel data. You can also use the GraphiQL Explorer to interact with the API on your own OpsLevel account.
Our GraphQL API allows you to easily integrate OpsLevel with your other operational tools. You can enrich your internal tickets, incidents, and other systems with service and team data pulled from OpsLevel.
You can also use our API to automatically keep your OpsLevel info up-to-date by integrating it with real-time information pushed from tools like Terraform, Chef, Circle CI, etc. Historically, we’ve supported a YAML file integration with your git repositories for this same purpose, but our API now gives you more automation options.
What is GraphQL?
If you’ve used APIs before, you’ve probably encountered RESTful APIs. In REST, each resource generally has its own endpoint. For example, if OpsLevel had a REST API, there would be endpoints for services, teams, and users. If you wanted to fetch a list of all Services and their associated Teams, you would have to make many queries: one query to fetch the services, then one query per service to fetch the team for that service.
GraphQL works differently. GraphQL is a query language that lets clients declaratively specify what data they want to retrieve, not how it should be retrieved. With GraphQL, there is only one HTTP request that needs to be made and the response is completely customizable. GraphQL is also type safe, meaning your API client can verify that the data you’re asking for is sound. Visit the following link to see many other additional benefits of GraphQL over REST:
https://www.howtographql.com/basics/1-graphql-is-the-better-rest/
Why is OpsLevel using GraphQL for its API?
The data model for modern operations is incredibly rich and sophisticated. For example, there are dependencies between services themselves, between services and teams, teams and users, services and deployments, and deployments and infrastructure.
GraphQL is extremely well suited for clients to easily navigate this kind of rich data model. As discussed previously, GraphQL allows clients to fetch only the data they want and to do so in a single HTTP request. That leads to less bandwidth used (by only retrieving the necessary data) and less roundtrips (by not having to make a separate request per related resource).
Getting Started with the OpsLevel GraphQL API
Background
OpsLevel’s GraphQL API makes use of two high level types: queries and mutations.
Queries allow you to fetch information from OpsLevel.
Mutations allow you to push information to OpsLevel.
For more information on how to make GraphQL queries and mutations, visit https://graphql.org/learn/queries/.
Public schema
You can perform introspection against the GraphQL API directly with an account api token.
Alternatively, you can download the latest version of the public schema here: https://app.opslevel.com/public/schema.graphql
The GraphiQL Explorer
The easiest way to get started with the the OpsLevel API is with GraphiQL, an interactive environment for exploring our API and its documentation.
This explorer will allow you to easily test queries and mutations before integrating our API with your app.
The GraphiQL Explorer consists of three main components:
- Query Editor pane
- Query Response pane
- Documentation Explorer
Query Editor
Where you will be writing your GraphQL queries.
Query Response Pane
Where you will see the responses to your GraphQL queries.
Documentation Explorer
GraphQL comes with first class support for documentation. You can interact with our API documentation directly from within GraphiQL.
Note: If you do not see the Documentation Explorer, it may be closed by default and can be opened by pressing the Docs button in the top right corner.
Executing GraphQL Queries from GraphiQL
You can execute your GraphQL queries from GraphiQL by pressing the Play button after writing your query in the Query Editor.
Sample Query
To get started, try pasting the following query in the Query Editor pane (the left pane of GraphiQL):
{
account {
name
}
}
Now press the Play button. You should see this result in the Query Response pane (the middle pane of GraphiQL):
{
"data": {
"account": {
"name": "Your Account Name"
}
}
}
Pagination
OpsLevel limits query results for an object to a maximum of 100 results. If you have more than 100 objects to fetch, you will have to paginate through the result set.
Objects whose name end with ConnectionType
, such as ServiceConnectionType
, are ones that you can paginate through. Please see GraphQL Pagination for an explanation of what these connection types are, how they relate to pagination, and code examples for how to paginate. An example on using cursor-based pagination is below. (Please note that we do not support offset
.)
For example, you can use cursor-based pagination, utilizing after
and pageInfo
to get the next page of results. With the query below, you can run the query without the after
input, and then use the value from endCursor
to get the next page of results if hasNextPage
returns true
.
query pagination_with_services{
account{
services(first: 5, after: "NQ"){
totalCount
pageInfo{
hasNextPage
endCursor
}
edges{
node{
id
name
}
cursor
}
}
}
}
Returning data and errors on mutations
All OpsLevel GraphQL API mutations require you to return some payload. It is represented in the GraphQL Schema documentation by an exclamation mark (!) after the name of all mutations’ payloads.
For instance, in serviceCreate
mutation, ServiceCreatePayload
is required.
serviceCreate(input: ServiceCreateInput!): ServiceCreatePayload!
If you don’t include a return payload in your mutation, you will get an error. E.g.:
mutation {
tagDelete(input: { id:"Z2lkOi8vb3BzbGV2ZWwvVGFnLzU" })
}
Here is an example of how the mutation above should be correctly called.
mutation {
tagDelete(input: { id:"Z2lkOi8vb3BzbGV2ZWwvVGFnLzU" }) {
deletedTagId
errors {
message
}
}
}
Dealing with Errors
Always include the errors field in your mutations.
If you’re coming from the REST world, you might be expecting our API to return 4xxs for client errors. But in GraphQL, non-2xx errors only get returned for more serious issues like network failures. For client errors, we will return a 200, with more information about the error in the errors
field. You should always include the errors
field in your requests so that you can handle errors appropriately.
Here’s an example error response from the serviceUpdate
mutation:
{
"data": {
"serviceUpdate": {
"service": null,
"errors": [
{
"message": "This service is locked by a service config file.",
"path": [
"locked"
]
}
]
}
}
}
Integrating OpsLevel API into your own App
1. Create an API Token
In the OpsLevel app, navigate to the API tokens page by pressing the API link in the side menu or by navigating to https://app.opslevel.com/api_tokens.
From this page, press the + Create API Token button.
After pressing the + Create API Token button, you will be prompted to add a Token Description. Once you’ve added a description, press the Create API Token button shown below.
After your token has been created, you will be shown a confirmation modal with your new API token.
Important: You will only be shown your API token once upon creation. Store it somewhere safe. If you lose this token, it’s irrecoverable by OpsLevel.
Tokens are to be used in the Authorization
header of your request as a Bearer
or Token
.
Note: <token>
will be used in place of your actual token in all examples.
2. Make a request with curl
To test that everything is working correctly, copy and paste one of the following curl commands into your terminal and replace <token>
with the token generated in the previous section.
GraphQL query
TOKEN= # ... paste in your API token
curl -X POST \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-H "Authorization: Bearer ${TOKEN}" \
-d '{ "query": "{ account { name } }" }' \
https://api.opslevel.com/graphql
You should receive the following response:
{"data":{"account":{"name":"Your Account Name"}}}
where "Your Account Name"
is replaced with your actual account name.
GraphQL mutation
You can also apply a mutation, such as creating a new service, with the following:
TOKEN= # ... paste in your API token
curl -X POST \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-H "Authorization: Bearer ${TOKEN}" \
-d '{ "query": "mutation { serviceCreate(input:{name:\"Brand New Service\"}) { service { id name } errors { message path } } }" }' \
https://api.opslevel.com/graphql
3. Make a query with your favourite client library
Underneath it all, GraphQL APIs are built on top of HTTP, so you can use your existing HTTP libraries and tools. GraphQL is widely supported by a variety of languages and frameworks through client plugins, such as Apollo for Javascript and graphql-client for Ruby.
We also have built a golang client which is being developed in tandem with our CLI, Terraform provider and kubectl sync.
For a great list of GraphQL plugins for both server and client applications, refer to https://github.com/github/graphql-client.
GraphQL Examples
Some query and mutation examples are listed below to help you get started with GraphQL.
For more examples, see this repo here: https://github.com/OpsLevel/community-integrations/tree/main/graphql_query_examples
Querying Service Information
Query all services with their team name and manager contact info
{
account {
services {
nodes {
name
aliases
id
description
owner {
name
manager {
email
}
}
}
}
}
}
Query all services with owner, aliases, tags, tier, and repositories
{
account {
services {
nodes {
name
description
owner {
name
}
aliases
id
tags {
nodes {
key
value
}
}
tier {
alias
name
}
repositories {
totalCount
nodes {
name
defaultBranch
private
url
}
}
}
}
}
}
Query services with criteria - Ruby on Rails services
{
account {
services(language: "Ruby", framework: "Rails") {
nodes {
name
aliases
id
description
language
framework
}
}
}
}
Query services with criteria - Tagged with public-facing:true
{
account {
services(tag: {key:"public-facing", value:"true"}) {
nodes {
name
aliases
id
description
tags {
nodes {
key
value
}
}
}
}
}
}
Query a specific service by its alias
{
account {
service(alias: "shopping_cart") {
name
aliases
id
description
}
}
}
Query a specific service by ID
{
account {
service(id: "Z2lkOi8vb3BzbGV2ZWwvU2VydmljZS8xMzM") {
name
aliases
description
}
}
}
The OpsLevel API offers more queries which can be found in GraphiQL’s Docs tab.
Pushing Service Information
Registering a new service with OpsLevel
mutation {
serviceCreate(input: {
name: "New Service",
tierAlias:"tier_1",
description:"This is a description for the new service"
language: "Java",
framework: "Spring",
ownerInput: {
alias: "a-team"
}
}) {
service {
name
description
id
owner {
name
}
tier {
alias
name
}
}
errors {
message
path
}
}
}
Updating a service
Using the ID of the service
mutation {
serviceUpdate(input: { id: "Z2lkOi8vb3BzbGV2ZWwvU2VydmljZS8xMzM", name: "Updated Service Name" }) {
service {
name
}
errors {
message
path
}
}
}
Using the alias of the service
mutation {
serviceUpdate(input: { alias: "shopping_cart", name: "Updated Service Name" }) {
service {
name
}
errors {
message
path
}
}
}
Deleting a service from OpsLevel
Using the alias of the service
mutation {
serviceDelete(input: { alias: "shopping_cart" }) {
deletedServiceId
errors {
message
path
}
}
}
The OpsLevel API offers more mutations which are documented in GraphiQL’s Docs tab.
Managing Tags Information
Querying tags for a given Service
Using the ID of the service
{
account {
service(id: "Z2lkOi8vb3BzbGV2ZWwvU2VydmljZS8xMzM") {
name
tags {
nodes {
key
value
id
}
}
}
}
}
Using the alias of the service
{
account {
service(alias: "shopping_cart") {
name
tags {
nodes {
key
value
id
}
}
}
}
}
Assigning tags to a service
The tagAssign mutation is an ‘upsert’-style mutation: if a tag with the same key already exists it will be updated, otherwise a new tag will be created.
This is useful as way to easily push tags into OpsLevel without having to do a query.
Assigning Tags
mutation {
tagAssign(input: {
alias: "shopping_cart",
tags: [
{ key:"database", value:"mysql-5.8" },
{ key:"queue", value:"sidekiq" },
]
})
{
tags {
id
key
value
}
errors {
message
}
}
}
Deleting Tags
To delete a tag, you must query tags for a given service to know the id of the tag.
mutation {
tagDelete(input: { id:"Z2lkOi8vb3BzbGV2ZWwvVGFnLzU" }) {
errors {
message
}
}
}
Frequently Asked Questions
What happens if I lose my API token?
For security purposes, API tokens are irrecoverable by OpsLevel. If you lose your API token, you can delete it and create a new one.
Who else uses GraphQL?
GraphQL is gaining popularity rapidly because of the benefits it provides. Companies such as Facebook, Twitter, Shopify, GitHub, GitLab, and many many more use GraphQL today.
What is the API rate limit?
There are two levels of rate limiting in place at OpsLevel:
- IP Address Request Limit: No more than 10,000 requests every 5 mins from a single IP Address -- this limit includes OpsLevel requests outside of the GraphQL API.
- API Token Request Limit: No more than 250 API requests per minute per API token
If you exceed these limits, you will receive a 429 - Too Many Requests - status code indicating that you are being rate limited. For API Token Request Limits, we provide two request headers to help you avoid or handle being rate limited:
- RateLimit-Remaining - The number requests you have remaining before the API Token reaches the 250 request limit
- RateLimit-Retry-After - The number of seconds to wait before its safe to retry again because you'll have room left in the budget for that API Token.
What if I have more questions or suggestions?
If you have any questions, suggestions, or just want to chat, reach out to us at [email protected].
Updated 5 months ago