# How to Interact with Fuel Core Using the GraphQL API: A Complete Developer's Guide

> Learn to interact with Fuel Core using its GraphQL API. Query blockchain data, submit transactions, and subscribe to events with FuelClient or HTTP. Your complete developer guide.

- Repository: [Fuel Labs/fuel-core](https://github.com/FuelLabs/fuel-core)
- Tags: how-to-guide
- Published: 2026-03-06

---

**Fuel Core exposes a built-in GraphQL service that allows developers to query blockchain data, submit transactions, and subscribe to real-time block events via HTTP, configurable through `ServiceConfig` and accessible via the official `FuelClient` or raw HTTP requests.**

The FuelLabs/fuel-core repository ships with a comprehensive GraphQL layer that serves as the primary interface for external applications to interact with the Fuel network. This service runs as an integrated sub-system within the node, providing both synchronous query capabilities and asynchronous subscriptions over Server-Sent Events.

## GraphQL Service Architecture

The GraphQL implementation spans multiple modules under `crates/fuel-core/src/graphql_api/`, integrating configuration management, HTTP routing, and schema execution.

### Configuration Layer

According to the source code in [`crates/fuel-core/src/graphql_api.rs`](https://github.com/FuelLabs/fuel-core/blob/main/crates/fuel-core/src/graphql_api.rs) (lines 21-49), the service is controlled by the **`Config`** and **`ServiceConfig`** structures. These hold the listener address, query complexity limits, depth restrictions, and cost settings. When initializing a node via `Config::local_node()`, GraphQL is enabled by default and binds to `127.0.0.1:4000`, though you can customize `cfg.graphql_config.addr` to any valid socket address.

### Service Construction and Routing

In [`crates/fuel-core/src/graphql_api/api_service.rs`](https://github.com/FuelLabs/fuel-core/blob/main/crates/fuel-core/src/graphql_api/api_service.rs) (lines 34-74), the **`new_service`** function constructs the GraphQL runner. It first builds a **`CoreSchema`** with extensions for metrics, validation, and block-height checks, then wires this schema into an **Axum** HTTP router. The router applies middleware for CORS, request timeouts, concurrency limits, and body-size restrictions before exposing the following endpoints:

- **`/v1/graphql`** – Accepts POST requests with JSON-encoded GraphQL queries and mutations.
- **`/v1/graphql-sub`** – Handles GraphQL subscriptions using Server-Sent Events for real-time data streaming.
- **`/v1/playground`** – Serves the interactive GraphiQL IDE for schema exploration and manual testing.
- **`/v1/health`** and **`/v1/metrics`** – Expose node health status and operational telemetry.

Request handling is performed by dedicated functions defined in the same file: **`graphql_handler`** executes queries against the schema, **`graphql_subscription_handler`** manages streaming subscriptions, and **`health`** returns the node's operational status.

## Starting a Node with GraphQL Enabled

To launch a Fuel Core node with the GraphQL service active, initialize the configuration using `Config::local_node()` and start the service via `FuelService::from_database`.

```rust
use fuel_core::{
    service::{Config, FuelService},
    database::Database,
};

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    // Initialize default configuration with GraphQL enabled on port 4000
    let mut cfg = Config::local_node();
    cfg.graphql_config.addr = "127.0.0.1:4000".parse()?;

    // Start the node and all sub-services including GraphQL
    let service = FuelService::from_database(Database::default(), cfg).await?;
    service.start().await?;
    Ok(())
}

```

The `Config::local_node()` method populates `ServiceConfig` with sensible defaults for complexity limits and timeouts, which you can override directly on the `cfg.graphql_config` object before starting the service.

## Querying Blockchain Data via HTTP

Once the node is running, you can execute GraphQL queries by sending POST requests to `/v1/graphql` with a JSON payload containing the query string.

```bash
curl -X POST http://127.0.0.1:4000/v1/graphql \
     -H "Content-Type: application/json" \
     -d '{"query":"{ block(height: 0) { id header { height timestamp } } }"}'

```

The server returns a JSON response containing the requested data:

```json
{
  "data": {
    "block": {
      "id": "...",
      "header": {
        "height": "0",
        "timestamp": "..."
      }
    }
  }
}

```

## Subscribing to Real-Time Events

For applications requiring live updates, the **`FuelClient`** Rust library abstracts the subscription protocol. The client posts GraphQL subscription queries to `/v1/graphql-sub` and yields Server-Sent Events as implemented in [`crates/fuel-core/src/graphql_api/api_service.rs`](https://github.com/FuelLabs/fuel-core/blob/main/crates/fuel-core/src/graphql_api/api_service.rs).

```rust
use fuel_core_client::client::FuelClient;
use futures::StreamExt;
use std::time::Duration;
use tokio::time::timeout;

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    // Initialize client with URL fail-over support
    let client = FuelClient::with_urls(&["http://127.0.0.1:4000/v1/graphql"])
        .expect("client creation");

    // Subscribe to new block events
    let mut sub = client
        .new_blocks_subscription()
        .await
        .expect("subscription");

    // Await next block with timeout protection
    let block = timeout(Duration::from_secs(5), sub.next())
        .await??.expect("block event");
    
    println!("New block at height {}", block.sealed_block.entity.header().height());
    Ok(())
}

```

The `new_blocks_subscription()` method returns a stream that emits events whenever the chain produces a new block, handling the underlying HTTP upgrade and SSE parsing automatically.

## Using the GraphiQL Playground

For interactive development and schema exploration, navigate to `http://127.0.0.1:4000/v1/playground` in your browser. This endpoint, generated by `render_graphql_playground` in [`api_service.rs`](https://github.com/FuelLabs/fuel-core/blob/main/api_service.rs), loads the GraphiQL IDE pre-configured with the node's schema documentation, allowing you to construct queries, test mutations, and verify subscription behavior without writing client code.

## Key Implementation Files

| File | Purpose |
|------|---------|
| [`crates/fuel-core/src/graphql_api.rs`](https://github.com/FuelLabs/fuel-core/blob/main/crates/fuel-core/src/graphql_api.rs) | Defines `Config` and `ServiceConfig` structures for service parameters. |
| [`crates/fuel-core/src/graphql_api/api_service.rs`](https://github.com/FuelLabs/fuel-core/blob/main/crates/fuel-core/src/graphql_api/api_service.rs) | Implements `new_service`, Axum routing, and request handlers (`graphql_handler`, `graphql_subscription_handler`). |
| `crates/fuel-core/src/schema/` | Contains `CoreSchema` definitions for queries, mutations, and subscriptions. |
| [`tests/tests/fuel_client.rs`](https://github.com/FuelLabs/fuel-core/blob/main/tests/tests/fuel_client.rs) | Integration tests demonstrating `FuelClient` usage, fail-over logic, and subscription handling. |

## Summary

- **Fuel Core** exposes a GraphQL service via `Config::local_node()` that binds to a configurable address (default `127.0.0.1:4000`).
- The **`new_service`** function in [`api_service.rs`](https://github.com/FuelLabs/fuel-core/blob/main/api_service.rs) constructs an Axum-based HTTP server mounting `CoreSchema` at `/v1/graphql` (queries) and `/v1/graphql-sub` (subscriptions).
- Developers can query data via standard HTTP POST requests or use the **`FuelClient`** Rust library for type-safe interactions and automatic fail-over.
- Real-time subscriptions use Server-Sent Events streamed through the `/v1/graphql-sub` endpoint, accessible via `new_blocks_subscription()` and similar methods.
- The `/v1/playground` endpoint provides an interactive GraphiQL interface for development and debugging.

## Frequently Asked Questions

### How do I change the GraphQL listener address and port?

Modify the `addr` field on `cfg.graphql_config` before starting the service, as shown in [`crates/fuel-core/src/graphql_api.rs`](https://github.com/FuelLabs/fuel-core/blob/main/crates/fuel-core/src/graphql_api.rs) (lines 21-49). The default configuration used by `Config::local_node()` binds to `127.0.0.1:4000`, but you can parse any valid socket address string to customize the binding.

### What is the difference between `/v1/graphql` and `/v1/graphql-sub`?

The `/v1/graphql` endpoint handles standard request-response queries and mutations via HTTP POST, while `/v1/graphql-sub` establishes long-lived connections using Server-Sent Events to stream subscription data such as new blocks or transaction status updates. The latter is handled by `graphql_subscription_handler` in [`api_service.rs`](https://github.com/FuelLabs/fuel-core/blob/main/api_service.rs).

### Can I use GraphQL subscriptions from languages other than Rust?

Yes. While the `fuel_core_client` crate provides a convenient Rust wrapper, any HTTP client capable of consuming Server-Sent Events can connect to `/v1/graphql-sub`. Send a POST request with a subscription query, then parse the SSE stream for events formatted according to the GraphQL specification.

### Where are query complexity and depth limits configured?

These limits reside in the **`ServiceConfig`** structure defined in [`crates/fuel-core/src/graphql_api.rs`](https://github.com/FuelLabs/fuel-core/blob/main/crates/fuel-core/src/graphql_api.rs). You can adjust complexity thresholds, query depth limits, and execution timeouts directly on the `graphql_config` object before initializing `FuelService::from_database` to prevent resource exhaustion attacks.