GraphQL API Guide

GraphQL is a query language for APIs that offers an efficient and versatile alternative to REST APIs.

Benefits of Using GraphQL Over REST

  1. Single Endpoint: GraphQL employs a single endpoint for all queries and mutations, contrasting with REST which necessitates multiple endpoints.

  2. Streamlined Data Retrieval: With GraphQL, there's no need for intermediary datastores or additional layers when collating related data.

  3. Precise Data Retrieval: Clients dictate the exact data they need, ensuring swift and succinct responses.

  4. HTTP-Based: GraphQL, despite its unique query language, operates via standard HTTP, meaning any client capable of HTTP requests can interface with a GraphQL server. No GraphQL specific libraries are needed.

Authentication

Use the Authorization HTTP header with your personal access token.

Header:

bash
Authorization: Bearer YOUR_PERSONAL_ACCESS_TOKEN
Authorization: Bearer YOUR_PERSONAL_ACCESS_TOKEN

Obtaining a Personal Access Token

See: How do I create a personal access token?


Queries, Mutations, and Subscriptions

Queries

Queries allow for fetching data in a read-only manner. You can think of them as the equivalent of a GET request in REST.

Example: Get a device by ID.

graphql
query {
    device(id: "1234567890") {
        id
        label
    }
}
query {
    device(id: "1234567890") {
        id
        label
    }
}

Mutations

Mutations make modifications to the data and can be equated to POST, PUT, or DELETE requests in REST.

Example: Create and enable a new device.

graphql
mutation {
    createDevice(device: { label: "Drone01", enabled: true }) {
        id
        label
    }
}
mutation {
    createDevice(device: { label: "Drone01", enabled: true }) {
        id
        label
    }
}

Subscriptions

Subscriptions are a unique feature of GraphQL, allowing for real-time updates through WebSockets. They're valuable for keeping the client-side data in sync with the server.

Example: Receive real-time position updates for all of the current user's devices.

graphql
subscription {
    devices {
        id
        lastPosition {
            timestamp
            position { llaDec { lat lon alt } }
        }
    }
}
subscription {
    devices {
        id
        lastPosition {
            timestamp
            position { llaDec { lat lon alt } }
        }
    }
}

Filters

Filters allow you to fine-tune your GraphQL queries, allowing you to retrieve data based on specific conditions.

StringConditional

StringConditional is an input type that provides a mechanism to filter strings based on certain conditions:

graphql
input StringConditional {
    """
    Equals operator
    """
    eq: String

    """
    Not Equals operator
    """
    ne: String
}
input StringConditional {
    """
    Equals operator
    """
    eq: String

    """
    Not Equals operator
    """
    ne: String
}

This input type provides two fields:

  1. eq: This field expects a string value. When provided, it represents an "equals" condition, meaning that the field being filtered should match (be equal to) the provided string.

  2. ne: This field also expects a string value. When provided, it represents a "not equals" condition, meaning that the field being filtered should not match (be different from) the provided string.

For example, if you were to use this input type in a query to filter devices by a specific label, it could look something like this:

graphql
query {
    myDevices(filter: { label: { eq: "My Special Device" } }) {
        content {
            id
            label
        }
    }
}
query {
    myDevices(filter: { label: { eq: "My Special Device" } }) {
        content {
            id
            label
        }
    }
}

DeviceFilter

The DeviceFilter allows for querying devices based on specific attributes such as label, status, and tags.

Filtering by Connection Status

To filter devices by their connection status, use the status attribute of DeviceFilter and choose a value from the ConnectionStatus enum.

graphql
query {
  myDevices(filter: { status: "GOOD" }) {
    content {
      id
      label
    }
  }
}
query {
  myDevices(filter: { status: "GOOD" }) {
    content {
      id
      label
    }
  }
}

This query retrieves devices with a connection status of "GOOD".

Filtering by Label

To query devices based on string values, use the StringConditional.

graphql
query {
  myDevices(filter: { label: { eq: "MyVehicle" } }) {
    content {
      id
      label
    }
  }
}
query {
  myDevices(filter: { label: { eq: "MyVehicle" } }) {
    content {
      id
      label
    }
  }
}

In this example, devices labeled "MyVehicle" are fetched.

TagFilter

Filtering by Tag Value

To fetch devices with a specific tag value, utilize the tag field within DeviceFilter. The tag field expects a TagFilter.

graphql
query {
  myDevices(filter: { tag: { key: "Group", value: { eq: "Warehouse A" } } }) {
    content {
      id
      label
    }
  }
}
query {
  myDevices(filter: { tag: { key: "Group", value: { eq: "Warehouse A" } } }) {
    content {
      id
      label
    }
  }
}

This query targets devices with a tag that has a key named "Group" and a value of "Warehouse A".

Logical Operators in Filters

Logical operators, namely and, or, and not, allow you to combine or exclude multiple filter conditions, granting you the ability to construct more advanced queries.

AND Operator

The and operator helps you combine multiple filter conditions, returning results that match all the given conditions.

graphql
query {
  myDevices(filter: { and: [{ status: "GOOD" }, { label: { eq: "MyVehicle" } }] }) {
    content {
      id
      label
    }
  }
}
query {
  myDevices(filter: { and: [{ status: "GOOD" }, { label: { eq: "MyVehicle" } }] }) {
    content {
      id
      label
    }
  }
}

This fetches devices that are both in a "GOOD" connection status and have a label of "MyVehicle".

OR Operator

The or operator retrieves results that fulfill any of the conditions provided.

graphql
query {
  myDevices(filter: { or: [{ status: "NO_CONNECTION" }, { label: { eq: "MyDrone" } }] }) {
    content {
      id
      label
    }
  }
}
query {
  myDevices(filter: { or: [{ status: "NO_CONNECTION" }, { label: { eq: "MyDrone" } }] }) {
    content {
      id
      label
    }
  }
}

This query looks for devices that either have a connection status of "NO_CONNECTION" or are labeled "MyDrone".

NOT Operator

The not operator returns results that don't match the provided conditions.

graphql
query {
  myDevices(filter: { not: [{ status: "BAD_POSITION" }] }) {
    content {
      id
      label
    }
  }
}
query {
  myDevices(filter: { not: [{ status: "BAD_POSITION" }] }) {
    content {
      id
      label
    }
  }
}

Here, we're fetching devices that do not have a connection status of "BAD_POSITION".


Queries

myDevices

The myDevices retrieves all devices associated with your account. It also supports filtering based on various criteria:

graphql
type Query {
    """
    Get all devices that belong to the current User's account
    """
    myDevices(filter: DeviceFilter, offset: Int, limit: Int): DevicePage!
}
type Query {
    """
    Get all devices that belong to the current User's account
    """
    myDevices(filter: DeviceFilter, offset: Int, limit: Int): DevicePage!
}

You can filter devices based on a DeviceFilter input type, specify an offset to determine where to start the results from, and set a limit to determine how many results to retrieve.

bash
curl -X POST "https://graphql.pointonenav.com/graphql" \
     -H "Content-Type: application/json" \
     -H "Authorization: Bearer YOUR_PERSONAL_ACCESS_TOKEN" \
     -d '{
         "query": "query { myDevices(filter: { label: { eq: \"MyDevice\" } }) { content { id label } } }"
     }'
curl -X POST "https://graphql.pointonenav.com/graphql" \
     -H "Content-Type: application/json" \
     -H "Authorization: Bearer YOUR_PERSONAL_ACCESS_TOKEN" \
     -d '{
         "query": "query { myDevices(filter: { label: { eq: \"MyDevice\" } }) { content { id label } } }"
     }'
py
# Using the requests library:

import requests

url = "https://graphql.pointonenav.com/graphql"
headers = {
    "Content-Type": "application/json",
    "Authorization": "Bearer YOUR_PERSONAL_ACCESS_TOKEN"
}
data = {
    "query": "query { myDevices(filter: { label: { eq: \"MyDevice\" } }) { content { id label } } }"
}

response = requests.post(url, headers=headers, json=data)
print(response.json())
# Using the requests library:

import requests

url = "https://graphql.pointonenav.com/graphql"
headers = {
    "Content-Type": "application/json",
    "Authorization": "Bearer YOUR_PERSONAL_ACCESS_TOKEN"
}
data = {
    "query": "query { myDevices(filter: { label: { eq: \"MyDevice\" } }) { content { id label } } }"
}

response = requests.post(url, headers=headers, json=data)
print(response.json())
typescript
// Using the fetch API:

const url = "https://graphql.pointonenav.com/graphql";
const headers = {
    "Content-Type": "application/json",
    "Authorization": "Bearer YOUR_PERSONAL_ACCESS_TOKEN"
};
const body = {
    query: `query { myDevices(filter: { label: { eq: "MyDevice" } }) { content { id label } } }`
};

fetch(url, {
    method: "POST",
    headers: headers,
    body: JSON.stringify(body)
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error("Error:", error));
// Using the fetch API:

const url = "https://graphql.pointonenav.com/graphql";
const headers = {
    "Content-Type": "application/json",
    "Authorization": "Bearer YOUR_PERSONAL_ACCESS_TOKEN"
};
const body = {
    query: `query { myDevices(filter: { label: { eq: "MyDevice" } }) { content { id label } } }`
};

fetch(url, {
    method: "POST",
    headers: headers,
    body: JSON.stringify(body)
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error("Error:", error));
go
// Using the net/http package:

package main

import (
        "bytes"
        "encoding/json"
        "fmt"
        "net/http"
)

type GraphQLRequest struct {
        Query string `json:"query"`
}

type Device struct {
        ID    string `json:"id"`
        Label string `json:"label"`
}

type DevicePage struct {
        Content []Device `json:"content"`
}

type GraphQLResponse struct {
        Data struct {
                MyDevices DevicePage `json:"myDevices"`
        } `json:"data"`
}

func main() {
        url := "https://graphql.pointonenav.com/graphql"
        query := `query { myDevices(filter: { label: { eq: "MyDevice" } }) { content { id label } } }`

        requestBody, _ := json.Marshal(GraphQLRequest{Query: query})

        req, _ := http.NewRequest("POST", url, bytes.NewBuffer(requestBody))
        req.Header.Set("Content-Type", "application/json")
        req.Header.Set("Authorization", "Bearer YOUR_PERSONAL_ACCESS_TOKEN")

        client := &http.Client{}
        resp, err := client.Do(req)
        if err != nil {
                panic(err)
        }
        defer resp.Body.Close()

        var result GraphQLResponse
        json.NewDecoder(resp.Body).Decode(&result)

        for _, device := range result.Data.MyDevices.Content {
                fmt.Printf("ID: %s, Label: %s\n", device.ID, device.Label)
        }
}
// Using the net/http package:

package main

import (
        "bytes"
        "encoding/json"
        "fmt"
        "net/http"
)

type GraphQLRequest struct {
        Query string `json:"query"`
}

type Device struct {
        ID    string `json:"id"`
        Label string `json:"label"`
}

type DevicePage struct {
        Content []Device `json:"content"`
}

type GraphQLResponse struct {
        Data struct {
                MyDevices DevicePage `json:"myDevices"`
        } `json:"data"`
}

func main() {
        url := "https://graphql.pointonenav.com/graphql"
        query := `query { myDevices(filter: { label: { eq: "MyDevice" } }) { content { id label } } }`

        requestBody, _ := json.Marshal(GraphQLRequest{Query: query})

        req, _ := http.NewRequest("POST", url, bytes.NewBuffer(requestBody))
        req.Header.Set("Content-Type", "application/json")
        req.Header.Set("Authorization", "Bearer YOUR_PERSONAL_ACCESS_TOKEN")

        client := &http.Client{}
        resp, err := client.Do(req)
        if err != nil {
                panic(err)
        }
        defer resp.Body.Close()

        var result GraphQLResponse
        json.NewDecoder(resp.Body).Decode(&result)

        for _, device := range result.Data.MyDevices.Content {
                fmt.Printf("ID: %s, Label: %s\n", device.ID, device.Label)
        }
}

device

The device query allows a user to retrieve a specific device by its Device ID:

graphql
type Query {
    """
    Get a Device by its Device ID
    """
    device(id: ID!): Device!
}
type Query {
    """
    Get a Device by its Device ID
    """
    device(id: ID!): Device!
}

The id parameter is required.

bash
curl -X POST "https://graphql.pointonenav.com/graphql" \
     -H "Content-Type: application/json" \
     -H "Authorization: Bearer YOUR_PERSONAL_ACCESS_TOKEN" \
     -d '{
         "query": "query { device(id: \"YOUR_DEVICE_ID\") { id label } }"
     }'
curl -X POST "https://graphql.pointonenav.com/graphql" \
     -H "Content-Type: application/json" \
     -H "Authorization: Bearer YOUR_PERSONAL_ACCESS_TOKEN" \
     -d '{
         "query": "query { device(id: \"YOUR_DEVICE_ID\") { id label } }"
     }'
