> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/graphprotocol/graph-node/llms.txt
> Use this file to discover all available pages before exploring further.

# Graphman GraphQL API

> Manage Graph Node deployments through a GraphQL interface with real-time status monitoring

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

<Warning>
  The Graphman server should **never be exposed externally**. It provides privileged operations that could severely impact your indexer if accessed by an attacker.
</Warning>

## Configuration

The Graphman GraphQL server is only started when the `GRAPHMAN_SERVER_AUTH_TOKEN` environment variable is set.

### Environment Variables

<ParamField path="GRAPHMAN_SERVER_AUTH_TOKEN" type="string" required>
  Authentication token for GraphQL requests. The server will not start without this variable.
</ParamField>

<ParamField path="GRAPHMAN_PORT" type="number" default="8050">
  Port number for the GraphQL server
</ParamField>

### Example Configuration

```bash theme={null}
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:

```bash theme={null}
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:

```
http://127.0.0.1:8050
```

<Info>
  The playground port matches your `GRAPHMAN_PORT` setting (default: 8050).
</Info>

### Setting Up Authentication in Playground

To use the playground, you must configure the authorization header:

1. Open the playground in your browser
2. Locate the **HTTP Headers** section at the bottom of the page
3. Add the authorization header:

```json theme={null}
{
  "Authorization": "Bearer your-secure-token-here"
}
```

<Tip>
  The playground is the best place to explore the full schema, available queries and mutations, and their documentation.
</Tip>

## Available Operations

### Deployment Info

Retrieve detailed information about one or multiple deployments.

<CodeGroup>
  ```graphql Query theme={null}
  query {
    deployment {
      info(deployment: { hash: "QmfWRZCjT8pri4Amey3e3mb2Bga75Vuh2fPYyNVnmPYL66" }) {
        id
        hash
        namespace
        shard
        active
        chain
        nodeId
        status {
          isPaused
          isSynced
          health
          earliestBlockNumber
          latestBlock {
            hash
            number
          }
          chainHeadBlock {
            hash
            number
          }
        }
      }
    }
  }
  ```

  ```json Response theme={null}
  {
    "data": {
      "deployment": {
        "info": [
          {
            "id": 123,
            "hash": "QmfWRZCjT8pri4Amey3e3mb2Bga75Vuh2fPYyNVnmPYL66",
            "namespace": "sgd123",
            "shard": "primary",
            "active": true,
            "chain": "mainnet",
            "nodeId": "default",
            "status": {
              "isPaused": false,
              "isSynced": true,
              "health": "HEALTHY",
              "earliestBlockNumber": 15000000,
              "latestBlock": {
                "hash": "0xabc...",
                "number": 18500000
              },
              "chainHeadBlock": {
                "hash": "0xdef...",
                "number": 18500010
              }
            }
          }
        ]
      }
    }
  }
  ```
</CodeGroup>

#### Deployment Selection

You can query deployments using different selectors:

<Tabs>
  <Tab title="By Hash">
    ```graphql theme={null}
    query {
      deployment {
        info(deployment: { hash: "QmfWRZCjT8pri4Amey3e3mb2Bga75Vuh2fPYyNVnmPYL66" }) {
          status { isPaused }
        }
      }
    }
    ```
  </Tab>

  <Tab title="By Name">
    ```graphql theme={null}
    query {
      deployment {
        info(deployment: { name: "author/subgraph-name" }) {
          status { isPaused }
        }
      }
    }
    ```
  </Tab>

  <Tab title="All Deployments">
    ```graphql theme={null}
    query {
      deployment {
        info {
          hash
          status { isPaused }
        }
      }
    }
    ```
  </Tab>
</Tabs>

#### Status Fields

<ResponseField name="isPaused" type="boolean">
  Whether the deployment is currently paused
</ResponseField>

<ResponseField name="isSynced" type="boolean">
  Whether the deployment has synced to the current chain head
</ResponseField>

<ResponseField name="health" type="enum">
  Deployment health status: `HEALTHY`, `UNHEALTHY`, or `FAILED`
</ResponseField>

<ResponseField name="earliestBlockNumber" type="number">
  The earliest indexed block number
</ResponseField>

