GraphQL API
Hugin exposes a GraphQL API primarily used by the desktop UI. It provides richer querying capabilities than the REST API for flow data -- multi-field filtering, sorting, pagination, and real-time subscriptions are all available in a single interface.
Endpoint
POST /graphql Execute queries and mutations
GET /graphql GraphQL Playground (interactive browser IDE)
The GraphQL Playground is accessible at http://127.0.0.1:8081/graphql in a browser when the API server is running.
Schema
The schema is built with async-graphql and provides queries, mutations, and subscriptions.
Queries
flows -- List flows with filtering, sorting, and pagination.
query {
flows(filter: {
host: "example.com"
method: "POST"
statusCode: 200
flagged: true
limit: 50
offset: 0
sortBy: "created_at"
sortOrder: "desc"
createdAfter: "2026-03-01T00:00:00Z"
minStatus: 200
maxStatus: 299
hasParams: true
contentType: "application/json"
tag: "auth"
}) {
flows {
id
method
url
host
status
contentType
size
latency
flagged
createdAt
}
total
limit
offset
hasMore
}
}
Filter fields:
method-- Filter by HTTP methodhost-- Filter by hostnameurlContains-- Substring match on URLstatusCode-- Exact status code matchflagged-- Boolean filter for flagged flowsprojectId-- Filter by project UUIDlimit-- Results per page (default: 100)offset-- Pagination offset (default: 0)sortBy-- Sort column:created_at,method,host,status,latency,sizesortOrder--ascordesc(default:desc)createdAfter-- ISO 8601 timestamp lower boundcreatedBefore-- ISO 8601 timestamp upper boundminStatus/maxStatus-- Status code rangeminLatencyMs-- Minimum response latency in millisecondshasParams-- Only flows whose URL contains?contentType-- Content-Type LIKE matchtag-- Flow must have this specific tag
flow -- Get a single flow by ID.
query {
flow(id: "a3f2e1d0-...") {
id
method
url
host
status
requestHeaders
responseHeaders
requestBody
responseBody
latency
flagged
annotations
createdAt
}
}
stats -- Proxy statistics.
query {
stats {
totalFlows
uniqueHosts
totalSize
}
}
Mutations
annotateFlow -- Flag, unflag, comment, or delete a flow.
mutation {
annotateFlow(id: "a3f2...", action: FLAG, comment: "Interesting endpoint") {
id
flagged
}
}
deleteFlow -- Delete a flow by ID.
mutation {
deleteFlow(id: "a3f2...") {
success
}
}
Subscriptions
flowUpdates -- Real-time stream of new flows as they are captured by the proxy.
subscription {
flowUpdates {
id
method
url
host
status
latency
createdAt
}
}
This subscription uses WebSocket transport (graphql-ws protocol). Connect to ws://127.0.0.1:8081/graphql with the graphql-transport-ws subprotocol.
Usage with curl
# Query flows
curl -X POST http://127.0.0.1:8081/graphql \
-H "Content-Type: application/json" \
-d '{"query": "{ flows(filter: { host: \"example.com\", limit: 10 }) { flows { id method url status } total } }"}'
# Get stats
curl -X POST http://127.0.0.1:8081/graphql \
-H "Content-Type: application/json" \
-d '{"query": "{ stats { totalFlows uniqueHosts } }"}'
Usage from JavaScript
const response = await fetch('http://127.0.0.1:8081/graphql', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
query: `
query($host: String) {
flows(filter: { host: $host, limit: 20 }) {
flows { id method url status latency }
total hasMore
}
}
`,
variables: { host: 'api.example.com' }
})
});
const { data } = await response.json();
Authentication
When API authentication is enabled, include credentials in the request:
# Bearer token
curl -X POST http://host:8081/graphql \
-H "Authorization: Bearer your-token" \
-H "Content-Type: application/json" \
-d '{"query": "{ stats { totalFlows } }"}'
# Basic Auth
curl -X POST http://host:8081/graphql \
-u "admin:password" \
-H "Content-Type: application/json" \
-d '{"query": "{ stats { totalFlows } }"}'
REST vs GraphQL
The REST API and GraphQL API share the same underlying data store and service layer. Choose based on your use case:
- REST: Simple CRUD, automation scripts, CI/CD integration, shell scripting
- GraphQL: Complex queries with multiple filters, real-time subscriptions, UI integration, when you need precise control over returned fields