py
# Using the requests library:

import requests

url = "https://graphql.pointonenav.com/graphql"
headers = {
    "Content-Type": "application/json",
    "Authorization": "Bearer YOUR_PERSONAL_ACCESS_TOKEN"
}
data = {
    "query": "query { device(id: \"YOUR_DEVICE_ID\") { id label } }"
}

response = requests.post(url, headers=headers, json=data)
print(response.json())
# Using the requests library:

import requests

url = "https://graphql.pointonenav.com/graphql"
headers = {
    "Content-Type": "application/json",
    "Authorization": "Bearer YOUR_PERSONAL_ACCESS_TOKEN"
}
data = {
    "query": "query { device(id: \"YOUR_DEVICE_ID\") { id label } }"
}

response = requests.post(url, headers=headers, json=data)
print(response.json())
typescript
// Using the fetch API:

const url = "https://graphql.pointonenav.com/graphql";
const headers = {
    "Content-Type": "application/json",
    "Authorization": "Bearer YOUR_PERSONAL_ACCESS_TOKEN"
};
const body = {
    query: `query { device(id: "YOUR_DEVICE_ID") { id label } }`
};

fetch(url, {
    method: "POST",
    headers: headers,
    body: JSON.stringify(body)
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error("Error:", error));
// Using the fetch API:

const url = "https://graphql.pointonenav.com/graphql";
const headers = {
    "Content-Type": "application/json",
    "Authorization": "Bearer YOUR_PERSONAL_ACCESS_TOKEN"
};
const body = {
    query: `query { device(id: "YOUR_DEVICE_ID") { id label } }`
};

fetch(url, {
    method: "POST",
    headers: headers,
    body: JSON.stringify(body)
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error("Error:", error));
go
// Using the net/http package:

package main

import (
        "bytes"
        "encoding/json"
        "fmt"
        "net/http"
)

type GraphQLRequest struct {
        Query string `json:"query"`
}

type Device struct {
        ID    string `json:"id"`
        Label string `json:"label"`
}

type GraphQLResponse struct {
        Data struct {
                Device Device `json:"device"`
        } `json:"data"`
}

func main() {
        url := "https://graphql.pointonenav.com/graphql"
        query := `query { device(id: "YOUR_DEVICE_ID") { id label } }`

        requestBody, _ := json.Marshal(GraphQLRequest{Query: query})

        req, _ := http.NewRequest("POST", url, bytes.NewBuffer(requestBody))
        req.Header.Set("Content-Type", "application/json")
        req.Header.Set("Authorization", "Bearer YOUR_PERSONAL_ACCESS_TOKEN")

        client := &http.Client{}
        resp, err := client.Do(req)
        if err != nil {
                panic(err)
        }
        defer resp.Body.Close()

        var result GraphQLResponse
        json.NewDecoder(resp.Body).Decode(&result)

        fmt.Printf("ID: %s, Label: %s\n", result.Data.Device.ID, result.Data.Device.Label)
}
// Using the net/http package:

package main

import (
        "bytes"
        "encoding/json"
        "fmt"
        "net/http"
)

type GraphQLRequest struct {
        Query string `json:"query"`
}

type Device struct {
        ID    string `json:"id"`
        Label string `json:"label"`
}

type GraphQLResponse struct {
        Data struct {
                Device Device `json:"device"`
        } `json:"data"`
}

func main() {
        url := "https://graphql.pointonenav.com/graphql"
        query := `query { device(id: "YOUR_DEVICE_ID") { id label } }`

        requestBody, _ := json.Marshal(GraphQLRequest{Query: query})

        req, _ := http.NewRequest("POST", url, bytes.NewBuffer(requestBody))
        req.Header.Set("Content-Type", "application/json")
        req.Header.Set("Authorization", "Bearer YOUR_PERSONAL_ACCESS_TOKEN")

        client := &http.Client{}
        resp, err := client.Do(req)
        if err != nil {
                panic(err)
        }
        defer resp.Body.Close()

        var result GraphQLResponse
        json.NewDecoder(resp.Body).Decode(&result)

        fmt.Printf("ID: %s, Label: %s\n", result.Data.Device.ID, result.Data.Device.Label)
}

viewPersonalAccessTokens

graphql
The viewPersonalAccessTokens query allows a user to retrieve all personal access tokens associated with the current user's account:

type Query {
    """
    View all personal access tokens for current user
    """
    viewPersonalAccessTokens: [PersonalAccessToken!]
}
The viewPersonalAccessTokens query allows a user to retrieve all personal access tokens associated with the current user's account:

type Query {
    """
    View all personal access tokens for current user
    """
    viewPersonalAccessTokens: [PersonalAccessToken!]
}

No parameters are required for this query.

bash
curl -X POST "https://graphql.pointonenav.com/graphql" \
     -H "Content-Type: application/json" \
     -H "Authorization: Bearer YOUR_PERSONAL_ACCESS_TOKEN" \
     -d '{
         "query": "query { viewPersonalAccessTokens { name description createdAt } }"
     }'
curl -X POST "https://graphql.pointonenav.com/graphql" \
     -H "Content-Type: application/json" \
     -H "Authorization: Bearer YOUR_PERSONAL_ACCESS_TOKEN" \
     -d '{
         "query": "query { viewPersonalAccessTokens { name description createdAt } }"
     }'
py
# Using the requests library:

import requests

url = "https://graphql.pointonenav.com/graphql"
headers = {
    "Content-Type": "application/json",
    "Authorization": "Bearer YOUR_PERSONAL_ACCESS_TOKEN"
}
data = {
    "query": "query { viewPersonalAccessTokens { name description createdAt } }"
}

response = requests.post(url, headers=headers, json=data)
print(response.json())
# Using the requests library:

import requests

url = "https://graphql.pointonenav.com/graphql"
headers = {
    "Content-Type": "application/json",
    "Authorization": "Bearer YOUR_PERSONAL_ACCESS_TOKEN"
}
data = {
    "query": "query { viewPersonalAccessTokens { name description createdAt } }"
}

response = requests.post(url, headers=headers, json=data)
print(response.json())
typescript
// Using the fetch API:

const url = "https://graphql.pointonenav.com/graphql";
const headers = {
    "Content-Type": "application/json",
    "Authorization": "Bearer YOUR_PERSONAL_ACCESS_TOKEN"
};
const body = {
    query: `query { viewPersonalAccessTokens { name description createdAt } }`
};

fetch(url, {
    method: "POST",
    headers: headers,
    body: JSON.stringify(body)
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error("Error:", error));
// Using the fetch API:

const url = "https://graphql.pointonenav.com/graphql";
const headers = {
    "Content-Type": "application/json",
    "Authorization": "Bearer YOUR_PERSONAL_ACCESS_TOKEN"
};
const body = {
    query: `query { viewPersonalAccessTokens { name description createdAt } }`
};

fetch(url, {
    method: "POST",
    headers: headers,
    body: JSON.stringify(body)
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error("Error:", error));
go
// Using the net/http package:

package main

import (
        "bytes"
        "encoding/json"
        "fmt"
        "net/http"
)

type GraphQLRequest struct {
        Query string `json:"query"`
}

type PersonalAccessToken struct {
        Name        string `json:"name"`
        Description string `json:"description"`
        CreatedAt   string `json:"createdAt"`
}

type GraphQLResponse struct {
        Data struct {
                PersonalAccessTokens []PersonalAccessToken `json:"viewPersonalAccessTokens"`
        } `json:"data"`
}

func main() {
        url := "https://graphql.pointonenav.com/graphql"
        query := `query { viewPersonalAccessTokens { name description createdAt } }`

        requestBody, _ := json.Marshal(GraphQLRequest{Query: query})

        req, _ := http.NewRequest("POST", url, bytes.NewBuffer(requestBody))
        req.Header.Set("Content-Type", "application/json")
        req.Header.Set("Authorization", "Bearer YOUR_PERSONAL_ACCESS_TOKEN")

        client := &http.Client{}
        resp, err := client.Do(req)
        if err != nil {
                panic(err)
        }
        defer resp.Body.Close()

        var result GraphQLResponse
        json.NewDecoder(resp.Body).Decode(&result)

        for _, token := range result.Data.PersonalAccessTokens {
                fmt.Printf("Name: %s, Description: %s, Created At: %s\n", token.Name, token.Description, token.CreatedAt)
        }
}
// Using the net/http package:

package main

import (
        "bytes"
        "encoding/json"
        "fmt"
        "net/http"
)

type GraphQLRequest struct {
        Query string `json:"query"`
}

type PersonalAccessToken struct {
        Name        string `json:"name"`
        Description string `json:"description"`
        CreatedAt   string `json:"createdAt"`
}

type GraphQLResponse struct {
        Data struct {
                PersonalAccessTokens []PersonalAccessToken `json:"viewPersonalAccessTokens"`
        } `json:"data"`
}

func main() {
        url := "https://graphql.pointonenav.com/graphql"
        query := `query { viewPersonalAccessTokens { name description createdAt } }`

        requestBody, _ := json.Marshal(GraphQLRequest{Query: query})

        req, _ := http.NewRequest("POST", url, bytes.NewBuffer(requestBody))
        req.Header.Set("Content-Type", "application/json")
        req.Header.Set("Authorization", "Bearer YOUR_PERSONAL_ACCESS_TOKEN")

        client := &http.Client{}
        resp, err := client.Do(req)
        if err != nil {
                panic(err)
        }
        defer resp.Body.Close()

        var result GraphQLResponse
        json.NewDecoder(resp.Body).Decode(&result)

        for _, token := range result.Data.PersonalAccessTokens {
                fmt.Printf("Name: %s, Description: %s, Created At: %s\n", token.Name, token.Description, token.CreatedAt)
        }
}

Mutations

createDevice

The createDevice mutation allows a user to create a new device

graphql
type Mutation {
    """
    Create a new device
    """
    createDevice(input: CreateDeviceInput!): Device!
}
type Mutation {
    """
    Create a new device
    """
    createDevice(input: CreateDeviceInput!): Device!
}
bash
curl -X POST "https://graphql.pointonenav.com/graphql" \
     -H "Content-Type: application/json" \
     -H "Authorization: Bearer YOUR_PERSONAL_ACCESS_TOKEN" \
     -d '{
         "query": "mutation { createDevice(device: {label: \"YOUR_DEVICE_LABEL\"}) { id label } }"
     }'
curl -X POST "https://graphql.pointonenav.com/graphql" \
     -H "Content-Type: application/json" \
     -H "Authorization: Bearer YOUR_PERSONAL_ACCESS_TOKEN" \
     -d '{
         "query": "mutation { createDevice(device: {label: \"YOUR_DEVICE_LABEL\"}) { id label } }"
     }'