<ResponseField name="latestBlock" type="object">
  The most recently indexed block

  <Expandable>
    <ResponseField name="hash" type="string">
      Block hash
    </ResponseField>

    <ResponseField name="number" type="number">
      Block number
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="chainHeadBlock" type="object">
  The current blockchain head block

  <Expandable>
    <ResponseField name="hash" type="string">
      Block hash
    </ResponseField>

    <ResponseField name="number" type="number">
      Block number
    </ResponseField>
  </Expandable>
</ResponseField>

***

### Pause Deployment

Temporarily stops indexing for a deployment without removing any data.

<CodeGroup>
  ```graphql Mutation theme={null}
  mutation {
    deployment {
      pause(deployment: { hash: "QmfWRZCjT8pri4Amey3e3mb2Bga75Vuh2fPYyNVnmPYL66" }) {
        success
        message
      }
    }
  }
  ```

  ```json Success Response theme={null}
  {
    "data": {
      "deployment": {
        "pause": {
          "success": true,
          "message": "Deployment paused successfully"
        }
      }
    }
  }
  ```

  ```json Error Response theme={null}
  {
    "data": {
      "deployment": {
        "pause": {
          "success": false,
          "message": "Deployment is already paused"
        }
      }
    }
  }
  ```
</CodeGroup>

#### Use Cases

<AccordionGroup>
  <Accordion title="Maintenance Windows">
    Pause deployments during planned maintenance or RPC provider changes:

    ```graphql theme={null}
    mutation {
      deployment {
        pause(deployment: { name: "author/subgraph-name" }) {
          success
        }
      }
    }
    ```
  </Accordion>

  <Accordion title="Resource Management">
    Temporarily pause resource-intensive subgraphs during high-load periods:

    ```graphql theme={null}
    mutation PauseMultiple {
      sg1: deployment {
        pause(deployment: { hash: "Qm...1" }) { success }
      }
      sg2: deployment {
        pause(deployment: { hash: "Qm...2" }) { success }
      }
    }
    ```
  </Accordion>

  <Accordion title="Debugging">
    Pause a deployment to investigate issues without affecting other subgraphs:

    ```graphql theme={null}
    mutation {
      deployment {
        pause(deployment: { hash: "QmProblematic..." }) {
          success
          message
        }
      }
    }
    ```
  </Accordion>
</AccordionGroup>

<Warning>
  A deployment cannot be paused if it's already in a paused state. Check the `isPaused` field before attempting to pause.
</Warning>

***

### Resume Deployment

Resumes indexing for a previously paused deployment.

<CodeGroup>
  ```graphql Mutation theme={null}
  mutation {
    deployment {
      resume(deployment: { hash: "QmfWRZCjT8pri4Amey3e3mb2Bga75Vuh2fPYyNVnmPYL66" }) {
        success
        message
      }
    }
  }
  ```

  ```json Success Response theme={null}
  {
    "data": {
      "deployment": {
        "resume": {
          "success": true,
          "message": "Deployment resumed successfully"
        }
      }
    }
  }
  ```

  ```json Error Response theme={null}
  {
    "data": {
      "deployment": {
        "resume": {
          "success": false,
          "message": "Deployment is not paused"
        }
      }
    }
  }
  ```
</CodeGroup>

#### Example Workflow

```graphql theme={null}
# 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.

<Info>
  This is a **long-running operation**. The mutation returns immediately with an execution ID that you can use to track progress.
</Info>

<CodeGroup>
  ```graphql Mutation theme={null}
  mutation {
    deployment {
      restart(deployment: { hash: "QmfWRZCjT8pri4Amey3e3mb2Bga75Vuh2fPYyNVnmPYL66" }) {
        id
      }
    }
  }
  ```

  ```json Response theme={null}
  {
    "data": {
      "deployment": {
        "restart": {
          "id": "550e8400-e29b-41d4-a716-446655440000"
        }
      }
    }
  }
  ```
</CodeGroup>

#### Tracking Execution Status

Use the returned execution ID to monitor the restart operation:

<CodeGroup>
  ```graphql Query Status theme={null}
  query {
    execution {
      info(id: "550e8400-e29b-41d4-a716-446655440000") {
        status
        errorMessage
        startedAt
        completedAt
      }
    }
  }
  ```

  ```json Running theme={null}
  {
    "data": {
      "execution": {
        "info": {
          "status": "RUNNING",
          "errorMessage": null,
          "startedAt": "2024-03-04T10:15:30Z",
          "completedAt": null
        }
      }
    }
  }
  ```

  ```json Succeeded theme={null}
  {
    "data": {
      "execution": {
        "info": {
          "status": "SUCCEEDED",
          "errorMessage": null,
          "startedAt": "2024-03-04T10:15:30Z",
          "completedAt": "2024-03-04T10:15:50Z"
        }
      }
    }
  }
  ```

  ```json Failed theme={null}
  {
    "data": {
      "execution": {
        "info": {
          "status": "FAILED",
          "errorMessage": "Deployment not found",
          "startedAt": "2024-03-04T10:15:30Z",
          "completedAt": "2024-03-04T10:15:31Z"
        }
      }
    }
  }
  ```
</CodeGroup>

#### Execution Status Values

<ParamField path="PENDING" type="status">
  Operation is queued but not yet started
</ParamField>

<ParamField path="RUNNING" type="status">
  Operation is currently executing
</ParamField>

<ParamField path="SUCCEEDED" type="status">
  Operation completed successfully
</ParamField>

<ParamField path="FAILED" type="status">
  Operation failed with an error
</ParamField>

#### Polling for Completion

```javascript theme={null}
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:

