Skip to main content
Sui’s GraphQL API provides a flexible, efficient way to query blockchain data. It offers a modern alternative to JSON-RPC with powerful filtering, pagination, and field selection.

GraphQL Endpoint

Mainnet:
https://sui-mainnet.mystenlabs.com/graphql
Testnet:
https://sui-testnet.mystenlabs.com/graphql
Devnet:
https://sui-devnet.mystenlabs.com/graphql

Why GraphQL?

GraphQL offers several advantages over REST/JSON-RPC:
  • Precise Queries: Request exactly the fields you need
  • Single Request: Fetch related data in one query
  • Strongly Typed: Schema-based with built-in validation
  • Powerful Filtering: Rich query capabilities
  • Nested Queries: Retrieve related objects in a single request
  • Real-time Updates: Subscriptions for live data

Quick Start

HTTP Request

curl -X POST https://sui-mainnet.mystenlabs.com/graphql \
  -H "Content-Type: application/json" \
  -d '{
    "query": "{ chainIdentifier }"
  }'

JavaScript Client

const query = `
  query {
    chainIdentifier
    epoch {
      epochId
      referenceGasPrice
    }
  }
`;

const response = await fetch('https://sui-mainnet.mystenlabs.com/graphql', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ query }),
});

const data = await response.json();
console.log(data);

TypeScript SDK

import { SuiGraphQLClient } from '@mysten/sui.js/graphql';

const client = new SuiGraphQLClient({
  url: 'https://sui-mainnet.mystenlabs.com/graphql',
});

const { data } = await client.query({
  query: `
    query {
      chainIdentifier
    }
  `,
});

Schema Exploration

Use GraphQL introspection to explore the schema:
query {
  __schema {
    types {
      name
      description
    }
  }
}
Or use GraphQL Playground:
  • Navigate to the GraphQL endpoint in your browser
  • Explore the schema in the “Docs” panel
  • Test queries interactively

Common Queries

Get Chain Information

query {
  chainIdentifier
  serviceConfig {
    maxQueryDepth
    maxQueryNodes
    requestTimeoutMs
  }
}

Get Current Epoch

query {
  epoch {
    epochId
    referenceGasPrice
    startTimestamp
    endTimestamp
    validatorSet {
      totalStake
    }
  }
}

Get Object by ID

query GetObject($id: SuiAddress!) {
  object(address: $id) {
    address
    version
    digest
    owner {
      __typename
      ... on AddressOwner {
        owner {
          address
        }
      }
      ... on Shared {
        initialSharedVersion
      }
    }
    asMoveObject {
      contents {
        type {
          repr
        }
        json
      }
    }
  }
}
Variables:
{
  "id": "0x5"
}

Get Owned Objects

query GetOwnedObjects($owner: SuiAddress!, $first: Int) {
  address(address: $owner) {
    objects(first: $first) {
      nodes {
        address
        version
        digest
        asMoveObject {
          contents {
            type {
              repr
            }
          }
        }
      }
      pageInfo {
        hasNextPage
        endCursor
      }
    }
  }
}

Get Transaction Block

query GetTransaction($digest: String!) {
  transactionBlock(digest: $digest) {
    digest
    sender {
      address
    }
    gasInput {
      gasSponsor {
        address
      }
      gasPrice
      gasBudget
    }
    effects {
      status
      gasEffects {
        gasObject {
          address
        }
        gasSummary {
          computationCost
          storageCost
          storageRebate
        }
      }
    }
  }
}

Query Events

query GetEvents($filter: EventFilter, $first: Int) {
  events(filter: $filter, first: $first) {
    nodes {
      sendingModule {
        package {
          address
        }
        name
      }
      type {
        repr
      }
      sender {
        address
      }
      json
      bcs
    }
    pageInfo {
      hasNextPage
      endCursor
    }
  }
}
Variables:
{
  "filter": {
    "eventType": "0x2::coin::CoinCreated"
  },
  "first": 10
}

Get Balance

query GetBalance($owner: SuiAddress!, $type: String) {
  address(address: $owner) {
    balance(type: $type) {
      coinType {
        repr
      }
      coinObjectCount
      totalBalance
    }
  }
}

Pagination

GraphQL uses cursor-based pagination:
query GetObjectsWithPagination(
  $owner: SuiAddress!
  $first: Int
  $after: String
) {
  address(address: $owner) {
    objects(first: $first, after: $after) {
      nodes {
        address
        version
      }
      pageInfo {
        hasNextPage
        hasPreviousPage
        startCursor
        endCursor
      }
    }
  }
}
To get the next page, use the endCursor as the after parameter:
{
  "owner": "0x...",
  "first": 50,
  "after": "eyJvIjoxMDAsImMiOjUwfQ"
}

Nested Queries

Fetch related data in a single query:
query GetTransactionWithObjects($digest: String!) {
  transactionBlock(digest: $digest) {
    digest
    sender {
      address
      objects(first: 5) {
        nodes {
          address
        }
      }
    }
    effects {
      objectChanges {
        nodes {
          address
          idCreated
          idDeleted
        }
      }
    }
  }
}

Filtering

Use filters to narrow results:
query GetFilteredObjects($owner: SuiAddress!) {
  address(address: $owner) {
    objects(
      first: 50
      filter: {
        type: "0x2::coin::Coin"
      }
    ) {
      nodes {
        address
        asMoveObject {
          contents {
            type {
              repr
            }
          }
        }
      }
    }
  }
}

Error Handling

GraphQL returns errors in a standardized format:
{
  "data": null,
  "errors": [
    {
      "message": "Object not found",
      "locations": [{ "line": 2, "column": 3 }],
      "path": ["object"]
    }
  ]
}

Rate Limits

The public GraphQL endpoint has rate limits:
  • Query Depth: Maximum 15 levels deep
  • Query Nodes: Maximum 500 nodes per query
  • Request Timeout: 30 seconds
  • Rate Limit: Subject to fair use policies
For production use:
  • Run your own indexer with GraphQL
  • Use a managed RPC provider
  • Implement caching and batching

Next Steps

Build docs developers (and LLMs) love