py
# Using the requests library:

import requests

url = "https://graphql.pointonenav.com/graphql"
headers = {
    "Content-Type": "application/json",
    "Authorization": "Bearer YOUR_PERSONAL_ACCESS_TOKEN"
}
data = {
    "query": "mutation { createDevice(device: {label: \"YOUR_DEVICE_LABEL\"}) { id label type } }"
}

response = requests.post(url, headers=headers, json=data)
print(response.json())
# Using the requests library:

import requests

url = "https://graphql.pointonenav.com/graphql"
headers = {
    "Content-Type": "application/json",
    "Authorization": "Bearer YOUR_PERSONAL_ACCESS_TOKEN"
}
data = {
    "query": "mutation { createDevice(device: {label: \"YOUR_DEVICE_LABEL\"}) { id label type } }"
}

response = requests.post(url, headers=headers, json=data)
print(response.json())
typescript
// Using the fetch API:

const url = "https://graphql.pointonenav.com/graphql";
const headers = {
    "Content-Type": "application/json",
    "Authorization": "Bearer YOUR_PERSONAL_ACCESS_TOKEN"
};
const body = {
    query: `mutation { createDevice(device: {label: "YOUR_DEVICE_LABEL" }) { id label } }`
};

fetch(url, {
    method: "POST",
    headers: headers,
    body: JSON.stringify(body)
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error("Error:", error));
// Using the fetch API:

const url = "https://graphql.pointonenav.com/graphql";
const headers = {
    "Content-Type": "application/json",
    "Authorization": "Bearer YOUR_PERSONAL_ACCESS_TOKEN"
};
const body = {
    query: `mutation { createDevice(device: {label: "YOUR_DEVICE_LABEL" }) { id label } }`
};

fetch(url, {
    method: "POST",
    headers: headers,
    body: JSON.stringify(body)
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error("Error:", error));
go
// Using the net/http package:

package main

import (
    "bytes"
    "encoding/json"
    "fmt"
    "net/http"
)

type GraphQLRequest struct {
    Query string `json:"query"`
}

type Device struct {
    ID    string `json:"id"`
    Label string `json:"label"`
    Type  string `json:"type"`
}

type GraphQLResponse struct {
    Data struct {
        CreateDevice Device `json:"createDevice"`
    } `json:"data"`
}

func main() {
    url := "https://graphql.pointonenav.com/graphql"
    query := `mutation { createDevice(device: {label: "YOUR_DEVICE_LABEL"}) { id label } }`

    requestBody, _ := json.Marshal(GraphQLRequest{Query: query})

    req, _ := http.NewRequest("POST", url, bytes.NewBuffer(requestBody))
    req.Header.Set("Content-Type", "application/json")
    req.Header.Set("Authorization", "Bearer YOUR_PERSONAL_ACCESS_TOKEN")

    client := &http.Client{}
    resp, err := client.Do(req)
    if err != nil {
        panic(err)
    }
    defer resp.Body.Close()

    var result GraphQLResponse
    json.NewDecoder(resp.Body).Decode(&result)

    fmt.Printf("ID: %s, Label: %s\n", result.Data.CreateDevice.ID, result.Data.CreateDevice.Label)
}
// Using the net/http package:

package main

import (
    "bytes"
    "encoding/json"
    "fmt"
    "net/http"
)

type GraphQLRequest struct {
    Query string `json:"query"`
}

type Device struct {
    ID    string `json:"id"`
    Label string `json:"label"`
    Type  string `json:"type"`
}

type GraphQLResponse struct {
    Data struct {
        CreateDevice Device `json:"createDevice"`
    } `json:"data"`
}

func main() {
    url := "https://graphql.pointonenav.com/graphql"
    query := `mutation { createDevice(device: {label: "YOUR_DEVICE_LABEL"}) { id label } }`

    requestBody, _ := json.Marshal(GraphQLRequest{Query: query})

    req, _ := http.NewRequest("POST", url, bytes.NewBuffer(requestBody))
    req.Header.Set("Content-Type", "application/json")
    req.Header.Set("Authorization", "Bearer YOUR_PERSONAL_ACCESS_TOKEN")

    client := &http.Client{}
    resp, err := client.Do(req)
    if err != nil {
        panic(err)
    }
    defer resp.Body.Close()

    var result GraphQLResponse
    json.NewDecoder(resp.Body).Decode(&result)

    fmt.Printf("ID: %s, Label: %s\n", result.Data.CreateDevice.ID, result.Data.CreateDevice.Label)
}

createDevices

The createDevices mutation allows a user to create multiple devices at once.

graphql
type Mutation {
    """
    Create multiple Devices
    """
    createDevices(quantity: Int!, enabled: Boolean): [Device!]!
}
type Mutation {
    """
    Create multiple Devices
    """
    createDevices(quantity: Int!, enabled: Boolean): [Device!]!
}

The quantity parameter is required and specifies the number of devices to be created. The enabled parameter is optional and sets the state of the devices.

bash
curl -X POST "https://graphql.pointonenav.com/graphql" \
     -H "Content-Type: application/json" \
     -H "Authorization: Bearer YOUR_PERSONAL_ACCESS_TOKEN" \
     -d '{
         "query": "mutation { createDevices(quantity: 2, enabled: true) { id label } }"
     }'
curl -X POST "https://graphql.pointonenav.com/graphql" \
     -H "Content-Type: application/json" \
     -H "Authorization: Bearer YOUR_PERSONAL_ACCESS_TOKEN" \
     -d '{
         "query": "mutation { createDevices(quantity: 2, enabled: true) { id label } }"
     }'
py
# Using the requests library:

import requests

url = "https://graphql.pointonenav.com/graphql"
headers = {
    "Content-Type": "application/json",
    "Authorization": "Bearer YOUR_PERSONAL_ACCESS_TOKEN"
}
data = {
    "query": "mutation { createDevices(quantity: 2, enabled: true) { id label } }"
}

response = requests.post(url, headers=headers, json=data)
print(response.json())
# Using the requests library:

import requests

url = "https://graphql.pointonenav.com/graphql"
headers = {
    "Content-Type": "application/json",
    "Authorization": "Bearer YOUR_PERSONAL_ACCESS_TOKEN"
}
data = {
    "query": "mutation { createDevices(quantity: 2, enabled: true) { id label } }"
}

response = requests.post(url, headers=headers, json=data)
print(response.json())
typescript
// Using the fetch API:

const url = "https://graphql.pointonenav.com/graphql";
const headers = {
    "Content-Type": "application/json",
    "Authorization": "Bearer YOUR_PERSONAL_ACCESS_TOKEN"
};
const body = {
    query: `mutation { createDevices(quantity: 2, enabled: true) { id label } }`
};

fetch(url, {
    method: "POST",
    headers: headers,
    body: JSON.stringify(body)
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error("Error:", error));
// Using the fetch API:

const url = "https://graphql.pointonenav.com/graphql";
const headers = {
    "Content-Type": "application/json",
    "Authorization": "Bearer YOUR_PERSONAL_ACCESS_TOKEN"
};
const body = {
    query: `mutation { createDevices(quantity: 2, enabled: true) { id label } }`
};

fetch(url, {
    method: "POST",
    headers: headers,
    body: JSON.stringify(body)
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error("Error:", error));
go
// Using the net/http package:

package main

import (
        "bytes"
        "encoding/json"
        "fmt"
        "net/http"
)

type GraphQLRequest struct {
        Query string `json:"query"`
}

type Device struct {
        ID    string `json:"id"`
        Label string `json:"label"`
}

type GraphQLResponse struct {
        Data struct {
                Devices []Device `json:"createDevices"`
        } `json:"data"`
}

func main() {
        url := "https://graphql.pointonenav.com/graphql"
        query := `mutation { createDevices(quantity: 2, enabled: true) { id label } }`

        requestBody, _ := json.Marshal(GraphQLRequest{Query: query})

        req, _ := http.NewRequest("POST", url, bytes.NewBuffer(requestBody))
        req.Header.Set("Content-Type", "application/json")
        req.Header.Set("Authorization", "Bearer YOUR_PERSONAL_ACCESS_TOKEN")

        client := &http.Client{}
        resp, err := client.Do(req)
        if err != nil {
                panic(err)
        }
        defer resp.Body.Close()

        var result GraphQLResponse
        json.NewDecoder(resp.Body).Decode(&result)

        for _, device := range result.Data.Devices {
            fmt.Printf("ID: %s, Label: %s\n", device.ID, device.Label)
        }
}
// Using the net/http package:

package main

import (
        "bytes"
        "encoding/json"
        "fmt"
        "net/http"
)

type GraphQLRequest struct {
        Query string `json:"query"`
}

type Device struct {
        ID    string `json:"id"`
        Label string `json:"label"`
}

type GraphQLResponse struct {
        Data struct {
                Devices []Device `json:"createDevices"`
        } `json:"data"`
}

func main() {
        url := "https://graphql.pointonenav.com/graphql"
        query := `mutation { createDevices(quantity: 2, enabled: true) { id label } }`

        requestBody, _ := json.Marshal(GraphQLRequest{Query: query})

        req, _ := http.NewRequest("POST", url, bytes.NewBuffer(requestBody))
        req.Header.Set("Content-Type", "application/json")
        req.Header.Set("Authorization", "Bearer YOUR_PERSONAL_ACCESS_TOKEN")

        client := &http.Client{}
        resp, err := client.Do(req)
        if err != nil {
                panic(err)
        }
        defer resp.Body.Close()

        var result GraphQLResponse
        json.NewDecoder(resp.Body).Decode(&result)

        for _, device := range result.Data.Devices {
            fmt.Printf("ID: %s, Label: %s\n", device.ID, device.Label)
        }
}

updateDevice

The updateDevice mutation allows a user to update the details of a specific device.

graphql
type Mutation {
    """
    Update a specific Device
    """
    updateDevice(device: DeviceInput!): Device!
}
type Mutation {
    """
    Update a specific Device
    """
    updateDevice(device: DeviceInput!): Device!
}

The device parameter is required and should be of type DeviceInput.

bash
curl -X POST "https://graphql.pointonenav.com/graphql" \
     -H "Content-Type: application/json" \
     -H "Authorization: Bearer YOUR_PERSONAL_ACCESS_TOKEN" \
     -d '{
         "query": "mutation { updateDevice(device: {id: \"YOUR_DEVICE_ID\", label: \"New Label\"}) { id label } }"
     }'
curl -X POST "https://graphql.pointonenav.com/graphql" \
     -H "Content-Type: application/json" \
     -H "Authorization: Bearer YOUR_PERSONAL_ACCESS_TOKEN" \
     -d '{
         "query": "mutation { updateDevice(device: {id: \"YOUR_DEVICE_ID\", label: \"New Label\"}) { id label } }"
     }'
py
# Using the requests library:

import requests

url = "https://graphql.pointonenav.com/graphql"
headers = {
    "Content-Type": "application/json",
    "Authorization": "Bearer YOUR_PERSONAL_ACCESS_TOKEN"
}
data = {
    "query": "mutation { updateDevice(device: {id: \"YOUR_DEVICE_ID\", label: \"New Label\"}) { id label } }"
}

response = requests.post(url, headers=headers, json=data)
print(response.json())
# Using the requests library:

import requests