1. Return immediately with a unique execution ID
2. Execute in the background
3. Can be monitored using the `execution.info` query

### Benefits

<CardGroup cols={2}>
  <Card title="Non-Blocking" icon="clock">
    Your client doesn't need to maintain a long-lived connection
  </Card>

  <Card title="Resumable" icon="rotate">
    You can disconnect and check status later using the execution ID
  </Card>

  <Card title="Transparent" icon="eye">
    Full visibility into operation progress and errors
  </Card>

  <Card title="Reliable" icon="shield-check">
    Operations continue even if the client disconnects
  </Card>
</CardGroup>

***

## Integration Examples

### Python

```python theme={null}
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

```javascript theme={null}
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

```bash theme={null}
# 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

<AccordionGroup>
  <Accordion title="Never Expose Externally" icon="shield-exclamation">
    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
  </Accordion>

  <Accordion title="Rotate Tokens Regularly" icon="rotate">
    Change your `GRAPHMAN_SERVER_AUTH_TOKEN` periodically:

    ```bash theme={null}
    # 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
    ```
  </Accordion>

  <Accordion title="Use Strong Tokens" icon="key">
    Generate cryptographically secure tokens:

    ```bash theme={null}
    # Good: Strong random token
    openssl rand -base64 32

    # Bad: Weak predictable token
    echo "admin123"  # Never do this!
    ```
  </Accordion>

  <Accordion title="Monitor Access" icon="eye">
    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
  </Accordion>

  <Accordion title="Principle of Least Privilege" icon="user-lock">
    * 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
  </Accordion>
</AccordionGroup>

***

## Error Handling

### Common Errors

<Accordion title="Authentication Failed">
  ```json theme={null}
  {
    "errors": [
      {
        "message": "Unauthorized",
        "extensions": {
          "code": "UNAUTHENTICATED"
        }
      }
    ]
  }
  ```

  **Solution**: Verify your `Authorization` header includes the correct token.
</Accordion>

<Accordion title="Deployment Not Found">
  ```json theme={null}
  {
    "data": {
      "deployment": {
        "pause": {
          "success": false,
          "message": "Deployment not found"
        }
      }
    }
  }
  ```

  **Solution**: Check the deployment hash or name is correct using the `info` query.
</Accordion>

<Accordion title="Already Paused/Resumed">
  ```json theme={null}
  {
    "data": {
      "deployment": {
        "pause": {
          "success": false,
          "message": "Deployment is already paused"
        }
      }
    }
  }
  ```

  **Solution**: Check current status before attempting pause/resume operations.
</Accordion>

<Accordion title="Execution Not Found">
  ```json theme={null}
  {
    "data": {
      "execution": {
        "info": null
      }
    }
  }
  ```

  **Solution**: Verify the execution ID is correct. Execution records may expire after completion.
</Accordion>

***

## Future Operations

<Info>
  Additional Graphman commands will be added to the GraphQL API over time. Always check the GraphQL playground for the latest schema and available operations.
</Info>

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](#graphql-playground) regularly to discover new features as they become available.

***

## See Also

* [Graphman CLI Commands](/api/graphman-commands) - Command-line interface for Graph Node management
* [Graph Node Configuration](https://github.com/graphprotocol/graph-node/blob/master/docs/config.md) - Configuration file reference
* [GraphQL Specification](https://spec.graphql.org/) - GraphQL language specification
