GraphQL API
Full Sui GraphQL RPC with complete chain history - served through a single endpoint.
Overview
Inodra runs the Sui GraphQL RPC service on its own infrastructure, backed by both live indexing and archival storage. You get the exact same schema as Sui's public GraphQL endpoint, with one endpoint covering everything from the genesis checkpoint to the chain tip.
Endpoint: https://mainnet-api.inodra.com/v1/graphql
Key features:
- Complete history - every checkpoint, transaction, and object version since genesis
- Schema introspection enabled - works out of the box with GraphiQL, Apollo, and codegen tools
How It Works
Behind the endpoint, Inodra combines two data sources:
- Live indexed data - recent checkpoints, transactions, objects, and events are indexed in real time and served with low latency.
- Archival storage - older data is served from Inodra's archival storage.
You don't need to think about which source a query hits - point lookups (a checkpoint by sequence number, a transaction by digest, an object at a version) work across the entire chain history through the same endpoint and the same queries.
Quick Start
1. Basic Setup
const GRAPHQL_URL = 'https://mainnet-api.inodra.com/v1/graphql'
const API_KEY = 'YOUR_API_KEY'
async function queryGraphQL(query, variables = {}) {
const response = await fetch(GRAPHQL_URL, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'x-api-key': API_KEY
},
body: JSON.stringify({ query, variables })
})
return response.json()
}2. Your First Query
const query = `
query LatestCheckpoints {
checkpoints(last: 5) {
nodes {
sequenceNumber
digest
timestamp
networkTotalTransactions
}
}
}
`
const result = await queryGraphQL(query)
console.log('Latest checkpoints:', result.data.checkpoints.nodes)Using the Sui SDK
The official Sui SDK provides SuiGraphQLClient with type-safe queries:
import { SuiGraphQLClient } from '@mysten/sui/graphql'
import { graphql } from '@mysten/sui/graphql/schema'
const client = new SuiGraphQLClient({
url: 'https://mainnet-api.inodra.com/v1/graphql',
headers: { 'x-api-key': 'YOUR_API_KEY' }
})
// Type-safe query with autocomplete
const chainQuery = graphql(`
query {
chainIdentifier
}
`)
const result = await client.query({ query: chainQuery })
console.log('Chain:', result.data?.chainIdentifier)The graphql() function provides compile-time type checking for your queries, catching errors before runtime.
Querying Historical Data
The same queries work across the full chain history - no separate archival endpoint:
query HistoricalData {
# Checkpoint from 2023 - old data served from archival storage
checkpoint(sequenceNumber: 1000) {
digest
timestamp
epoch {
epochId
}
}
# The Clock object as it was at a specific checkpoint
object(address: "0x6", atCheckpoint: 50000000) {
version
digest
asMoveObject {
contents {
json
}
}
}
# Any past epoch, with totals and gas data
epoch(epochId: 100) {
startTimestamp
endTimestamp
totalTransactions
referenceGasPrice
}
}Pagination
GraphQL uses cursor-based pagination on every connection:
async function getAllTransactions(address) {
const allTransactions = []
let hasNextPage = true
let cursor = null
while (hasNextPage) {
const query = `
query PaginatedTransactions($address: SuiAddress!, $after: String) {
transactions(filter: { affectedAddress: $address }, first: 50, after: $after) {
nodes {
digest
effects {
status
}
}
pageInfo {
hasNextPage
endCursor
}
}
}
`
const result = await queryGraphQL(query, { address, after: cursor })
const txData = result.data.transactions
allTransactions.push(...txData.nodes)
hasNextPage = txData.pageInfo.hasNextPage
cursor = txData.pageInfo.endCursor
}
return allTransactions
}Using with GraphQL Clients
Apollo Client
import { ApolloClient, InMemoryCache, createHttpLink } from '@apollo/client'
import { setContext } from '@apollo/client/link/context'
const httpLink = createHttpLink({
uri: 'https://mainnet-api.inodra.com/v1/graphql'
})
const authLink = setContext((_, { headers }) => ({
headers: {
...headers,
'x-api-key': 'YOUR_API_KEY'
}
}))
const client = new ApolloClient({
link: authLink.concat(httpLink),
cache: new InMemoryCache()
})urql
import { Client, cacheExchange, fetchExchange } from 'urql'
const client = new Client({
url: 'https://mainnet-api.inodra.com/v1/graphql',
exchanges: [cacheExchange, fetchExchange],
fetchOptions: {
headers: {
'x-api-key': 'YOUR_API_KEY'
}
}
})Requests exceeding these limits return a GraphQL error rather than partial data.
Credits & Billing
GraphQL billing matches the other gateways:
- Queries: 1 credit per request, regardless of complexity
- Transactions: 5 credits for the
executeTransactionmutation or asimulateTransactionquery - same as send/dry-run/simulate on JSON-RPC and gRPC
Batching multiple lookups into a single query (e.g. with multiGet* fields) still costs 1 credit - a single GraphQL request is a single API call.
Error Handling
async function safeGraphQLQuery(query, variables = {}) {
try {
const result = await queryGraphQL(query, variables)
if (result.errors) {
console.error('GraphQL Errors:', result.errors)
throw new Error(`GraphQL Errors: ${result.errors.map((e) => e.message).join(', ')}`)
}
return result.data
} catch (error) {
console.error('Query failed:', error)
throw error
}
}GraphQL Schema Reference
Inodra serves the official Sui GraphQL RPC schema. For complete documentation of all types, fields, and arguments, refer to:
- Sui GraphQL Documentation - Official Sui GraphQL reference
- Schema introspection - the endpoint has introspection enabled, so any GraphQL IDE (GraphiQL, Altair, Apollo Sandbox) can explore the live schema directly
When to Use GraphQL
Perfect for:
- Applications needing flexible, complex queries in a single round trip
- Frontend applications with varying data requirements
- Historical analysis that mixes point lookups with recent data
- Projects already using GraphQL in their stack
Consider gRPC instead if you need streaming, maximum throughput, or binary efficiency - see the gRPC gateway.
Next Steps
- Explore the schema interactively with introspection in your favorite GraphQL IDE
- Read the complete Sui GraphQL schema documentation
- Monitor usage in the Inodra dashboard
- Join our Discord for GraphQL best practices