url = "https://graphql.pointonenav.com/graphql"
headers = {
    "Content-Type": "application/json",
    "Authorization": "Bearer YOUR_PERSONAL_ACCESS_TOKEN"
}
data = {
    "query": "mutation { updateDevice(device: {id: \"YOUR_DEVICE_ID\", label: \"New Label\"}) { id label } }"
}

response = requests.post(url, headers=headers, json=data)
print(response.json())
typescript
// Using the fetch API:

const url = "https://graphql.pointonenav.com/graphql";
const headers = {
    "Content-Type": "application/json",
    "Authorization": "Bearer YOUR_PERSONAL_ACCESS_TOKEN"
};
const body = {
    query: `mutation { updateDevice(device: {id: "YOUR_DEVICE_ID", label: "New Label"}) { id label } }`
};

fetch(url, {
    method: "POST",
    headers: headers,
    body: JSON.stringify(body)
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error("Error:", error));
// Using the fetch API:

const url = "https://graphql.pointonenav.com/graphql";
const headers = {
    "Content-Type": "application/json",
    "Authorization": "Bearer YOUR_PERSONAL_ACCESS_TOKEN"
};
const body = {
    query: `mutation { updateDevice(device: {id: "YOUR_DEVICE_ID", label: "New Label"}) { id label } }`
};

fetch(url, {
    method: "POST",
    headers: headers,
    body: JSON.stringify(body)
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error("Error:", error));
go
// Using the net/http package:

package main

import (
        "bytes"
        "encoding/json"
        "fmt"
        "net/http"
)

type GraphQLRequest struct {
        Query string `json:"query"`
}

type Device struct {
        ID    string `json:"id"`
        Label string `json:"label"`
}

type GraphQLResponse struct {
        Data struct {
                Device Device `json:"updateDevice"`
        } `json:"data"`
}

func main() {
        url := "https://graphql.pointonenav.com/graphql"
        query := `mutation { updateDevice(device: {id: "YOUR_DEVICE_ID", label: "New Label"}) { id label } }`

        requestBody, _ := json.Marshal(GraphQLRequest{Query: query})

        req, _ := http.NewRequest("POST", url, bytes.NewBuffer(requestBody))
        req.Header.Set("Content-Type", "application/json")
        req.Header.Set("Authorization", "Bearer YOUR_PERSONAL_ACCESS_TOKEN")

        client := &http.Client{}
        resp, err := client.Do(req)
        if err != nil {
                panic(err)
        }
        defer resp.Body.Close()

        var result GraphQLResponse
        json.NewDecoder(resp.Body).Decode(&result)

        fmt.Printf("ID: %s, Label: %s\n", result.Data.Device.ID, result.Data.Device.Label)
}
// Using the net/http package:

package main

import (
        "bytes"
        "encoding/json"
        "fmt"
        "net/http"
)

type GraphQLRequest struct {
        Query string `json:"query"`
}

type Device struct {
        ID    string `json:"id"`
        Label string `json:"label"`
}

type GraphQLResponse struct {
        Data struct {
                Device Device `json:"updateDevice"`
        } `json:"data"`
}

func main() {
        url := "https://graphql.pointonenav.com/graphql"
        query := `mutation { updateDevice(device: {id: "YOUR_DEVICE_ID", label: "New Label"}) { id label } }`

        requestBody, _ := json.Marshal(GraphQLRequest{Query: query})

        req, _ := http.NewRequest("POST", url, bytes.NewBuffer(requestBody))
        req.Header.Set("Content-Type", "application/json")
        req.Header.Set("Authorization", "Bearer YOUR_PERSONAL_ACCESS_TOKEN")

        client := &http.Client{}
        resp, err := client.Do(req)
        if err != nil {
                panic(err)
        }
        defer resp.Body.Close()

        var result GraphQLResponse
        json.NewDecoder(resp.Body).Decode(&result)

        fmt.Printf("ID: %s, Label: %s\n", result.Data.Device.ID, result.Data.Device.Label)
}

createPersonalAccessToken

The createPersonalAccessToken mutation allows a user to create a new personal access token.

graphql
type Mutation {
    """
    Create a new personal access token
    """
    createPersonalAccessToken(name: String!, description: String, role: TokenRole, expiryInDays: Int! = 365): String!
}
type Mutation {
    """
    Create a new personal access token
    """
    createPersonalAccessToken(name: String!, description: String, role: TokenRole, expiryInDays: Int! = 365): String!
}

The name parameter is required, and you can optionally provide a description, role, and expiryInDays parameter. The role can be either ROLE_READ for read-only permission or ROLE_READ_WRITE for read-write permission. The expiryInDays defaults to 365 days if not specified.

bash
curl -X POST "https://graphql.pointonenav.com/graphql" \
     -H "Content-Type: application/json" \
     -H "Authorization: Bearer YOUR_PERSONAL_ACCESS_TOKEN" \
     -d '{
         "query": "mutation { createPersonalAccessToken(name: \"Token Name\", description: \"Description for the token\", role: ROLE_READ, expiryInDays: 365) }"
     }'
curl -X POST "https://graphql.pointonenav.com/graphql" \
     -H "Content-Type: application/json" \
     -H "Authorization: Bearer YOUR_PERSONAL_ACCESS_TOKEN" \
     -d '{
         "query": "mutation { createPersonalAccessToken(name: \"Token Name\", description: \"Description for the token\", role: ROLE_READ, expiryInDays: 365) }"
     }'
py
# Using the requests library:

import requests

url = "https://graphql.pointonenav.com/graphql"
headers = {
    "Content-Type": "application/json",
    "Authorization": "Bearer YOUR_PERSONAL_ACCESS_TOKEN"
}
data = {
    "query": "mutation { createPersonalAccessToken(name: \"Token Name\", description: \"Description for the token\", role: ROLE_READ, expiryInDays: 365) }"
}

response = requests.post(url, headers=headers, json=data)
print(response.json())
# Using the requests library:

import requests

url = "https://graphql.pointonenav.com/graphql"
headers = {
    "Content-Type": "application/json",
    "Authorization": "Bearer YOUR_PERSONAL_ACCESS_TOKEN"
}
data = {
    "query": "mutation { createPersonalAccessToken(name: \"Token Name\", description: \"Description for the token\", role: ROLE_READ, expiryInDays: 365) }"
}

response = requests.post(url, headers=headers, json=data)
print(response.json())
typescript
// Using the fetch API:

const url = "https://graphql.pointonenav.com/graphql";
const headers = {
    "Content-Type": "application/json",
    "Authorization": "Bearer YOUR_PERSONAL_ACCESS_TOKEN"
};
const body = {
    query: `mutation { createPersonalAccessToken(name: "Token Name", description: "Description for the token", role: ROLE_READ, expiryInDays: 365) }`
};

fetch(url, {
    method: "POST",
    headers: headers,
    body: JSON.stringify(body)
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error("Error:", error));
// Using the fetch API:

const url = "https://graphql.pointonenav.com/graphql";
const headers = {
    "Content-Type": "application/json",
    "Authorization": "Bearer YOUR_PERSONAL_ACCESS_TOKEN"
};
const body = {
    query: `mutation { createPersonalAccessToken(name: "Token Name", description: "Description for the token", role: ROLE_READ, expiryInDays: 365) }`
};

fetch(url, {
    method: "POST",
    headers: headers,
    body: JSON.stringify(body)
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error("Error:", error));
go
// Using the net/http package:

package main

import (
        "bytes"
        "encoding/json"
        "fmt"
        "net/http"
)

type GraphQLRequest struct {
        Query string `json:"query"`
}

type GraphQLResponse struct {
        Data struct {
                Token string `json:"createPersonalAccessToken"`
        } `json:"data"`
}

func main() {
        url := "https://graphql.pointonenav.com/graphql"
        query := `mutation { createPersonalAccessToken(name: "Token Name", description: "Description for the token", role: ROLE_READ, expiryInDays: 365) }`

        requestBody, _ := json.Marshal(GraphQLRequest{Query: query})

        req, _ := http.NewRequest("POST", url, bytes.NewBuffer(requestBody))
        req.Header.Set("Content-Type", "application/json")
        req.Header.Set("Authorization", "Bearer YOUR_PERSONAL_ACCESS_TOKEN")

        client := &http.Client{}
        resp, err := client.Do(req)
        if err != nil {
                panic(err)
        }
        defer resp.Body.Close()

        var result GraphQLResponse
        json.NewDecoder(resp.Body).Decode(&result)

        fmt.Printf("Created Token: %s\n", result.Data.Token)
}
// Using the net/http package:

package main

import (
        "bytes"
        "encoding/json"
        "fmt"
        "net/http"
)

type GraphQLRequest struct {
        Query string `json:"query"`
}

type GraphQLResponse struct {
        Data struct {
                Token string `json:"createPersonalAccessToken"`
        } `json:"data"`
}

func main() {
        url := "https://graphql.pointonenav.com/graphql"
        query := `mutation { createPersonalAccessToken(name: "Token Name", description: "Description for the token", role: ROLE_READ, expiryInDays: 365) }`

        requestBody, _ := json.Marshal(GraphQLRequest{Query: query})

        req, _ := http.NewRequest("POST", url, bytes.NewBuffer(requestBody))
        req.Header.Set("Content-Type", "application/json")
        req.Header.Set("Authorization", "Bearer YOUR_PERSONAL_ACCESS_TOKEN")

        client := &http.Client{}
        resp, err := client.Do(req)
        if err != nil {
                panic(err)
        }
        defer resp.Body.Close()

        var result GraphQLResponse
        json.NewDecoder(resp.Body).Decode(&result)

        fmt.Printf("Created Token: %s\n", result.Data.Token)
}

revokePersonalAccessToken

The revokePersonalAccessToken mutation allows a user to revoke a personal access token using its name.

graphql
type Mutation {
    """
    Revoke a personal access token by name
    """
    revokePersonalAccessToken(name: String!): Boolean!
}
type Mutation {
    """
    Revoke a personal access token by name
    """
    revokePersonalAccessToken(name: String!): Boolean!
}

The name parameter is required and should match the name of the personal access token you wish to revoke.

bash
curl -X POST "https://graphql.pointonenav.com/graphql" \
     -H "Content-Type: application/json" \
     -H "Authorization: Bearer YOUR_PERSONAL_ACCESS_TOKEN" \
     -d '{
         "query": "mutation { revokePersonalAccessToken(name: \"Token Name\") }"
     }'
curl -X POST "https://graphql.pointonenav.com/graphql" \
     -H "Content-Type: application/json" \
     -H "Authorization: Bearer YOUR_PERSONAL_ACCESS_TOKEN" \
     -d '{
         "query": "mutation { revokePersonalAccessToken(name: \"Token Name\") }"
     }'
py
# Using the requests library:

import requests

url = "https://graphql.pointonenav.com/graphql"
headers = {
    "Content-Type": "application/json",
    "Authorization": "Bearer YOUR_PERSONAL_ACCESS_TOKEN"
}
data = {
    "query": "mutation { revokePersonalAccessToken(name: \"Token Name\") }"
}

response = requests.post(url, headers=headers, json=data)
print(response.json())
# Using the requests library:

import requests

url = "https://graphql.pointonenav.com/graphql"
headers = {
    "Content-Type": "application/json",
    "Authorization": "Bearer YOUR_PERSONAL_ACCESS_TOKEN"
}
data = {
    "query": "mutation { revokePersonalAccessToken(name: \"Token Name\") }"
}

response = requests.post(url, headers=headers, json=data)
print(response.json())
typescript
// Using the fetch API:

const url = "https://graphql.pointonenav.com/graphql";
const headers = {
    "Content-Type": "application/json",
    "Authorization": "Bearer YOUR_PERSONAL_ACCESS_TOKEN"
};
const body = {
    query: `mutation { revokePersonalAccessToken(name: "Token Name") }`
};

