The Graphman GraphQL API provides programmatic access to Graph Node management operations. It offers an alternative to the CLI for deployment management, status monitoring, and administrative tasks.
Overview
The GraphQL API enables you to:
Query deployment information and status
Pause and resume subgraph indexing
Restart deployments
Monitor long-running operations
Integrate Graph Node management into your tooling
The Graphman server should never be exposed externally . It provides privileged operations that could severely impact your indexer if accessed by an attacker.
Configuration
The Graphman GraphQL server is only started when the GRAPHMAN_SERVER_AUTH_TOKEN environment variable is set.
Environment Variables
GRAPHMAN_SERVER_AUTH_TOKEN
Authentication token for GraphQL requests. The server will not start without this variable.
Port number for the GraphQL server
Example Configuration
export GRAPHMAN_SERVER_AUTH_TOKEN = "your-secure-token-here"
export GRAPHMAN_PORT = 8050
# Start Graph Node with Graphman API enabled
graph-node --config config.toml
Authentication
All GraphQL requests must include the authentication token in the Authorization header:
curl -X POST http://127.0.0.1:8050/graphql \
-H "Authorization: Bearer your-secure-token-here" \
-H "Content-Type: application/json" \
-d '{"query":"{ __typename }"}'
GraphQL Playground
When the server is running, access the interactive GraphQL playground at:
The playground port matches your GRAPHMAN_PORT setting (default: 8050).
Setting Up Authentication in Playground
To use the playground, you must configure the authorization header:
Open the playground in your browser
Locate the HTTP Headers section at the bottom of the page
Add the authorization header:
{
"Authorization" : "Bearer your-secure-token-here"
}
The playground is the best place to explore the full schema, available queries and mutations, and their documentation.
Available Operations
Deployment Info
Retrieve detailed information about one or multiple deployments.
query {
deployment {
info ( deployment : { hash : "QmfWRZCjT8pri4Amey3e3mb2Bga75Vuh2fPYyNVnmPYL66" }) {
id
hash
namespace
shard
active
chain
nodeId
status {
isPaused
isSynced
health
earliestBlockNumber
latestBlock {
hash
number
}
chainHeadBlock {
hash
number
}
}
}
}
}
Deployment Selection
You can query deployments using different selectors:
By Hash
By Name
All Deployments
query {
deployment {
info ( deployment : { hash : "QmfWRZCjT8pri4Amey3e3mb2Bga75Vuh2fPYyNVnmPYL66" }) {
status { isPaused }
}
}
}
query {
deployment {
info ( deployment : { name : "author/subgraph-name" }) {
status { isPaused }
}
}
}
query {
deployment {
info {
hash
status { isPaused }
}
}
}
Status Fields
Whether the deployment is currently paused
Whether the deployment has synced to the current chain head
Deployment health status: HEALTHY, UNHEALTHY, or FAILED
The earliest indexed block number
The most recently indexed block
The current blockchain head block
Pause Deployment
Temporarily stops indexing for a deployment without removing any data.
Mutation
Success Response
Error Response
mutation {
deployment {
pause ( deployment : { hash : "QmfWRZCjT8pri4Amey3e3mb2Bga75Vuh2fPYyNVnmPYL66" }) {
success
message
}
}
}
Use Cases
Pause deployments during planned maintenance or RPC provider changes: mutation {
deployment {
pause ( deployment : { name : "author/subgraph-name" }) {
success
}
}
}
Temporarily pause resource-intensive subgraphs during high-load periods: mutation PauseMultiple {
sg1 : deployment {
pause ( deployment : { hash : "Qm...1" }) { success }
}
sg2 : deployment {
pause ( deployment : { hash : "Qm...2" }) { success }
}
}
Pause a deployment to investigate issues without affecting other subgraphs: mutation {
deployment {
pause ( deployment : { hash : "QmProblematic..." }) {
success
message
}
}
}
A deployment cannot be paused if it’s already in a paused state. Check the isPaused field before attempting to pause.
Resume Deployment
Resumes indexing for a previously paused deployment.
Mutation
Success Response
Error Response
mutation {
deployment {
resume ( deployment : { hash : "QmfWRZCjT8pri4Amey3e3mb2Bga75Vuh2fPYyNVnmPYL66" }) {
success
message
}
}
}
Example Workflow
# Step 1: Check current status
query {
deployment {
info ( deployment : { hash : "Qm..." }) {
status { isPaused }
}
}
}
# Step 2: Resume if paused
mutation {
deployment {
resume ( deployment : { hash : "Qm..." }) {
success
}
}
}
# Step 3: Verify resumed
query {
deployment {
info ( deployment : { hash : "Qm..." }) {
status { isPaused }
}
}
}
Restart Deployment
Pauses a deployment and automatically resumes it after a delay (default: 20 seconds). This is useful for forcing a fresh sync from a specific block.
This is a long-running operation . The mutation returns immediately with an execution ID that you can use to track progress.
mutation {
deployment {
restart ( deployment : { hash : "QmfWRZCjT8pri4Amey3e3mb2Bga75Vuh2fPYyNVnmPYL66" }) {
id
}
}
}
Tracking Execution Status
Use the returned execution ID to monitor the restart operation:
Query Status
Running
Succeeded
Failed
query {
execution {
info ( id : "550e8400-e29b-41d4-a716-446655440000" ) {
status
errorMessage
startedAt
completedAt
}
}
}
Execution Status Values
Operation is queued but not yet started
Operation is currently executing
Operation completed successfully
Operation failed with an error
Polling for Completion
async function waitForRestart ( executionId ) {
while ( true ) {
const response = await fetch ( 'http://127.0.0.1:8050/graphql' , {
method: 'POST' ,
headers: {
'Authorization' : 'Bearer your-token' ,
'Content-Type' : 'application/json' ,
},
body: JSON . stringify ({
query: `
query {
execution {
info(id: " ${ executionId } ") {
status
errorMessage
}
}
}
`
})
});
const data = await response . json ();
const status = data . data . execution . info . status ;
if ( status === 'SUCCEEDED' ) {
console . log ( 'Restart completed successfully' );
break ;
} else if ( status === 'FAILED' ) {
console . error ( 'Restart failed:' , data . data . execution . info . errorMessage );
break ;
}
// Wait 2 seconds before next poll
await new Promise ( resolve => setTimeout ( resolve , 2000 ));
}
}
Long-Running Operations
Some operations (like restart) execute asynchronously in the background. These operations:
Return immediately with a unique execution ID
Execute in the background
Can be monitored using the execution.info query
Benefits
Non-Blocking Your client doesn’t need to maintain a long-lived connection
Resumable You can disconnect and check status later using the execution ID
Transparent Full visibility into operation progress and errors
Reliable Operations continue even if the client disconnects
Integration Examples
Python
import requests
import time
GRAPHMAN_URL = "http://127.0.0.1:8050/graphql"
AUTH_TOKEN = "your-secure-token-here"
def graphql_request ( query , variables = None ):
headers = {
"Authorization" : f "Bearer { AUTH_TOKEN } " ,
"Content-Type" : "application/json"
}
response = requests.post(
GRAPHMAN_URL ,
json = { "query" : query, "variables" : variables},
headers = headers
)
return response.json()
# Check deployment status
status_query = """
query($hash: String!) {
deployment {
info(deployment: { hash: $hash }) {
status {
isPaused
isSynced
health
}
}
}
}
"""
result = graphql_request(status_query, {
"hash" : "QmfWRZCjT8pri4Amey3e3mb2Bga75Vuh2fPYyNVnmPYL66"
})
print (result[ "data" ][ "deployment" ][ "info" ][ 0 ][ "status" ])
# Pause deployment
pause_mutation = """
mutation($hash: String!) {
deployment {
pause(deployment: { hash: $hash }) {
success
message
}
}
}
"""
result = graphql_request(pause_mutation, {
"hash" : "QmfWRZCjT8pri4Amey3e3mb2Bga75Vuh2fPYyNVnmPYL66"
})
if result[ "data" ][ "deployment" ][ "pause" ][ "success" ]:
print ( "Deployment paused successfully" )
Node.js
const fetch = require ( 'node-fetch' );
const GRAPHMAN_URL = 'http://127.0.0.1:8050/graphql' ;
const AUTH_TOKEN = 'your-secure-token-here' ;
async function graphqlRequest ( query , variables = {}) {
const response = await fetch ( GRAPHMAN_URL , {
method: 'POST' ,
headers: {
'Authorization' : `Bearer ${ AUTH_TOKEN } ` ,
'Content-Type' : 'application/json' ,
},
body: JSON . stringify ({ query , variables }),
});
return await response . json ();
}
// Restart deployment and wait for completion
async function restartDeployment ( hash ) {
// Start restart
const restartMutation = `
mutation($hash: String!) {
deployment {
restart(deployment: { hash: $hash }) {
id
}
}
}
` ;
const restartResult = await graphqlRequest ( restartMutation , { hash });
const executionId = restartResult . data . deployment . restart . id ;
console . log ( `Restart initiated with ID: ${ executionId } ` );
// Poll for completion
const statusQuery = `
query($id: String!) {
execution {
info(id: $id) {
status
errorMessage
}
}
}
` ;
while ( true ) {
const statusResult = await graphqlRequest ( statusQuery , { id: executionId });
const { status , errorMessage } = statusResult . data . execution . info ;
if ( status === 'SUCCEEDED' ) {
console . log ( 'Restart completed successfully' );
break ;
} else if ( status === 'FAILED' ) {
console . error ( `Restart failed: ${ errorMessage } ` );
throw new Error ( errorMessage );
}
console . log ( `Status: ${ status } ` );
await new Promise ( resolve => setTimeout ( resolve , 2000 ));
}
}
// Usage
restartDeployment ( 'QmfWRZCjT8pri4Amey3e3mb2Bga75Vuh2fPYyNVnmPYL66' )
. then (() => console . log ( 'Done' ))
. catch ( err => console . error ( 'Error:' , err ));
cURL
# Check deployment status
curl -X POST http://127.0.0.1:8050/graphql \
-H "Authorization: Bearer your-secure-token-here" \
-H "Content-Type: application/json" \
-d '{
"query": "query($hash: String!) { deployment { info(deployment: { hash: $hash }) { status { isPaused isSynced health } } } }",
"variables": {
"hash": "QmfWRZCjT8pri4Amey3e3mb2Bga75Vuh2fPYyNVnmPYL66"
}
}'
# Pause deployment
curl -X POST http://127.0.0.1:8050/graphql \
-H "Authorization: Bearer your-secure-token-here" \
-H "Content-Type: application/json" \
-d '{
"query": "mutation($hash: String!) { deployment { pause(deployment: { hash: $hash }) { success message } } }",
"variables": {
"hash": "QmfWRZCjT8pri4Amey3e3mb2Bga75Vuh2fPYyNVnmPYL66"
}
}'
# Resume deployment
curl -X POST http://127.0.0.1:8050/graphql \
-H "Authorization: Bearer your-secure-token-here" \
-H "Content-Type: application/json" \
-d '{
"query": "mutation($hash: String!) { deployment { resume(deployment: { hash: $hash }) { success message } } }",
"variables": {
"hash": "QmfWRZCjT8pri4Amey3e3mb2Bga75Vuh2fPYyNVnmPYL66"
}
}'
Security Best Practices
The Graphman server should only be accessible from trusted internal networks:
Bind to localhost (127.0.0.1) only
Use firewall rules to restrict access
Never expose to the public internet
Consider using VPN or SSH tunnels for remote access
Change your GRAPHMAN_SERVER_AUTH_TOKEN periodically: # Generate a secure token
openssl rand -hex 32
# Update environment variable
export GRAPHMAN_SERVER_AUTH_TOKEN = "new-token-here"
# Restart Graph Node
systemctl restart graph-node
Generate cryptographically secure tokens: # Good: Strong random token
openssl rand -base64 32
# Bad: Weak predictable token
echo "admin123" # Never do this!
Log all Graphman API access and monitor for suspicious activity:
Track failed authentication attempts
Monitor unusual operation patterns
Alert on destructive operations
Maintain audit logs
Principle of Least Privilege
Only grant Graphman API access to operators who need it
Use separate tokens for different automation systems
Implement token revocation when access is no longer needed
Error Handling
Common Errors
{
"errors" : [
{
"message" : "Unauthorized" ,
"extensions" : {
"code" : "UNAUTHENTICATED"
}
}
]
}
Solution : Verify your Authorization header includes the correct token.
{
"data" : {
"deployment" : {
"pause" : {
"success" : false ,
"message" : "Deployment not found"
}
}
}
}
Solution : Check the deployment hash or name is correct using the info query.
{
"data" : {
"deployment" : {
"pause" : {
"success" : false ,
"message" : "Deployment is already paused"
}
}
}
}
Solution : Check current status before attempting pause/resume operations.
{
"data" : {
"execution" : {
"info" : null
}
}
}
Solution : Verify the execution ID is correct. Execution records may expire after completion.
Future Operations
Additional Graphman commands will be added to the GraphQL API over time. Always check the GraphQL playground for the latest schema and available operations.
Operations being considered for future releases:
Deployment assignment and unassignment
Unused deployment management
Chain block verification
Call cache management
Bulk operations on multiple deployments
Check the GraphQL playground regularly to discover new features as they become available.
See Also