GraphQL Reference
GraphQL API for flexible, graph-based access to your OpenIndustrial workspace.
The GraphQL API provides a flexible alternative to REST, allowing you to request exactly the data you need in a single request.
Endpoint
POST https://api.openindustrial.co/v1/{workspace-id}/graphql
Headers:
Authorization: Bearer YOUR_API_KEY
Content-Type: application/json
Schema Overview
Root Query Type
type Query {
# Queries
queries(surface: String, limit: Int, offset: Int): QueryConnection!
query(name: String!): WarmQuery
# Connections
connections(status: ConnectionStatus): ConnectionConnection!
connection(id: ID!): Connection
# Surfaces
surfaces(limit: Int, offset: Int): SurfaceConnection!
surface(id: ID!): Surface
# Workspace
workspace: Workspace!
}
Core Types
type WarmQuery {
name: String!
description: String
surface: Surface!
kql: String!
schema: QuerySchema!
createdAt: DateTime!
updatedAt: DateTime!
}
type QuerySchema {
columns: [Column!]!
}
type Column {
name: String!
type: String!
}
type Connection {
id: ID!
name: String!
type: ConnectionType!
status: ConnectionStatus!
surfaces: [Surface!]!
stats: ConnectionStats
createdAt: DateTime!
updatedAt: DateTime!
}
type Surface {
id: ID!
name: String!
description: String
connections: [Connection!]!
queries: [WarmQuery!]!
createdAt: DateTime!
updatedAt: DateTime!
}
Enums
enum ConnectionType {
AZURE_IOT_HUB
AZURE_EVENT_HUB
SIMULATOR
}
enum ConnectionStatus {
CONNECTED
CONNECTING
DISCONNECTED
ERROR
}
Queries
List All Queries
query ListQueries {
queries(limit: 10) {
nodes {
name
description
surface {
name
}
updatedAt
}
totalCount
}
}
Response:
{
"data": {
"queries": {
"nodes": [
{
"name": "hourly-temperature-avg",
"description": "Average temperature by hour",
"surface": {
"name": "production-monitoring"
},
"updatedAt": "2026-01-18T14:30:00Z"
}
],
"totalCount": 5
}
}
}
Get Query Details
query GetQuery($name: String!) {
query(name: $name) {
name
description
kql
schema {
columns {
name
type
}
}
surface {
name
connections {
name
status
}
}
}
}
Variables:
{
"name": "hourly-temperature-avg"
}
List Connections with Status
query ActiveConnections {
connections(status: CONNECTED) {
nodes {
id
name
type
status
stats {
messagesReceived
lastMessage
}
surfaces {
name
}
}
}
}
Get Surface with Queries
query GetSurface($id: ID!) {
surface(id: $id) {
name
description
connections {
name
type
status
}
queries {
name
description
schema {
columns {
name
type
}
}
}
}
}
Workspace Overview
query WorkspaceOverview {
workspace {
id
name
stats {
connectionCount
surfaceCount
queryCount
}
}
connections {
totalCount
}
surfaces {
totalCount
}
queries {
totalCount
}
}
Mutations
Execute Query
mutation ExecuteQuery($name: String!, $parameters: JSON) {
executeQuery(name: $name, parameters: $parameters) {
columns
rows
meta {
rowCount
executionTime
}
}
}
Variables:
{
"name": "hourly-temperature-avg",
"parameters": {
"timeRange": "1h"
}
}
Pagination
All list queries support cursor-based pagination:
query PaginatedQueries($cursor: String) {
queries(first: 10, after: $cursor) {
nodes {
name
}
pageInfo {
hasNextPage
endCursor
}
totalCount
}
}
Error Handling
GraphQL errors are returned in the errors field:
{
"data": null,
"errors": [
{
"message": "Query 'my-query' not found",
"path": ["query"],
"extensions": {
"code": "RESOURCE_NOT_FOUND"
}
}
]
}
Common Error Codes
| Code | Description |
|---|---|
UNAUTHORIZED | Invalid/missing API key |
FORBIDDEN | Insufficient permissions |
RESOURCE_NOT_FOUND | Requested resource doesn't exist |
VALIDATION_ERROR | Invalid query or variables |
RATE_LIMITED | Too many requests |
Introspection
Query the schema to discover available types:
query IntrospectionQuery {
__schema {
types {
name
kind
fields {
name
type {
name
}
}
}
}
}
Thinking Tip:
Use GraphQL Playground or tools like Insomnia/Postman with introspection to explore the full schema.
Examples
JavaScript with graphql-request
import { GraphQLClient, gql } from 'graphql-request';
const client = new GraphQLClient(
`https://api.openindustrial.co/v1/${WORKSPACE_ID}/graphql`,
{
headers: {
Authorization: `Bearer ${API_KEY}`,
},
}
);
const query = gql`
query GetQueries {
queries(limit: 5) {
nodes {
name
description
surface {
name
}
}
}
}
`;
const data = await client.request(query);
console.log(data.queries.nodes);
Python with gql
from gql import gql, Client
from gql.transport.requests import RequestsHTTPTransport
transport = RequestsHTTPTransport(
url=f"https://api.openindustrial.co/v1/{WORKSPACE_ID}/graphql",
headers={"Authorization": f"Bearer {API_KEY}"}
)
client = Client(transport=transport, fetch_schema_from_transport=True)
query = gql("""
query GetQueries {
queries(limit: 5) {
nodes {
name
description
}
}
}
""")
result = client.execute(query)
print(result["queries"]["nodes"])
cURL
curl -X POST \
"https://api.openindustrial.co/v1/{workspace-id}/graphql" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"query": "query { queries { nodes { name description } } }"
}'
GraphQL vs REST
| Use Case | Recommended |
|---|---|
| Simple query execution | REST |
| Fetching multiple related resources | GraphQL |
| Exploring data relationships | GraphQL |
| Webhook integrations | REST |
| Simple CRUD operations | REST |
| Complex nested queries | GraphQL |
Related
- REST API Reference - Alternative API
- Reference Overview - Authentication details
- Troubleshooting - Common API issues
On this page
- FrontmatterVersion: 1 DocumentType: Reference Title: "GraphQL" Summary: "Request exactly the fields you need in one call. Covers the schema, queries, mutations, pagination, introspection, and when to prefer REST." Created: 2026-01-19
- GraphQL Reference
- ╰─▶Endpoint
- ╰─▶Schema Overview
- ╰─▶Root Query Type
- ╰─▶Core Types
- ╰─▶Enums
- ╰─▶Queries
- ╰─▶Mutations
- ╰─▶Pagination
- ╰─▶Error Handling
- ╰─▶Introspection
- ╰─▶Examples
- ╰─▶GraphQL vs REST
- ╰─▶Related