fetch(url, {
    method: "POST",
    headers: headers,
    body: JSON.stringify(body)
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error("Error:", error));
// Using the fetch API:

const url = "https://graphql.pointonenav.com/graphql";
const headers = {
    "Content-Type": "application/json",
    "Authorization": "Bearer YOUR_PERSONAL_ACCESS_TOKEN"
};
const body = {
    query: `mutation { revokePersonalAccessToken(name: "Token Name") }`
};

fetch(url, {
    method: "POST",
    headers: headers,
    body: JSON.stringify(body)
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error("Error:", error));
go
// Using the net/http package:

package main

import (
        "bytes"
        "encoding/json"
        "fmt"
        "net/http"
)

type GraphQLRequest struct {
        Query string `json:"query"`
}

type GraphQLResponse struct {
        Data struct {
                Success bool `json:"revokePersonalAccessToken"`
        } `json:"data"`
}

func main() {
        url := "https://graphql.pointonenav.com/graphql"
        query := `mutation { revokePersonalAccessToken(name: "Token Name") }`

        requestBody, _ := json.Marshal(GraphQLRequest{Query: query})

        req, _ := http.NewRequest("POST", url, bytes.NewBuffer(requestBody))
        req.Header.Set("Content-Type", "application/json")
        req.Header.Set("Authorization", "Bearer YOUR_PERSONAL_ACCESS_TOKEN")

        client := &http.Client{}
        resp, err := client.Do(req)
        if err != nil {
                panic(err)
        }
        defer resp.Body.Close()

        var result GraphQLResponse
        json.NewDecoder(resp.Body).Decode(&result)

        fmt.Printf("Revoke Success: %v\n", result.Data.Success)
}
// Using the net/http package:

package main

import (
        "bytes"
        "encoding/json"
        "fmt"
        "net/http"
)

type GraphQLRequest struct {
        Query string `json:"query"`
}

type GraphQLResponse struct {
        Data struct {
                Success bool `json:"revokePersonalAccessToken"`
        } `json:"data"`
}

func main() {
        url := "https://graphql.pointonenav.com/graphql"
        query := `mutation { revokePersonalAccessToken(name: "Token Name") }`

        requestBody, _ := json.Marshal(GraphQLRequest{Query: query})

        req, _ := http.NewRequest("POST", url, bytes.NewBuffer(requestBody))
        req.Header.Set("Content-Type", "application/json")
        req.Header.Set("Authorization", "Bearer YOUR_PERSONAL_ACCESS_TOKEN")

        client := &http.Client{}
        resp, err := client.Do(req)
        if err != nil {
                panic(err)
        }
        defer resp.Body.Close()

        var result GraphQLResponse
        json.NewDecoder(resp.Body).Decode(&result)

        fmt.Printf("Revoke Success: %v\n", result.Data.Success)
}

setDeviceTag

The setDeviceTag mutation allows a user to assign a tag to a specific device.

graphql
type Mutation {
    """
    Assign a tag to a device
    """
    setDeviceTag(input: TagInput!): Tag!
}
type Mutation {
    """
    Assign a tag to a device
    """
    setDeviceTag(input: TagInput!): Tag!
}

The input parameter is required and should be of type TagInput, which typically includes fields such as id and key.

bash
curl -X POST "https://graphql.pointonenav.com/graphql" \
     -H "Content-Type: application/json" \
     -H "Authorization: Bearer YOUR_PERSONAL_ACCESS_TOKEN" \
     -d '{
         "query": "mutation { setDeviceTag(input: { ids: [\"YOUR_DEVICE_ID\"], key: \"YourTagName\", value: \"YourTagValue\" }) { key, value } }"
     }'
curl -X POST "https://graphql.pointonenav.com/graphql" \
     -H "Content-Type: application/json" \
     -H "Authorization: Bearer YOUR_PERSONAL_ACCESS_TOKEN" \
     -d '{
         "query": "mutation { setDeviceTag(input: { ids: [\"YOUR_DEVICE_ID\"], key: \"YourTagName\", value: \"YourTagValue\" }) { key, value } }"
     }'
py
# Using the requests library:

import requests

url = "https://graphql.pointonenav.com/graphql"
headers = {
    "Content-Type": "application/json",
    "Authorization": "Bearer YOUR_PERSONAL_ACCESS_TOKEN"
}
data = {
    "query": "mutation { setDeviceTag(input: { ids: [\"YOUR_DEVICE_ID\"], key: \"YourTagName\", value: \"YourTagValue\" }) { key, value } }"
}

response = requests.post(url, headers=headers, json=data)
print(response.json())
# Using the requests library:

import requests

url = "https://graphql.pointonenav.com/graphql"
headers = {
    "Content-Type": "application/json",
    "Authorization": "Bearer YOUR_PERSONAL_ACCESS_TOKEN"
}
data = {
    "query": "mutation { setDeviceTag(input: { ids: [\"YOUR_DEVICE_ID\"], key: \"YourTagName\", value: \"YourTagValue\" }) { key, value } }"
}

response = requests.post(url, headers=headers, json=data)
print(response.json())
typescript
// Using the fetch API:

const url = "https://graphql.pointonenav.com/graphql";
const headers = {
    "Content-Type": "application/json",
    "Authorization": "Bearer YOUR_PERSONAL_ACCESS_TOKEN"
};
const body = {
    query: `mutation { setDeviceTag(input: { ids: ["YOUR_DEVICE_ID"], key: "YourTagName", value: "yourTagValue" }) { key, value } }`
};

fetch(url, {
    method: "POST",
    headers: headers,
    body: JSON.stringify(body)
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error("Error:", error));
// Using the fetch API:

const url = "https://graphql.pointonenav.com/graphql";
const headers = {
    "Content-Type": "application/json",
    "Authorization": "Bearer YOUR_PERSONAL_ACCESS_TOKEN"
};
const body = {
    query: `mutation { setDeviceTag(input: { ids: ["YOUR_DEVICE_ID"], key: "YourTagName", value: "yourTagValue" }) { key, value } }`
};

fetch(url, {
    method: "POST",
    headers: headers,
    body: JSON.stringify(body)
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error("Error:", error));
go
package main

import (
        "bytes"
        "encoding/json"
        "fmt"
        "net/http"
)

type TagInput struct {
        IDs   []string `json:"ids"`
        Key   string   `json:"key"`
        Value string   `json:"value"`
}

type GraphQLRequest struct {
        Query     string   `json:"query"`
        Variables map[string]TagInput `json:"variables"`
}

type Tag struct {
        Key   string `json:"key"`
        Value string `json:"value"`
}

type GraphQLResponse struct {
        Data struct {
                Tag Tag `json:"setDeviceTag"`
        } `json:"data"`
}

func main() {
        url := "https://graphql.pointonenav.com/graphql"
        tagInput := TagInput{
                IDs:   []string{"YOUR_DEVICE_ID"},
                Key:   "YourTagName",
                Value: "yourTagValue",
        }
        query := `mutation ($input: TagInput!) { setDeviceTag(input: $input) { key, value } }`

        requestBody, _ := json.Marshal(GraphQLRequest{Query: query, Variables: map[string]TagInput{"input": tagInput}})

        req, _ := http.NewRequest("POST", url, bytes.NewBuffer(requestBody))
        req.Header.Set("Content-Type", "application/json")
        req.Header.Set("Authorization", "Bearer YOUR_PERSONAL_ACCESS_TOKEN")

        client := &http.Client{}
        resp, err := client.Do(req)
        if err != nil {
                panic(err)
        }
        defer resp.Body.Close()

        var result GraphQLResponse
        json.NewDecoder(resp.Body).Decode(&result)

        fmt.Printf("Tag: %s = %s\n", result.Data.Tag.Key, result.Data.Tag.Value)
}
package main

import (
        "bytes"
        "encoding/json"
        "fmt"
        "net/http"
)

type TagInput struct {
        IDs   []string `json:"ids"`
        Key   string   `json:"key"`
        Value string   `json:"value"`
}

type GraphQLRequest struct {
        Query     string   `json:"query"`
        Variables map[string]TagInput `json:"variables"`
}

type Tag struct {
        Key   string `json:"key"`
        Value string `json:"value"`
}

type GraphQLResponse struct {
        Data struct {
                Tag Tag `json:"setDeviceTag"`
        } `json:"data"`
}

func main() {
        url := "https://graphql.pointonenav.com/graphql"
        tagInput := TagInput{
                IDs:   []string{"YOUR_DEVICE_ID"},
                Key:   "YourTagName",
                Value: "yourTagValue",
        }
        query := `mutation ($input: TagInput!) { setDeviceTag(input: $input) { key, value } }`

        requestBody, _ := json.Marshal(GraphQLRequest{Query: query, Variables: map[string]TagInput{"input": tagInput}})

        req, _ := http.NewRequest("POST", url, bytes.NewBuffer(requestBody))
        req.Header.Set("Content-Type", "application/json")
        req.Header.Set("Authorization", "Bearer YOUR_PERSONAL_ACCESS_TOKEN")

        client := &http.Client{}
        resp, err := client.Do(req)
        if err != nil {
                panic(err)
        }
        defer resp.Body.Close()

        var result GraphQLResponse
        json.NewDecoder(resp.Body).Decode(&result)

        fmt.Printf("Tag: %s = %s\n", result.Data.Tag.Key, result.Data.Tag.Value)
}

unsetDeviceTag

The unsetDeviceTag mutation allows a user to remove a tag from a specific device.

graphql
type Mutation {
    """
    Remove a tag from a device
    """
    unsetDeviceTag(input: TagInput!): Boolean!
}
type Mutation {
    """
    Remove a tag from a device
    """
    unsetDeviceTag(input: TagInput!): Boolean!
}

The input parameter is required and should be of type TagInput, which typically includes fields such as ids and key.

bash
curl -X POST "https://graphql.pointonenav.com/graphql" \
     -H "Content-Type: application/json" \
     -H "Authorization: Bearer YOUR_PERSONAL_ACCESS_TOKEN" \
     -d '{
         "query": "mutation { unsetDeviceTag(input: { ids: [\"YOUR_DEVICE_ID\"], key: \"YourTagName\" }) }"
     }'
curl -X POST "https://graphql.pointonenav.com/graphql" \
     -H "Content-Type: application/json" \
     -H "Authorization: Bearer YOUR_PERSONAL_ACCESS_TOKEN" \
     -d '{
         "query": "mutation { unsetDeviceTag(input: { ids: [\"YOUR_DEVICE_ID\"], key: \"YourTagName\" }) }"
     }'
py
# Using the requests library:

import requests

url = "https://graphql.pointonenav.com/graphql"
headers = {
    "Content-Type": "application/json",
    "Authorization": "Bearer YOUR_PERSONAL_ACCESS_TOKEN"
}
data = {
    "query": "mutation { unsetDeviceTag(input: { ids: [\"YOUR_DEVICE_ID\"], key: \"YourTagName\" }) }"
}

response = requests.post(url, headers=headers, json=data)
print(response.json())
# Using the requests library:

import requests

url = "https://graphql.pointonenav.com/graphql"
headers = {
    "Content-Type": "application/json",
    "Authorization": "Bearer YOUR_PERSONAL_ACCESS_TOKEN"
}
data = {
    "query": "mutation { unsetDeviceTag(input: { ids: [\"YOUR_DEVICE_ID\"], key: \"YourTagName\" }) }"
}

response = requests.post(url, headers=headers, json=data)
print(response.json())
typescript
// Using the fetch API:

