---
title: GraphQL API
---

Explore the GraphQL Query API for interacting with Subgraphs on The Graph Network.

[GraphQL](https://graphql.org/learn/) is a query language for APIs and a runtime for executing those queries with existing data.

The Graph uses GraphQL to query Subgraphs.

## Core Concepts

### Entities

- **What they are**: Persistent data objects defined with `@entity` in your schema
- **Key requirement**: Must contain `id: ID!` as primary identifier
- **Usage**: Foundation for all query operations

### Schema

- **Purpose**: Blueprint defining the data structure and relationships using GraphQL [IDL](https://facebook.github.io/graphql/draft/#sec-Type-System)
- **Key characteristics**:
  - Auto-generates query endpoints
  - Read-only operations (no mutations)
  - Defines entity interfaces and derived fields

## Query Structure

GraphQL queries in The Graph target entities defined in the Subgraph schema. Each `Entity` type generates corresponding `entity` and `entities` fields on the root `Query` type.

> Note: The `query` keyword is not required at the top level of GraphQL queries.

### Single Entity Queries Example

Query for a single `Token` entity:

```graphql
{
  token(id: "1") {
    id
    owner
  }
}
```

> Note: Single entity queries require the `id` parameter as a string.

### Collection Queries Example

Query format for all `Token` entities:

```graphql
{
  tokens {
    id
    owner
  }
}
```

### Sorting Example

Collection queries support the following sort parameters:

- `orderBy`: Specifies the attribute for sorting
- `orderDirection`: Accepts `asc` (ascending) or `desc` (descending)

#### Standard Sorting Example

```graphql
{
  tokens(orderBy: price, orderDirection: asc) {
    id
    owner
  }
}
```

#### Nested Entity Sorting Example

```graphql
{
  tokens(orderBy: owner__name, orderDirection: asc) {
    id
    owner {
      name
    }
  }
}
```

> Note: Nested sorting supports one-level-deep `String` or `ID` types on `@entity` and `@derivedFrom` fields.

### Pagination Example

When querying a collection, it is best to:

- Use the `first` parameter to paginate from the beginning of the collection.
  - The default sort order is by `ID` in ascending alphanumeric order, **not** by creation time.
- Use the `skip` parameter to skip entities and paginate. For instance, `first:100` shows the first 100 entities and `first:100, skip:100` shows the next 100 entities.
- Avoid using `skip` values in queries because they generally perform poorly. To retrieve a large number of items, it's best to page through entities based on an attribute as shown in the previous example above.

#### Standard Pagination Example

```graphql
{
  tokens(first: 10) {
    id
    owner
  }
}
```

#### Offset Pagination Example

```graphql
{
  tokens(first: 10, skip: 10) {
    id
    owner
  }
}
```

#### Cursor-based Pagination Example

```graphql
query manyTokens($lastID: String) {
  tokens(first: 1000, where: { id_gt: $lastID }) {
    id
    owner
  }
}
```

### Filtering

The `where` parameter filters entities based on specified conditions.

#### Basic Filtering Example

```graphql
{
  challenges(where: { outcome: "failed" }) {
    challenger
    outcome
    application {
      id
    }
  }
}
```

#### Numeric Comparison Example

```graphql
{
  applications(where: { deposit_gt: "10000000000" }) {
    id
    whitelisted
    deposit
  }
}
```

#### Block-based Filtering Example

```graphql
{
  applications(where: { _change_block: { number_gte: 100 } }) {
    id
    whitelisted
    deposit
  }
}
```

#### Nested Entity Filtering Example

```graphql
{
  challenges(where: { application_: { id: 1 } }) {
    challenger
    outcome
    application {
      id
    }
  }
}
```

#### Logical Operators

##### AND Operations Example

The following example filters for challenges with `outcome` `succeeded` and `number` greater than or equal to `100`.

```graphql
{
  challenges(where: { and: [{ number_gte: 100 }, { outcome: "succeeded" }] }) {
    challenger
    outcome
    application {
      id
    }
  }
}
```

**Syntactic sugar:** You can simplify the above query by removing the `and` operator and by passing a sub-expression separated by commas.

```graphql
{
  challenges(where: { number_gte: 100, outcome: "succeeded" }) {
    challenger
    outcome
    application {
      id
    }
  }
}
```

##### OR Operations Example

```graphql
{
  challenges(where: { or: [{ number_gte: 100 }, { outcome: "succeeded" }] }) {
    challenger
    outcome
    application {
      id
    }
  }
}
```

Global filter parameter:

```graphql
_change_block(number_gte: Int)
```

### Time-travel Queries Example

Queries support historical state retrieval using the `block` parameter:

- `number`: Integer block number
- `hash`: String block hash

> Note: The current implementation is still subject to certain limitations that might violate these guarantees. The implementation can not always tell that a given block hash is not on the main chain at all, or if a query result by a block hash for a block that is not yet considered final could be influenced by a block reorganization running concurrently with the query. They do not affect the results of queries by block hash when the block is final and known to be on the main chain. [This issue](https://github.com/graphprotocol/graph-node/issues/1405) explains what these limitations are in detail.

#### Block Number Query Example

```graphql
{
  challenges(block: { number: 8000000 }) {
    challenger
    outcome
    application {
      id
    }
  }
}
```

#### Block Hash Query Example

```graphql
{
  challenges(block: { hash: "0x5a0b54d5dc17e0aadc383d2db43b0a0d3e029c4c" }) {
    challenger
    outcome
    application {
      id
    }
  }
}
```

### Full-Text Search Example

Full-text search query fields provide an expressive text search API that can be added to the Subgraph schema and customized. Refer to [Defining Full-text Search Fields](/developing/creating-a-subgraph/#defining-fulltext-search-fields) to add full-text search to your Subgraph.

Full-text search queries have one required field, `text`, for supplying search terms. Several special full-text operators are available to be used in this `text` search field.

Full-text search fields use the required `text` parameter with the following operators:

| Operator  | Symbol | Description                                                     |
| --------- | ------ | --------------------------------------------------------------- |
| And       | `&`    | Matches entities containing all terms                           |
| Or        | `\|`   | Return all entities with a match from any of the provided terms |
| Follow by | `<->`  | Matches terms with specified distance                           |
| Prefix    | `:*`   | Matches word prefixes (minimum 2 characters)                    |

#### Search Examples

OR operator:

```
{
  blogSearch(text: "anarchism | crumpets") {
    id
    title
    body
    author
  }
}
```

“Follow” by operator:

```graphql
{
  blogSearch(text: "decentralized <-> philosophy") {
    id
    title
    body
    author
  }
}
```

Combined operators:

```graphql
{
  blogSearch(text: "lou:* <-> music") {
    id
    title
    body
    author
  }
}
```

### Schema Definition

Entity types require:

- GraphQL Interface Definition Language (IDL) format
- `@entity` directive
- `ID` field

### Subgraph Metadata Example

The `_Meta_` object provides subgraph metadata:

```graphql
{
  _meta(block: { number: 123987 }) {
    block {
      number
      hash
      timestamp
    }
    deployment
    hasIndexingErrors
  }
}
```

Metadata fields:

- `deployment`: IPFS CID of the subgraph.yaml
- `block`: Latest block information
- `hasIndexingErrors`: Boolean indicating past indexing errors

> Note: When writing queries, it is important to consider the performance impact of using the `or` operator. While `or` can be a useful tool for broadening search results, it can also have significant costs. One of the main issues with `or` is that it can cause queries to slow down. This is because `or` requires the database to scan through multiple indexes, which can be a time-consuming process. To avoid these issues, it is recommended that developers use `and` operators instead of `or` whenever possible. This allows for more precise filtering and can lead to faster, more accurate queries.

### GraphQL Filter Operators Reference

This table explains each filter operator available in The Graph's GraphQL API. These operators are used as suffixes to field names when filtering data using the `where` parameter.

| Operator | Description | Example |
| --- | --- | --- |
| `_` | Matches entities where the specified field equals another entity | `{ where: { owner_: { name: "Alice" } } }` |
| `_not` | Negates the specified condition | `{ where: { active_not: true } }` |
| `_gt` | Greater than (>) | `{ where: { price_gt: "100" } }` |
| `_lt` | Less than (`\<`) | `{ where: { price_lt: "100" } }` |
| `_gte` | Greater than or equal to (>=) | `{ where: { price_gte: "100" } }` |
| `_lte` | Less than or equal to (`\<=`) | `{ where: { price_lte: "100" } }` |
| `_in` | Value is in the specified array | `{ where: { category_in: ["Art", "Music"] } }` |
| `_not_in` | Value is not in the specified array | `{ where: { category_not_in: ["Art", "Music"] } }` |
| `_contains` | Field contains the specified string (case-sensitive) | `{ where: { name_contains: "token" } }` |
| `_contains_nocase` | Field contains the specified string (case-insensitive) | `{ where: { name_contains_nocase: "token" } }` |
| `_not_contains` | Field does not contain the specified string (case-sensitive) | `{ where: { name_not_contains: "test" } }` |
| `_not_contains_nocase` | Field does not contain the specified string (case-insensitive) | `{ where: { name_not_contains_nocase: "test" } }` |
| `_starts_with` | Field starts with the specified string (case-sensitive) | `{ where: { name_starts_with: "Crypto" } }` |
| `_starts_with_nocase` | Field starts with the specified string (case-insensitive) | `{ where: { name_starts_with_nocase: "crypto" } }` |
| `_ends_with` | Field ends with the specified string (case-sensitive) | `{ where: { name_ends_with: "Token" } }` |
| `_ends_with_nocase` | Field ends with the specified string (case-insensitive) | `{ where: { name_ends_with_nocase: "token" } }` |
| `_not_starts_with` | Field does not start with the specified string (case-sensitive) | `{ where: { name_not_starts_with: "Test" } }` |
| `_not_starts_with_nocase` | Field does not start with the specified string (case-insensitive) | `{ where: { name_not_starts_with_nocase: "test" } }` |
| `_not_ends_with` | Field does not end with the specified string (case-sensitive) | `{ where: { name_not_ends_with: "Test" } }` |
| `_not_ends_with_nocase` | Field does not end with the specified string (case-insensitive) | `{ where: { name_not_ends_with_nocase: "test" } }` |

#### Notes

- Type support varies by operator. For example, `Boolean` only supports `_not`, `_in`, and `_not_in`.
- The `_` operator is only available for object and interface types.
- String comparison operators are especially useful for text fields.
- Numeric comparison operators work with both number and string-encoded number fields.
- Use these operators in combination with logical operators (`and`, `or`) for complex filtering.

### Validation

Graph Node implements [specification-based](https://spec.graphql.org/October2021/#sec-Validation) validation of the GraphQL queries it receives using [graphql-tools-rs](https://github.com/dotansimha/graphql-tools-rs#validation-rules), which is based on the [graphql-js reference implementation](https://github.com/graphql/graphql-js/tree/main/src/validation). Queries which fail a validation rule do so with a standard error - visit the [GraphQL spec](https://spec.graphql.org/October2021/#sec-Validation) to learn more.
