Documentation Index
Fetch the complete documentation index at: https://mintlify.com/OpsMill/infrahub/llms.txt
Use this file to discover all available pages before exploring further.
The GraphQL API is the primary interface for interacting with Infrahub. It provides a flexible, type-safe way to query and mutate infrastructure data with support for branching, time-travel queries, and real-time subscriptions.
Endpoint
URL Pattern: /graphql/{branch_name}
Examples:
/graphql/main - Main branch
/graphql/feature-network-updates - Feature branch
Making Requests
HTTP POST
Send GraphQL queries via HTTP POST with JSON body:
curl -X POST http://localhost:8000/graphql/main \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{
"query": "query { InfraDevice { edges { node { id name { value } } } } }"
}'
With Variables
curl -X POST http://localhost:8000/graphql/main \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{
"query": "query GetDevice($name: String!) { InfraDevice(name__value: $name) { edges { node { id name { value } } } } }",
"variables": { "name": "router-01" }
}'
With Operation Name
curl -X POST http://localhost:8000/graphql/main \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{
"query": "query GetDevices { InfraDevice { edges { node { id } } } } query GetSites { InfraSite { edges { node { id } } } }",
"operationName": "GetDevices"
}'
Time-Travel Queries
Query historical data using the at query parameter:
# Absolute timestamp
curl -X POST "http://localhost:8000/graphql/main?at=2024-01-15T10:30:00Z" \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{"query": "query { InfraDevice { edges { node { id name { value } } } } }"}'
# Relative time (-1 hour)
curl -X POST "http://localhost:8000/graphql/main?at=-1h" \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{"query": "query { InfraDevice { edges { node { id name { value } } } } }"}'
Supported relative time formats:
-30m - 30 minutes ago
-1h - 1 hour ago
-7d - 7 days ago
Note: Mutations are not supported with the at parameter. Infrahub automatically resets at to the current time for mutation operations.
Branch Operations
Query from a Branch
Specify the branch in the URL path:
curl -X POST http://localhost:8000/graphql/feature-branch \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{"query": "query { InfraDevice { edges { node { id name { value } } } } }"}'
Mutations on Branches
All mutations automatically target the branch specified in the URL:
curl -X POST http://localhost:8000/graphql/feature-branch \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{
"query": "mutation { InfraDeviceCreate(data: { name: { value: \"router-02\" } }) { ok object { id } } }"
}'
Real-Time Subscriptions
GraphQL subscriptions enable real-time updates over WebSocket connections.
WebSocket Connection
URL Pattern: ws://localhost:8000/graphql/{branch_name}
Subscriptions use the graphql-ws protocol:
const ws = new WebSocket('ws://localhost:8000/graphql/main', 'graphql-ws');
ws.onopen = () => {
// Initialize connection
ws.send(JSON.stringify({ type: 'connection_init' }));
// Start subscription
ws.send(JSON.stringify({
id: '1',
type: 'start',
payload: {
query: 'subscription { event { event_type node_id } }'
}
}));
};
ws.onmessage = (event) => {
const message = JSON.parse(event.data);
console.log('Received:', message);
};
Subscription Protocol Messages
Client → Server:
connection_init - Initialize connection
start - Start subscription
stop - Stop subscription
connection_terminate - Close connection
Server → Client:
connection_ack - Connection acknowledged
data - Subscription data
error - Error occurred
complete - Subscription completed
Schema Introspection
Get Schema
Query the GraphQL schema using introspection:
query IntrospectionQuery {
__schema {
types {
name
kind
description
fields {
name
description
type {
name
kind
}
}
}
}
}
query {
__type(name: "InfraDevice") {
name
kind
description
fields {
name
type {
name
kind
}
}
}
}
Common Query Patterns
List All Objects
query {
InfraDevice {
edges {
node {
id
name {
value
}
}
}
}
}
Filter by Attribute
query {
InfraDevice(name__value: "router-01") {
edges {
node {
id
name {
value
}
}
}
}
}
Nested Relationships
query {
InfraDevice {
edges {
node {
id
name {
value
}
site {
node {
id
name {
value
}
}
}
}
}
}
}
query {
InfraDevice(first: 10, after: "cursor") {
pageInfo {
hasNextPage
endCursor
}
edges {
cursor
node {
id
name {
value
}
}
}
}
}
Common Mutations
Create Object
mutation {
InfraDeviceCreate(
data: {
name: { value: "router-01" }
description: { value: "Core router" }
}
) {
ok
object {
id
name {
value
}
}
}
}
Update Object
mutation {
InfraDeviceUpdate(
data: {
id: "<device-id>"
name: { value: "router-01-updated" }
}
) {
ok
object {
id
name {
value
}
}
}
}
Delete Object
mutation {
InfraDeviceDelete(data: { id: "<device-id>" }) {
ok
}
}
Upsert Object
mutation {
InfraDeviceUpsert(
data: {
name: { value: "router-01" }
description: { value: "Core router" }
}
) {
ok
object {
id
}
}
}
Successful Query
{
"data": {
"InfraDevice": {
"edges": [
{
"node": {
"id": "abc123",
"name": {
"value": "router-01"
}
}
}
]
}
}
}
Query with Errors
{
"data": null,
"errors": [
{
"message": "Node not found",
"locations": [
{
"line": 2,
"column": 3
}
],
"path": ["InfraDevice"],
"extensions": {
"code": "NODE_NOT_FOUND"
}
}
]
}
Partial Success
{
"data": {
"InfraDevice": {
"edges": []
}
},
"errors": [
{
"message": "Permission denied for field 'password'",
"path": ["InfraDevice", 0, "password"]
}
]
}
Query Depth and Height
Infrahub tracks query complexity metrics:
- Depth: Maximum nesting level of the query
- Height: Total number of fields requested
See /home/daytona/workspace/source/backend/infrahub/graphql/app.py:281 for metric implementation.
Field Selection
Only request fields you need:
# Good - Only request needed fields
query {
InfraDevice {
edges {
node {
id
name { value }
}
}
}
}
# Avoid - Requesting all fields
query {
InfraDevice {
edges {
node {
id
name { value }
description { value }
# ... all other fields
}
}
}
}
Always use pagination for large datasets:
query {
InfraDevice(first: 50) {
pageInfo {
hasNextPage
endCursor
}
edges {
node {
id
name { value }
}
}
}
}
Metrics and Monitoring
Infrahub exposes Prometheus metrics for GraphQL operations:
graphql_duration - Query execution time
graphql_query_depth - Query depth distribution
graphql_query_height - Query height distribution
graphql_query_errors - Error count
graphql_response_size - Response size in bytes
graphql_query_objects - Number of impacted models
See /home/daytona/workspace/source/backend/infrahub/graphql/metrics.py for implementation.
Error Codes
Common GraphQL error codes:
NODE_NOT_FOUND - Requested node doesn’t exist
PERMISSION_DENIED - Insufficient permissions
VALIDATION_ERROR - Input validation failed
CONSTRAINT_VIOLATION - Uniqueness or other constraint violated
BRANCH_NOT_FOUND - Specified branch doesn’t exist