const url = "https://graphql.pointonenav.com/graphql";
const headers = {
    "Content-Type": "application/json",
    "Authorization": "Bearer YOUR_PERSONAL_ACCESS_TOKEN"
};
const body = {
    query: `mutation { unsetDeviceTag(input: { ids: ["YOUR_DEVICE_ID"], key: "YourTagName" }) }`
};

fetch(url, {
    method: "POST",
    headers: headers,
    body: JSON.stringify(body)
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error("Error:", error));
// Using the fetch API:

const url = "https://graphql.pointonenav.com/graphql";
const headers = {
    "Content-Type": "application/json",
    "Authorization": "Bearer YOUR_PERSONAL_ACCESS_TOKEN"
};
const body = {
    query: `mutation { unsetDeviceTag(input: { ids: ["YOUR_DEVICE_ID"], key: "YourTagName" }) }`
};

fetch(url, {
    method: "POST",
    headers: headers,
    body: JSON.stringify(body)
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error("Error:", error));
go
package main

import (
        "bytes"
        "encoding/json"
        "fmt"
        "net/http"
)

type TagInput struct {
        IDs []string `json:"ids"`
        Key string   `json:"key"`
}

type GraphQLRequest struct {
        Query     string            `json:"query"`
        Variables map[string]TagInput `json:"variables"`
}

type GraphQLResponse struct {
        Data struct {
                UnsetDeviceTag interface{} `json:"unsetDeviceTag"`
        } `json:"data"`
        Error []struct {
                Message string `json:"message"`
        } `json:"errors"`
}

func main() {
        url := "https://graphql.pointonenav.com/graphql"
        tagInput := TagInput{
                IDs: []string{"YOUR_DEVICE_ID"},
                Key: "YourTagName",
        }
        query := `mutation ($input: TagInput!) { unsetDeviceTag(input: $input) }`

        requestBody, _ := json.Marshal(GraphQLRequest{Query: query, Variables: map[string]TagInput{"input": tagInput}})

        req, _ := http.NewRequest("POST", url, bytes.NewBuffer(requestBody))
        req.Header.Set("Content-Type", "application/json")
        req.Header.Set("Authorization", "Bearer YOUR_PERSONAL_ACCESS_TOKEN")

        client := &http.Client{}
        resp, err := client.Do(req)
        if err != nil {
                panic(err)
        }
        defer resp.Body.Close()

        var result GraphQLResponse
        if err := json.NewDecoder(resp.Body).Decode(&result); err != nil {
                panic(err)
        }

        // Check if there are any errors in the response
        if len(result.Error) > 0 {
                for _, err := range result.Error {
                        fmt.Println("Error:", err.Message)
                }
                return
        }

        fmt.Printf("Success: unsetDeviceTag = %v\n", result.Data.UnsetDeviceTag)
}
package main

import (
        "bytes"
        "encoding/json"
        "fmt"
        "net/http"
)

type TagInput struct {
        IDs []string `json:"ids"`
        Key string   `json:"key"`
}

type GraphQLRequest struct {
        Query     string            `json:"query"`
        Variables map[string]TagInput `json:"variables"`
}

type GraphQLResponse struct {
        Data struct {
                UnsetDeviceTag interface{} `json:"unsetDeviceTag"`
        } `json:"data"`
        Error []struct {
                Message string `json:"message"`
        } `json:"errors"`
}

func main() {
        url := "https://graphql.pointonenav.com/graphql"
        tagInput := TagInput{
                IDs: []string{"YOUR_DEVICE_ID"},
                Key: "YourTagName",
        }
        query := `mutation ($input: TagInput!) { unsetDeviceTag(input: $input) }`

        requestBody, _ := json.Marshal(GraphQLRequest{Query: query, Variables: map[string]TagInput{"input": tagInput}})

        req, _ := http.NewRequest("POST", url, bytes.NewBuffer(requestBody))
        req.Header.Set("Content-Type", "application/json")
        req.Header.Set("Authorization", "Bearer YOUR_PERSONAL_ACCESS_TOKEN")

        client := &http.Client{}
        resp, err := client.Do(req)
        if err != nil {
                panic(err)
        }
        defer resp.Body.Close()

        var result GraphQLResponse
        if err := json.NewDecoder(resp.Body).Decode(&result); err != nil {
                panic(err)
        }

        // Check if there are any errors in the response
        if len(result.Error) > 0 {
                for _, err := range result.Error {
                        fmt.Println("Error:", err.Message)
                }
                return
        }

        fmt.Printf("Success: unsetDeviceTag = %v\n", result.Data.UnsetDeviceTag)
}

Subscriptions

device

The device subscription allows a user to receive state changes for a given device by its Device ID through a WebSocket connection.

The id parameter is required.

py
import asyncio
import uuid

import websockets
import json


async def query_device(device_id):
    query = {
        "id": str(uuid.uuid4()),  # Unique ID for the subscription
        "type": "subscribe",
        "payload": {
            "query": """
                subscription {
                    device(id: "%s") {
                        id
                        lastPosition {
                            position {
                                llaDec {
                                    lat
                                    lon
                                    alt
                                }
                            }
                            timestamp
                        }
                        connectionStatus
                    }
                }
            """ % device_id
        }
    }

    init_message = {
        "type": "connection_init",
        "payload": {
            "Authorization": "Bearer YOUR_PERSONAL_ACCESS_TOKEN"
        }
    }

    uri = "wss://graphql.pointonenav.com/subscriptions"
    async with websockets.connect(uri) as websocket:  # Connect using the graphql-transport-ws protocol
        await websocket.send(json.dumps(init_message))

        while True:
            response_str = await websocket.recv()
            connect_response = json.loads(response_str)

            # Handle different message types here (connection_ack, data, error, etc.)
            if connect_response["type"] == 'connection_ack':
                # Connection acknowledged, now send subscription request
                subscribe_msg = json.dumps(query)
                print("Subscribe: ", subscribe_msg)
                await websocket.send(subscribe_msg)
                device_msg_str = await websocket.recv()
                device_response = json.loads(device_msg_str)
            else:
                print("Connection Error", json.dumps(connect_response))
                break

            while True:
                if device_response["type"] == 'next':
                    # Handle incoming data
                    device_update = device_response['payload']['data']['device']
                    device_msg = json.dumps(device_update)
                    print("Next: ", device_msg)
                    # Process the device update here....
                elif device_response["type"] == 'error':
                    # Handle err data
                    err_msg = connect_response['payload']
                    print("Message Error: ", json.dumps(err_msg))
                elif device_response["type"] == "complete":
                    break


device_id = 'YOUR_DEVICE_ID'
asyncio.get_event_loop().run_until_complete(query_device(device_id))
import asyncio
import uuid

import websockets
import json


async def query_device(device_id):
    query = {
        "id": str(uuid.uuid4()),  # Unique ID for the subscription
        "type": "subscribe",
        "payload": {
            "query": """
                subscription {
                    device(id: "%s") {
                        id
                        lastPosition {
                            position {
                                llaDec {
                                    lat
                                    lon
                                    alt
                                }
                            }
                            timestamp
                        }
                        connectionStatus
                    }
                }
            """ % device_id
        }
    }

    init_message = {
        "type": "connection_init",
        "payload": {
            "Authorization": "Bearer YOUR_PERSONAL_ACCESS_TOKEN"
        }
    }

    uri = "wss://graphql.pointonenav.com/subscriptions"
    async with websockets.connect(uri) as websocket:  # Connect using the graphql-transport-ws protocol
        await websocket.send(json.dumps(init_message))

        while True:
            response_str = await websocket.recv()
            connect_response = json.loads(response_str)

            # Handle different message types here (connection_ack, data, error, etc.)
            if connect_response["type"] == 'connection_ack':
                # Connection acknowledged, now send subscription request
                subscribe_msg = json.dumps(query)
                print("Subscribe: ", subscribe_msg)
                await websocket.send(subscribe_msg)
                device_msg_str = await websocket.recv()
                device_response = json.loads(device_msg_str)
            else:
                print("Connection Error", json.dumps(connect_response))
                break

            while True:
                if device_response["type"] == 'next':
                    # Handle incoming data
                    device_update = device_response['payload']['data']['device']
                    device_msg = json.dumps(device_update)
                    print("Next: ", device_msg)
                    # Process the device update here....
                elif device_response["type"] == 'error':
                    # Handle err data
                    err_msg = connect_response['payload']
                    print("Message Error: ", json.dumps(err_msg))
                elif device_response["type"] == "complete":
                    break


device_id = 'YOUR_DEVICE_ID'
asyncio.get_event_loop().run_until_complete(query_device(device_id))
typescript
import WebSocket from 'ws';
import {v4 as uuidv4} from "uuid";

const queryDevices = async (deviceId: string) => {
    const query = {
        id: uuidv4(), // Unique Connection Identifier 
        type: "subscribe",
        payload: {
            query: `
                subscription {
                    device(id: "${deviceId}") {
                        id
                        label
                        lastPosition {
                            position {
                                llaDec {
                                    lat
                                    lon
                                    alt
                                }
                            }
                            timestamp
                        }
                        connectionStatus
                    }
                }
            `
        }
    };

    const initMessage = {
        type: "connection_init",
        payload: {
            Authorization: "Bearer YOUR_PERSONAL_ACCESS_TOKEN"
        }
    };

    const uri = "wss://graphql.pointonenav.com/subscriptions";
    const websocket = new WebSocket(uri);

    websocket.on('open', async () => {
        websocket.send(JSON.stringify(initMessage));
    });

    websocket.on('message', (message: string) => {
        const {type, payload} = JSON.parse(message);
        if (type === 'connection_ack') {
            console.log('Connected!')
            websocket.send(JSON.stringify(query));
        } else if (type === 'next') {
            console.log('Next: ' + JSON.stringify(payload))
        } else if (type === 'error') {
            console.log('Error: ' + JSON.stringify(payload))
        }
    });
};

const deviceId = 'YOUR_DEVICE_ID';
queryDevices(deviceId);
import WebSocket from 'ws';
import {v4 as uuidv4} from "uuid";

const queryDevices = async (deviceId: string) => {
    const query = {
        id: uuidv4(), // Unique Connection Identifier 
        type: "subscribe",
        payload: {
            query: `
                subscription {
                    device(id: "${deviceId}") {
                        id
                        label
                        lastPosition {
                            position {
                                llaDec {
                                    lat
                                    lon
                                    alt
                                }
                            }
                            timestamp
                        }
                        connectionStatus
                    }
                }
            `
        }
    };

    const initMessage = {
        type: "connection_init",
        payload: {
            Authorization: "Bearer YOUR_PERSONAL_ACCESS_TOKEN"
        }
    };

    const uri = "wss://graphql.pointonenav.com/subscriptions";
    const websocket = new WebSocket(uri);

    websocket.on('open', async () => {
        websocket.send(JSON.stringify(initMessage));
    });

    websocket.on('message', (message: string) => {
        const {type, payload} = JSON.parse(message);
        if (type === 'connection_ack') {
            console.log('Connected!')
            websocket.send(JSON.stringify(query));
        } else if (type === 'next') {
            console.log('Next: ' + JSON.stringify(payload))
        } else if (type === 'error') {
            console.log('Error: ' + JSON.stringify(payload))
        }
    });
};

const deviceId = 'YOUR_DEVICE_ID';
queryDevices(deviceId);
go
package main

import (
	"encoding/json"
	"fmt"
	"log"
	"net/http"
	"net/url"

	"github.com/google/uuid"
	"github.com/gorilla/websocket"
)

// Connection Init message structure
type InitMessage struct {
	Type    string            `json:"type"`
	Payload map[string]string `json:"payload"`
}

// GraphQLSubscriptionMessage represents the structure of a GraphQL WebSocket message
type GraphQLSubscriptionMessage struct {
	Type    string            `json:"type"`
	ID      string            `json:"id,omitempty"`
	Payload map[string]string `json:"payload,omitempty"`
}

func main() {
	serverURL := url.URL{Scheme: "wss", Host: "graphql.pointonenav.com", Path: "/subscriptions"}
	// Prepare the WebSocket handshake request headers
	headers := http.Header{}
	headers.Add("Sec-WebSocket-Protocol", "graphql-transport-ws")

	// Connect to the GraphQL WebSocket endpoint
	conn, _, err := websocket.DefaultDialer.Dial(serverURL.String(), headers)
	if err != nil {
		log.Fatal("Error connecting to WebSocket:", err)
	}
	defer conn.Close()

	TOKEN := "YOUR_PERSONAL_ACCESS_TOKEN"
	auth := map[string]string{
		"Authorization": "Bearer " + TOKEN,
	}

	var init = InitMessage{
		Type:    "connection_init",
		Payload: auth,
	}

	// Initialize the websocket connection
	if err := conn.WriteJSON(init); err != nil {
		log.Fatal("Error sending connection_init message:", err)
	}

	// Read and print messages from the server
	for {
		_, message, err := conn.ReadMessage()
		if err != nil {
			log.Fatal("Error reading message from server:", err)
			break
		}

		fmt.Println("Received message from server:", string(message))

		var msg GraphQLSubscriptionMessage
		json.Unmarshal(message, &msg)

		switch msg.Type {
		case "connection_ack":
			query := `subscription {
				device(id: "YOUR_DEVICE_ID_HERE"){
					id
					label
					connectionStatus
				}
			}`

			fmt.Println("Connection acknowledged.")
			var qMap = map[string]string{
				"query": query,
			}

			// Send the subscribe message with query
			var subscribe = GraphQLSubscriptionMessage{
				ID:      uuid.NewString(),
				Type:    "subscribe",
				Payload: qMap,
			}
			err := conn.WriteJSON(subscribe)
			if err != nil {
				log.Fatal("Error sending subscribe message:", err)
			}

		case "next":
			data, err := json.Marshal(msg.Payload)
			if err != nil {
				log.Fatal("Error converting response", err)
			}
			fmt.Println("Data received:", data)
			// process the message
		case "complete":
			fmt.Println("Subscription complete.")
			return
		case "error":
			fmt.Println("Error:", msg.Payload)
		default:
			fmt.Println("Unknown message type:", msg.Type)
		}
	}
}
package main

import (
	"encoding/json"
	"fmt"
	"log"
	"net/http"
	"net/url"

	"github.com/google/uuid"
	"github.com/gorilla/websocket"
)

// Connection Init message structure
type InitMessage struct {
	Type    string            `json:"type"`
	Payload map[string]string `json:"payload"`
}

// GraphQLSubscriptionMessage represents the structure of a GraphQL WebSocket message
type GraphQLSubscriptionMessage struct {
	Type    string            `json:"type"`
	ID      string            `json:"id,omitempty"`
	Payload map[string]string `json:"payload,omitempty"`
}

func main() {
	serverURL := url.URL{Scheme: "wss", Host: "graphql.pointonenav.com", Path: "/subscriptions"}
	// Prepare the WebSocket handshake request headers
	headers := http.Header{}
	headers.Add("Sec-WebSocket-Protocol", "graphql-transport-ws")

	// Connect to the GraphQL WebSocket endpoint
	conn, _, err := websocket.DefaultDialer.Dial(serverURL.String(), headers)
	if err != nil {
		log.Fatal("Error connecting to WebSocket:", err)
	}
	defer conn.Close()

	TOKEN := "YOUR_PERSONAL_ACCESS_TOKEN"
	auth := map[string]string{
		"Authorization": "Bearer " + TOKEN,
	}

	var init = InitMessage{
		Type:    "connection_init",
		Payload: auth,
	}

	// Initialize the websocket connection
	if err := conn.WriteJSON(init); err != nil {
		log.Fatal("Error sending connection_init message:", err)
	}

	// Read and print messages from the server
	for {
		_, message, err := conn.ReadMessage()
		if err != nil {
			log.Fatal("Error reading message from server:", err)
			break
		}

		fmt.Println("Received message from server:", string(message))

		var msg GraphQLSubscriptionMessage
		json.Unmarshal(message, &msg)

		switch msg.Type {
		case "connection_ack":
			query := `subscription {
				device(id: "YOUR_DEVICE_ID_HERE"){
					id
					label
					connectionStatus
				}
			}`

			fmt.Println("Connection acknowledged.")
			var qMap = map[string]string{
				"query": query,
			}

			// Send the subscribe message with query
			var subscribe = GraphQLSubscriptionMessage{
				ID:      uuid.NewString(),
				Type:    "subscribe",
				Payload: qMap,
			}
			err := conn.WriteJSON(subscribe)
			if err != nil {
				log.Fatal("Error sending subscribe message:", err)
			}

		case "next":
			data, err := json.Marshal(msg.Payload)
			if err != nil {
				log.Fatal("Error converting response", err)
			}
			fmt.Println("Data received:", data)
			// process the message
		case "complete":
			fmt.Println("Subscription complete.")
			return
		case "error":
			fmt.Println("Error:", msg.Payload)
		default:
			fmt.Println("Unknown message type:", msg.Type)
		}
	}
}

devices

The devices subscription establishes a WebSocket connection to receive state changes for all the current user's devices.

graphql
type Subscription {
    """
    WebSocket connection to receive state changes for all current user's devices
    """
    devices: [Device!]
}
type Subscription {
    """
    WebSocket connection to receive state changes for all current user's devices
    """
    devices: [Device!]
}

This subscription does not require any parameters.

py
async def query_devices():
    query = {
        "id": str(uuid.uuid4()),  # Unique ID for the subscription
        "type": "subscribe",
        "payload": {
            "query": """
                subscription {
                    devices {
                        id
                        lastPosition {
                            position {
                                llaDec {
                                    lat
                                    lon
                                    alt
                                }
                            }
                            timestamp
                        }
                        connectionStatus
                    }
                }
            """
        }
    }

    init_message = {
        "type": "connection_init",
        "payload": {
            "Authorization": "Bearer YOUR_PERSONAL_ACCESS_TOKEN"
        }
    }

    uri = "wss://graphql.pointonenav.com/subscriptions"

    async with websockets.connect(uri) as websocket:  # Connect using the graphql-transport-ws protocol
        await websocket.send(json.dumps(init_message))

        while True:
            response_str = await websocket.recv()
            connect_response = json.loads(response_str)

            # Handle different message types here (connection_ack, data, error, etc.)
            if connect_response["type"] == 'connection_ack':
                # Connection acknowledged, now send subscription request
                subscribe_msg = json.dumps(query)
                print("Subscribe: ", subscribe_msg)
                await websocket.send(subscribe_msg)
                device_msg_str = await websocket.recv()
                device_response = json.loads(device_msg_str)
            else:
                print("Connection Error", json.dumps(connect_response))
                break

            while True:
                if device_response["type"] == 'next':
                    # Handle incoming data
                    device_update = device_response['payload']['data']['devices']
                    device_msg = json.dumps(device_update)
                    print("Next: ", device_msg)
                    # Process the device update here....
                elif device_response["type"] == 'error':
                    # Handle err data
                    err_msg = connect_response['payload']
                    print("Message Error: ", json.dumps(err_msg))
                elif device_response["type"] == "complete":
                    break

asyncio.get_event_loop().run_until_complete(query_devices())
async def query_devices():
    query = {
        "id": str(uuid.uuid4()),  # Unique ID for the subscription
        "type": "subscribe",
        "payload": {
            "query": """
                subscription {
                    devices {
                        id
                        lastPosition {
                            position {
                                llaDec {
                                    lat
                                    lon
                                    alt
                                }
                            }
                            timestamp
                        }
                        connectionStatus
                    }
                }
            """
        }
    }

    init_message = {
        "type": "connection_init",
        "payload": {
            "Authorization": "Bearer YOUR_PERSONAL_ACCESS_TOKEN"
        }
    }

    uri = "wss://graphql.pointonenav.com/subscriptions"

    async with websockets.connect(uri) as websocket:  # Connect using the graphql-transport-ws protocol
        await websocket.send(json.dumps(init_message))

        while True:
            response_str = await websocket.recv()
            connect_response = json.loads(response_str)

            # Handle different message types here (connection_ack, data, error, etc.)
            if connect_response["type"] == 'connection_ack':
                # Connection acknowledged, now send subscription request
                subscribe_msg = json.dumps(query)
                print("Subscribe: ", subscribe_msg)
                await websocket.send(subscribe_msg)
                device_msg_str = await websocket.recv()
                device_response = json.loads(device_msg_str)
            else:
                print("Connection Error", json.dumps(connect_response))
                break

            while True:
                if device_response["type"] == 'next':
                    # Handle incoming data
                    device_update = device_response['payload']['data']['devices']
                    device_msg = json.dumps(device_update)
                    print("Next: ", device_msg)
                    # Process the device update here....
                elif device_response["type"] == 'error':
                    # Handle err data
                    err_msg = connect_response['payload']
                    print("Message Error: ", json.dumps(err_msg))
                elif device_response["type"] == "complete":
                    break

asyncio.get_event_loop().run_until_complete(query_devices())
typescript
import WebSocket from 'ws';
import {v4 as uuidv4} from "uuid";

const queryDevices = async () => {
    const query = {
        id: uuidv4(), // Unique Connection Identifier 
        type: "subscribe",
        payload: {
            query: `
                subscription {
                    devices {
                        id
                        lastPosition {
                            position {
                                llaDec {
                                    lat
                                    lon
                                    alt
                                }
                            }
                            timestamp
                        }
                        connectionStatus
                    }
                }
            `
        }
    };

    const initMessage = {
        type: "connection_init",
        payload: {
            Authorization: "Bearer YOUR_PERSONAL_ACCESS_TOKEN"
        }
    };

    const uri = "wss://graphql.pointonenav.com/subscriptions";
    const websocket = new WebSocket(uri);

    websocket.on('open', async () => {
        websocket.send(JSON.stringify(initMessage));
    });

    websocket.on('message', (message: string) => {
        websocket.on('message', (message: string) => {
            const {type, payload} = JSON.parse(message);
            if (type === 'connection_ack') {
                console.log('Connected!')
                websocket.send(JSON.stringify(query));
            } else if (type === 'next') {
                console.log('Next: ' + JSON.stringify(payload))
            } else if (type === 'error') {
                console.log('Error: ' + JSON.stringify(payload))
            }
        });
    });
};

queryDevices();
import WebSocket from 'ws';
import {v4 as uuidv4} from "uuid";

const queryDevices = async () => {
    const query = {
        id: uuidv4(), // Unique Connection Identifier 
        type: "subscribe",
        payload: {
            query: `
                subscription {
                    devices {
                        id
                        lastPosition {
                            position {
                                llaDec {
                                    lat
                                    lon
                                    alt
                                }
                            }
                            timestamp
                        }
                        connectionStatus
                    }
                }
            `
        }
    };

    const initMessage = {
        type: "connection_init",
        payload: {
            Authorization: "Bearer YOUR_PERSONAL_ACCESS_TOKEN"
        }
    };

    const uri = "wss://graphql.pointonenav.com/subscriptions";
    const websocket = new WebSocket(uri);

    websocket.on('open', async () => {
        websocket.send(JSON.stringify(initMessage));
    });

    websocket.on('message', (message: string) => {
        websocket.on('message', (message: string) => {
            const {type, payload} = JSON.parse(message);
            if (type === 'connection_ack') {
                console.log('Connected!')
                websocket.send(JSON.stringify(query));
            } else if (type === 'next') {
                console.log('Next: ' + JSON.stringify(payload))
            } else if (type === 'error') {
                console.log('Error: ' + JSON.stringify(payload))
            }
        });
    });
};

queryDevices();
go
package main

import (
	"encoding/json"
	"fmt"
	"log"
	"net/http"
	"net/url"

	"github.com/google/uuid"
	"github.com/gorilla/websocket"
)

const query = `subscription {
    devices {
      id
      label
      connectionStatus
    }
  }`

// Connection Init message structure
type InitMessage struct {
	Type    string            `json:"type"`
	Payload map[string]string `json:"payload"`
}

// GraphQLSubscriptionMessage represents the structure of a GraphQL WebSocket message
type GraphQLSubscriptionMessage struct {
	Type    string            `json:"type"`
	ID      string            `json:"id,omitempty"`
	Payload map[string]string `json:"payload,omitempty"`
}

func main() {
    serverURL := url.URL{Scheme: "wss", Host: "graphql.pointonenav.com", Path: "/subscriptions"}

    // Prepare the WebSocket handshake request headers
    headers := http.Header{}
    headers.Add("Sec-WebSocket-Protocol", "graphql-transport-ws")

    // Connect to the GraphQL WebSocket endpoint
    conn, _, err := websocket.DefaultDialer.Dial(serverURL.String(), headers)
    if err != nil {
        log.Fatal("Error connecting to WebSocket:", err)
    }
    defer conn.Close()

    TOKEN := "YOUR_PERSONAL_ACCESS_TOKEN"
    auth := map[string]string{
        "Authorization": "Bearer " + TOKEN,
    }

    var init = InitMessage{
        Type:    "connection_init",
        Payload: auth,
    }

    // Initialize the websocket connection
    if err := conn.WriteJSON(init); err != nil {
        log.Fatal("Error sending connection_init message:", err)
    }

    // Read and print messages from the server
    for {
        _, message, err := conn.ReadMessage()
        if err != nil {
            log.Fatal("Error reading message from server:", err)
            break
        }

        fmt.Println("Received message from server:", string(message))

        var msg GraphQLSubscriptionMessage
        json.Unmarshal(message, &msg)

        switch msg.Type {
        case "connection_ack":
            fmt.Println("Connection acknowledged.")
            var qMap = map[string]string{
                "query": query,
            }

            // Send the subscribe message with query
            var subscribe = GraphQLSubscriptionMessage{
                ID:      uuid.NewString(),
                Type:    "subscribe",
                Payload: qMap,
            }
            err := conn.WriteJSON(subscribe)
        if err != nil {
            log.Fatal("Error sending subscribe message:", err)
        }

        case "next":
            data, err := json.Marshal(msg.Payload)
            if err != nil {
                log.Fatal("Error converting response", err)
            }
            fmt.Println("Data received:", data)
            // process the message
        case "complete":
            fmt.Println("Subscription complete.")
            return
        case "error":
            fmt.Println("Error:", msg.Payload)
        default:
            fmt.Println("Unknown message type:", msg.Type)
        }
    }
}
package main

import (
	"encoding/json"
	"fmt"
	"log"
	"net/http"
	"net/url"

	"github.com/google/uuid"
	"github.com/gorilla/websocket"
)

const query = `subscription {
    devices {
      id
      label
      connectionStatus
    }
  }`

// Connection Init message structure
type InitMessage struct {
	Type    string            `json:"type"`
	Payload map[string]string `json:"payload"`
}

// GraphQLSubscriptionMessage represents the structure of a GraphQL WebSocket message
type GraphQLSubscriptionMessage struct {
	Type    string            `json:"type"`
	ID      string            `json:"id,omitempty"`
	Payload map[string]string `json:"payload,omitempty"`
}

func main() {
    serverURL := url.URL{Scheme: "wss", Host: "graphql.pointonenav.com", Path: "/subscriptions"}

    // Prepare the WebSocket handshake request headers
    headers := http.Header{}
    headers.Add("Sec-WebSocket-Protocol", "graphql-transport-ws")

    // Connect to the GraphQL WebSocket endpoint
    conn, _, err := websocket.DefaultDialer.Dial(serverURL.String(), headers)
    if err != nil {
        log.Fatal("Error connecting to WebSocket:", err)
    }
    defer conn.Close()

    TOKEN := "YOUR_PERSONAL_ACCESS_TOKEN"
    auth := map[string]string{
        "Authorization": "Bearer " + TOKEN,
    }

    var init = InitMessage{
        Type:    "connection_init",
        Payload: auth,
    }

    // Initialize the websocket connection
    if err := conn.WriteJSON(init); err != nil {
        log.Fatal("Error sending connection_init message:", err)
    }

    // Read and print messages from the server
    for {
        _, message, err := conn.ReadMessage()
        if err != nil {
            log.Fatal("Error reading message from server:", err)
            break
        }

        fmt.Println("Received message from server:", string(message))

        var msg GraphQLSubscriptionMessage
        json.Unmarshal(message, &msg)

        switch msg.Type {
        case "connection_ack":
            fmt.Println("Connection acknowledged.")
            var qMap = map[string]string{
                "query": query,
            }

            // Send the subscribe message with query
            var subscribe = GraphQLSubscriptionMessage{
                ID:      uuid.NewString(),
                Type:    "subscribe",
                Payload: qMap,
            }
            err := conn.WriteJSON(subscribe)
        if err != nil {
            log.Fatal("Error sending subscribe message:", err)
        }

        case "next":
            data, err := json.Marshal(msg.Payload)
            if err != nil {
                log.Fatal("Error converting response", err)
            }
            fmt.Println("Data received:", data)
            // process the message
        case "complete":
            fmt.Println("Subscription complete.")
            return
        case "error":
            fmt.Println("Error:", msg.Payload)
        default:
            fmt.Println("Unknown message type:", msg.Type)
        }
    }
}

Type Reference

Enums

ConnectionStatus

graphql
enum ConnectionStatus {
    UNKNOWN,
    GOOD,
    NO_CONNECTION,
    BAD_POSITION,
    NO_POSITION
}
enum ConnectionStatus {
    UNKNOWN,
    GOOD,
    NO_CONNECTION,
    BAD_POSITION,
    NO_POSITION
}

TokenRole

graphql
enum TokenRole {
    ROLE_READ,
    ROLE_READ_WRITE
}
enum TokenRole {
    ROLE_READ,
    ROLE_READ_WRITE
}

Scalars

DateTime

LocalDateTime

Objects

Device

graphql
type Device {
    id: ID!
    account: Account!
    label: String!
    lastPosition: PositionHistory!
    type: String
    services: DeviceServices!
    tags: [Tag!]
    createdAt: DateTime!
    updatedAt: DateTime
}
type Device {
    id: ID!
    account: Account!
    label: String!
    lastPosition: PositionHistory!
    type: String
    services: DeviceServices!
    tags: [Tag!]
    createdAt: DateTime!
    updatedAt: DateTime
}

DevicePage

A page of results from a device query

graphql
type DevicePage implements PageResult {
    content: [Device!]
    pageNumber: Int!
    pageSize: Int!
    offset: Int!
    totalElements: Int!
    totalPages: Int!
    first: Boolean!
    last: Boolean!
}
type DevicePage implements PageResult {
    content: [Device!]
    pageNumber: Int!
    pageSize: Int!
    offset: Int!
    totalElements: Int!
    totalPages: Int!
    first: Boolean!
    last: Boolean!
}

PersonalAccessToken

graphql
type PersonalAccessToken {
    name: String!
    description: String
    createdAt: DateTime!
}
type PersonalAccessToken {
    name: String!
    description: String
    createdAt: DateTime!
}

DeviceServices

Information about active services attached to a device

graphql
type DeviceServices {
    rtk: RtkService
}
type DeviceServices {
    rtk: RtkService
}

NTRIP

NTRIP protocol credentials

graphql
type NTRIP {
    login: String!
    password: String!
}
type NTRIP {
    login: String!
    password: String!
}

Position

Geo-Positional data in a variety of formats

graphql
type Position {
    llaDMS: PositionLLADMS
    llaDec: PositionLLADD
    ecef: PositionECEF
}
type Position {
    llaDMS: PositionLLADMS
    llaDec: PositionLLADD
    ecef: PositionECEF
}

PositionLLADMS

Geo-Position as converted from Degrees, Minutes, Seconds

graphql
type PositionLLADMS {
    lat: String
    lon: String
    alt: String
}
type PositionLLADMS {
    lat: String
    lon: String
    alt: String
}

PositionLLADD

Geo-Position as Latitude, Longitude, Altitude

graphql
type PositionLLADD {
    lat: String
    lon: String
    alt: String
}
type PositionLLADD {
    lat: String
    lon: String
    alt: String
}

PositionECEF

Geo-Position as Earth-Fixed, Earth Centric

graphql
type PositionECEF {
    x: Float
    y: Float
    z: Float
}
type PositionECEF {
    x: Float
    y: Float
    z: Float
}

PositionHistory

Historical positional data for a specific Device (if applicable)

graphql
type PositionHistory {
    timestamp: LocalDateTime
    position: Position
}
type PositionHistory {
    timestamp: LocalDateTime
    position: Position
}

RTKService

graphql
type RtkService {
    enabled: Boolean!
    polarisKey: String!
    ntrip: NTRIP!
    connectionStatus: ConnectionStatus!
}
type RtkService {
    enabled: Boolean!
    polarisKey: String!
    ntrip: NTRIP!
    connectionStatus: ConnectionStatus!
}

Tag

Key-Value Pair metadata to aid in classification of Devices

graphql
type Tag {
    key: String!
    value: String
    createdAt: DateTime!
    updatedAt: DateTime
}
type Tag {
    key: String!
    value: String
    createdAt: DateTime!
    updatedAt: DateTime
}

Input Types

DeviceInput

Device Input for create/update requests

graphql
input DeviceInput {
    id: ID
    label: String
    type: String
    enabled: Boolean
}
input DeviceInput {
    id: ID
    label: String
    type: String
    enabled: Boolean
}

TagInput

Tag input for create/update requests

graphql
input TagInput {
    key: String
    value: String
    ids: [ID!]
}
input TagInput {
    key: String
    value: String
    ids: [ID!]
}

DeviceFilter

The search input to be submitted to filterable device queries

graphql
input DeviceFilter {
    type: String
    label: StringConditional
    status: String
    tag: TagFilter
    and: [DeviceFilter]
    or: [DeviceFilter]
    not: [DeviceFilter]
}
input DeviceFilter {
    type: String
    label: StringConditional
    status: String
    tag: TagFilter
    and: [DeviceFilter]
    or: [DeviceFilter]
    not: [DeviceFilter]
}

StringConditional

Defines String based operations for conditionals in filters

graphql
input StringConditional {
    eq: String
    ne: String
}
input StringConditional {
    eq: String
    ne: String
}

TagFilter

Tag Filter used in queries

graphql
input TagFilter {
    key: String
    value: StringConditional
}
input TagFilter {
    key: String
    value: StringConditional
}

Interfaces

PageResult

Any page-able list

graphql
interface PageResult {
    pageNumber: Int!
    pageSize: Int!
    offset: Int!
    totalElements: Int!
    totalPages: Int!
    first: Boolean!
    last: Boolean!
}
interface PageResult {
    pageNumber: Int!
    pageSize: Int!
    offset: Int!
    totalElements: Int!
    totalPages: Int!
    first: Boolean!
    last: Boolean!
}