# API

{% embed url="<https://api-docs.instruqt.com/#definition-TrackInvite>" %}

### What is the GraphQL API?

The Instruqt GraphQL API lets you exchange data between your systems and the Instruqt platform. As the name suggests, the API is based on [GraphQL](https://graphql.org/), a query language for APIs. GraphQL lets you query and update data with queries and mutations in JSON format. This means that you can do the following actions with the Instruqt GraphQL API:

* Query for information about Instruqt artifacts like tracks and challenges.
* Add Instruqt artifacts like track invites or team members.
* Update Instruqt artifacts, including deleting them.

The query response is in [JSON](https://www.json.org/json-en.html) format, and the following is an example of a GraphQL query that lists all your tracks by `id`, `slug` and `title`:

{% tabs %}
{% tab title="GraphQL" %}

```graphql
query {
    tracks(organizationSlug: \"instruqt\") {
      id
      slug
      title
    }
}
```

{% endtab %}
{% endtabs %}

Which gives a response like this:

{% tabs %}
{% tab title="JSON" %}

```json
{
    "data": {
        "tracks": [
            {
                "id": "amy5xhuaxukc",
                "slug": "aws-cloud-account",
                "title": "AWS Cloud Account"
            },
            {
                "id": "jrwu2g1tymzn",
                "slug": "azure-subscription",
                "title": "Azure subscription"
            },
            {
                "id": "4ttuxz0fgyf1",
                "slug": "gcp-project",
                "title": "GCP project"
            },
            {
                "id": "vnt0zc9owl5c",
                "slug": "kubernetes",
                "title": "Kubernetes"
            }
        ]
    }
}
```

{% endtab %}
{% endtabs %}

### Why would you use the GraphQL API?

The API is based on GraphQL, so you can form your own queries and are not bound to predefined requests and responses with unnecessary data. Furthermore, you can access the API from any modern programming language and software like Excel and Zapier.

Here are some possible scenarios:

* You can extract a list with participant IDs from Instruqt.
* You can add an Excel list with new team members to Instruqt.
* You can add a JSON file with track invites to Instruqt.

## How to use the GraphQL API

### Address the API Endpoint

You address all your GraphQL queries and mutations as HTTP `POST` requests to an API Endpoint. The GraphQL API Endpoint for Instruqt is:

<table><thead><tr><th width="152.16438356164383">Method</th><th width="492.02525493402374">Endpoint</th></tr></thead><tbody><tr><td><img src="https://2094212015-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MGJDYBXyftBAZb1Wq0e%2Fuploads%2FJ7xVpnAYQabwwtigzG4t%2Fimage.png?alt=media&#x26;token=90d161d9-fd09-4922-a0aa-699f6924a084" alt="" data-size="line"></td><td><code>https://play.instruqt.com/graphql</code></td></tr></tbody></table>

### Create your API key for authorization

Instruqt GraphQL API requires your queries and mutations to be authorized by an API key. Take the following steps to create your API key:

{% tabs %}
{% tab title="🌐 Web UI" %}

1. Click **Settings** → **API keys**.
2. Click **Generate API Key**.
3. Click **Copy to clipboard.**\
   ↳ You can apply the key now. You do that by passing the key to the HTTP request `Authorization: Bearer` parameter of your GraphQL query request.
   {% endtab %}
   {% endtabs %}

### Explore the API

Before you create queries and mutations, you should get familiar with the available queries and mutations and find the ones you need for your task—for example, list all tracks. You can explore the queries and mutations with the following resources:

* The GraphQL Playground desktop app
* The [Instruqt API Reference](https://api-docs.instruqt.com/)

Instruqt recommends [GraphQL Playground](https://github.com/prisma/graphql-playground), a GraphQL IDE that lets you explore an API and allows you to experiment with queries and mutations. You can [download](https://github.com/graphql/graphql-playground) GraphQL and install it as a desktop app. Follow the installation instructions, start GraphQL Playground, and then:

{% tabs %}
{% tab title="GraphQL Playground" %}

1. Add the following HTTP header:

   ```json
   {"Authorization": "Bearer YOUR_API_KEY"}
   ```

   ⇨ Replace `YOUR_API_KEY` with the copied key.
2. In the **Endpoint** field, enter `https://play.instruqt.com/graphql`.
3. Click the **Docs** tab.\
   ↳ A list with *QUERIES* and *MUTATIONS* opens.
4. Browse through the queries and mutations to get familiar with them—for example, scroll to the `tracks` query and click the lemma for more information.
5. Notice the *TYPE DETAILS*, listing track properties like `id`, `slug` and `title`.

{% hint style="info" %}
**Mandatory properties**

Properties trailed with a ! are non-nullable and mandatory in queries and mutations.
{% endhint %}
{% endtab %}
{% endtabs %}

You can also check the [API reference](https://api-docs.instruqt.com). This reference contains the same information as the GraphQL Playground in a different format.

### Create and run queries

#### List all your tracks and their play count

Now you are ready to create and run queries. First, let's create and run a query that lists all your tracks by `id`, `slug` , `title` and `play_count`:

{% tabs %}
{% tab title="Curl" %}

1. Open a terminal and run the following curl example:
2. ```bash
   cat >query.json <<EOF
   {
     "query": "query {
       tracks(organizationSlug: \"TEAM\") {
         id
         slug
         title
         play_count
       }
     }"
   }
   EOF

   curl -H "Authorization: Bearer YOUR_API_KEY" -X POST -d @query.json https://play.instruqt.com/graphql
   ```

   ⇨ Replace `TEAM` with your team and `YOUR_API_KEY` with the copied key.
   {% endtab %}

{% tab title="Python" %}

```python
import requests

api_key = "YOUR_API_KEY"
endpoint = f"https://play.instruqt.com/graphql"

query = """query {
    tracks(organizationSlug: \"TEAM\") {
      id
      slug
      title
      play_count
    }
}"""

response = requests.post(endpoint, headers={"Authorization": "Bearer " + api_key}, json={"query": query})
print(response.json())
```

⇨ Replace `TEAM` with your team and `YOUR_API_KEY` with the copied key.
{% endtab %}
{% endtabs %}

You will get a response like this:

{% tabs %}
{% tab title="JSON" %}

```json
{
    "data": {
        "tracks": [
            {
                "id": "amy5xhuaxukc",
                "slug": "aws-cloud-account",
                "title": "AWS Cloud Account",
                "play_count": 52
            },
            {
                "id": "jrwu2g1tymzn",
                "slug": "azure-subscription",
                "title": "Azure subscription",
                "play_count": 29
            },
            {
                "id": "4ttuxz0fgyf1",
                "slug": "gcp-project",
                "title": "GCP project",
                "play_count": 94                
            },
            {
                "id": "vnt0zc9owl5c",
                "slug": "kubernetes",
                "title": "Kubernetes",
                "play_count": 201                
            }
        ]
    }
}
```

{% endtab %}
{% endtabs %}

#### List challenges in a track and how many times they were started and completed

Next, let's list the challenges in the Kubernetes track with track ID `vnt0zc9owl5c` and see how many times the challenges were started and finished:

{% tabs %}
{% tab title="Curl" %}

1. Open a terminal and run the following curl example:
2. ```bash
   cat >query.json <<EOF
   {
     "query": "query {
       challenges(trackID: \"vnt0zc9owl5c\") {
         id
         title
         started
         completed
       }
     }"
   }
   EOF

   curl -H "Authorization: Bearer YOUR_API_KEY" -X POST -d @query.json https://play.instruqt.com/graphql
   ```

{% endtab %}

{% tab title="Python" %}

```python
import requests

api_key = "YOUR_API_KEY"
endpoint = f"https://play.instruqt.com/graphql"

query = """query {
    challenges(trackID: "vnt0zc9owl5c") {
      id
      title
      started
      completed
    }
}"""

response = requests.post(endpoint, headers={"Authorization": "Bearer " + api_key}, json={"query": query})
print(response.json())
```

{% endtab %}
{% endtabs %}

And the response will be something like this:

{% tabs %}
{% tab title="JSON" %}

```json
{
    "data": {
        "challenges": [
            {
                "id": "gbgigh8crymk",
                "title": "Deploy NGINX",
                "started": 173,
                "completed": 173
            },
            {
                "id": "1xajyu6cyyyz",
                "title": "Expose the NGINX service",
                "started": 173,
                "completed": 124                
            },
            {
                "id": "8dxweetsxxox",
                "title": "Viewing NGINX",
                "started": 124,
                "completed": 108                
            },
            {
                "id": "h6ejfdyevgqx",
                "title": "Kubernetes Dashboard"
                "started": 108,
                "completed": 108                
            }
        ]
    }
}
```

{% endtab %}
{% endtabs %}

### Create and run mutations

#### Add a track invite

First, head over to GraphQL Playground, search for the `createTrackInvite` mutation, and inspect the details.

Next, create the mutation to add a track invite:

{% tabs %}
{% tab title="Curl" %}

1. Open a terminal and run the following curl example:
2. ```bash
   cat >query.json <<EOF
   {
     "query": "mutation {
        createTrackInvite(invite: {title: \"New invites from ACorp\", trackIDs:[\"TRACK-ID\"], allowAnonymous: true}) {
          id
          title
        }
     }"
   }
   EOF

   curl -H "Authorization: Bearer YOUR_API_KEY" -X POST -d @query.json https://play.instruqt.com/graphql
   ```

   ⇨ Replace `TRACK-ID` with your track ID and `YOUR_API_KEY` with the copied key. You can also enter your title.
   {% endtab %}

{% tab title="Python" %}

```python
import requests

api_key = "YOUR_API_KEY"
endpoint = f"https://play.instruqt.com/graphql"

query = """mutation {
    createTrackInvite(invite: {title: "New invites from ACorp", trackIDs:["TRACK-ID"], allowAnonymous: true}) {
      id
      title
    }
}"""

response = requests.post(endpoint, headers={"Authorization": "Bearer " + api_key}, json={"query": query})
print(response.json())
```

⇨ Replace `TRACK-ID` with your track ID and `YOUR_API_KEY` with the copied key. You can also enter your title.
{% endtab %}
{% endtabs %}

The response will be something like this:

{% tabs %}
{% tab title="JSON" %}

```json
{
    "data": {
        "createTrackInvite": {
            "id": "nm3o1kx5eyna",
            "title": "New invites from ACorp"
        }
    }
}
```

{% endtab %}
{% endtabs %}

And if you move over to your team page in Web UI and click the **Invites** tab, you will see the newly created track invite.

#### Add a new team member

You can also add new team members with Instruqt GraphQL API. Again, first head over to GraphQL Playground and now search for the `inviteOrganizationUser` mutation to inspect the details.

Next, add a new team member with the `member` role:

{% tabs %}
{% tab title="Curl" %}

1. Open a terminal and run the following curl example:
2. ```bash
   cat >query.json <<EOF
   {
     "query": "mutation {
        inviteOrganizationUser(organizationID: \"TEAM\", email: \"EMAIL\", role: member) {
          id
          name
        }
     }"
   }
   EOF

   curl -H "Authorization: Bearer YOUR_API_KEY" -X POST -d @query.json https://play.instruqt.com/graphql
   ```

   ⇨ Replace `TEAM` with your team, `EMAIL` with the new member's email, and `YOUR_API_KEY` with the copied key.
   {% endtab %}

{% tab title="Python" %}

```python
import requests

api_key = "YOUR_API_KEY"
endpoint = f"https://play.instruqt.com/graphql"

query = """mutation {
    inviteOrganizationUser(organizationID: "TEAM", email: "EMAIL", role: member) {
      id
      name
    }
}"""


response = requests.post(endpoint, headers={"Authorization": "Bearer " + api_key}, json={"query": query})
print(response.json())
```

⇨ Replace `TEAM` with your team, `EMAIL` with the new member's email, and `YOUR_API_KEY` with the copied key.
{% endtab %}
{% endtabs %}

The response will be something like this:

{% tabs %}
{% tab title="JSON" %}

```json
{
    "data": {
        "inviteOrganizationUser": {
            "id": "p1qlyur60v9g",
            "name": "Instruqt"
        }
    }
}
```

{% endtab %}
{% endtabs %}

#### Delete a challenge

Inspect the details for the `deleteChallenge` mutation in GraphQL Playground and then delete the Kubernetes dashboard challenge:

{% tabs %}
{% tab title="Curl" %}

1. Open a terminal and run the following curl example:
2. ```bash
   cat >query.json <<EOF
   {
     "query": "mutation {
        deleteChallenge(challengeID: \"h6ejfdyevgqx\") {
        }   
      }"
   }
   EOF

   curl -H "Authorization: Bearer YOUR_API_KEY" -X POST -d @query.json https://play.instruqt.com/graphql
   ```

{% endtab %}

{% tab title="Python" %}

```python
import requests

api_key = "YOUR_API_KEY"
endpoint = f"https://play.instruqt.com/graphql"

query = """mutation {
    deleteChallenge(challengeID: "h6ejfdyevgqx") {
    }
}"""


response = requests.post(endpoint, headers={"Authorization": "Bearer " + api_key}, json={"query": query})
print(response.json())
```

{% endtab %}
{% endtabs %}

The response will be like this:

{% tabs %}
{% tab title="JSON" %}

```json
{
    "data": {
        "deleteChallenge": true
    }
}
```

{% endtab %}
{% endtabs %}

### Handling errors

Every GraphQL (HTTP Post) request responds with the status code `200` (OK), even if your query or mutation contains errors. So, you need to check the query or mutation response for signaling and handling errors. Let's see what an error response looks like by misspelling the `organizationSlug` property in a query:

{% tabs %}
{% tab title="Curl" %}

1. Open a terminal and run the following curl example:
2. ```bash
   cat >query.json <<EOF
   {
     "query": "query {
       tracks(organisationSlug: \"TEAM\") {
         id
         slug
         title
         play_count
       }
     }"
   }
   EOF

   curl -H "Authorization: Bearer YOUR_API_KEY" -X POST -d @query.json https://play.instruqt.com/graphql
   ```

   ⇨ Replace `TEAM` with your team and `YOUR_API_KEY` with the copied key.
   {% endtab %}

{% tab title="Python" %}

```python
import requests

api_key = "YOUR_API_KEY"
endpoint = f"https://play.instruqt.com/graphql"

query = """query {
    tracks(organisationSlug: \"TEAM\") {
      id
      slug
      title
      play_count
    }
}"""

response = requests.post(endpoint, headers={"Authorization": "Bearer " + api_key}, json={"query": query})
print(response.json())
```

⇨ Replace `TEAM` with your team and `YOUR_API_KEY` with the copied key.
{% endtab %}
{% endtabs %}

Now you will get an error response like this:

{% tabs %}
{% tab title="JSON" %}

```json
{
  "errors": [
    {
      "message": "Unknown argument \"organisationSug\" on field \"tracks\" of type \"Query\".",
      "locations": [
        {
          "line": 2,
          "column": 10
        }
      ]
    }
  ]
}
```

{% endtab %}
{% endtabs %}

And you can process this error in your script or program.

## Example: Updating track invites

Now let's look at a more extensive example in Python that updates all track invites with values set by you. The Python script queries all track invites and runs a mutation query for each track invite:

{% tabs %}
{% tab title="Python" %}

```python
import requests
import json

api_key = "YOUR_API_KEY"
endpoint = f"https://play.instruqt.com/graphql"
team = 'YOUR_TEAM'

# track invite values to be set by you
inviteLimit = 500
inviteTTL = '2022-07-26T15:00:00Z'
playLimit = 2000
playTTL = 120
allowAnonymous = "false"
allowedEmailAddresses = json.dumps(['june@mycorp.com', 'adam@mycorp.com',
                                    'angela@my-corp.com', 'pete@mycorp.com'])  # json.dumps replaces single quotes with double quotes as requered by the GraphQL API

# query all track invites
query = f"""query {{
    trackInvites(organizationSlug: \"{team}\") {{
      id
      title
      tracks {{id}}
    }}
}}"""
response = requests.post(endpoint, headers={
    "Authorization": "Bearer " + api_key}, json={"query": query})

# update each individual track invite
invites = response.json()['data']['trackInvites']
for invite in invites:
    # parse track invite values to pass them back into the mutation
    invite_id = invite['id']
    invite_title = invite['title']
    invite_tracks = invite['tracks']
    # create a list with track IDs
    trackIDs = list()
    for track in invite_tracks:
        trackIDs.append(track['id'])
    trackIDs = json.dumps(trackIDs)

    # execute the mutation
    query = f"""mutation {{updateTrackInvite(invite: {{id: "{invite_id}" 
                                                       title: "{invite_title}", 
                                                       trackIDs: {trackIDs}, 
                                                       inviteLimit: {inviteLimit}, 
                                                       inviteTTL: "{inviteTTL}", 
                                                       playLimit: {playLimit}, 
                                                       playTTL: {playTTL}, 
                                                       allowAnonymous: {allowAnonymous}, 
                                                       allowedEmailAddresses: {allowedEmailAddresses}}}) {{
                                id
                                title
                            }}
                         }}"""
    response = requests.post(endpoint, headers={
        "Authorization": "Bearer " + api_key}, json={"query": query})
    print('updated:', response.json())
```

⇨ Replace `YOUR\_API\_KEY` and `YOUR\_TEAM` with your values.\
⇨ Set the variables in lines 9 to 14 with your values.

↳ Lines 18 to 26 queries all track invites.\
↳ Line 29 parses all track invites into a variable.\
↳ Lines 30 to 57 run over all track invites and updates each track invite with the values you set.
{% endtab %}
{% endtabs %}
