The GraphQL Admin API is Shopify's recommended API for modern app development. It provides a single endpoint for all data operations with precise field selection.
The GraphqlClient provides methods for querying and mutating data through Shopify's GraphQL Admin API. This is the preferred approach over REST for most use cases.
Create a GraphqlClient from an authenticated session:
use shopify_sdk::{GraphqlClient, Session, ShopDomain, AuthScopes};
// Assuming you have a session from OAuth
let session = Session::new(
"session-id".to_string(),
ShopDomain::new("my-store").unwrap(),
"access-token".to_string(),
"read_products".parse().unwrap(),
false,
None,
);
// Create the client
let client = GraphqlClient::new(&session, None);
// Or with a custom API version
use shopify_sdk::ApiVersion;
let client = GraphqlClient::new(&session, Some(ApiVersion::V2026_04));Execute a basic GraphQL query:
use shopify_sdk::GraphqlClient;
let client = GraphqlClient::new(&session, None);
let response = client.query(
"query { shop { name primaryDomain { url } } }",
None, // variables
None, // extra headers
None, // max retries
).await?;
// Access the response data
let shop_name = &response.body["data"]["shop"]["name"];
println!("Shop name: {}", shop_name);Use variables for dynamic queries:
use shopify_sdk::GraphqlClient;
use serde_json::json;
let client = GraphqlClient::new(&session, None);
let query = r#"
query GetProduct($id: ID!) {
product(id: $id) {
title
description
status
variants(first: 10) {
edges {
node {
id
title
price
}
}
}
}
}
"#;
let variables = json!({
"id": "gid://shopify/Product/123456789"
});
let response = client.query(query, Some(variables), None, None).await?;
let product = &response.body["data"]["product"];
println!("Product: {}", product["title"]);Execute mutations to modify data:
use shopify_sdk::GraphqlClient;
use serde_json::json;
let client = GraphqlClient::new(&session, None);
let mutation = r#"
mutation CreateProduct($input: ProductInput!) {
productCreate(input: $input) {
product {
id
title
}
userErrors {
field
message
}
}
}
"#;
let variables = json!({
"input": {
"title": "New Product",
"productType": "Merchandise",
"vendor": "My Store"
}
});
let response = client.query(mutation, Some(variables), None, None).await?;
// Check for user errors
if let Some(errors) = response.body["data"]["productCreate"]["userErrors"].as_array() {
if !errors.is_empty() {
for error in errors {
println!("Error on {}: {}", error["field"], error["message"]);
}
}
}
// Access created product
let product_id = &response.body["data"]["productCreate"]["product"]["id"];
println!("Created product: {}", product_id);The response contains the JSON body and metadata:
use shopify_sdk::GraphqlClient;
let response = client.query("query { shop { name } }", None, None, None).await?;
// Access the JSON body
let data = &response.body["data"];
// Check for GraphQL errors (returned with HTTP 200)
if let Some(errors) = response.body.get("errors") {
if let Some(errors_array) = errors.as_array() {
for error in errors_array {
println!("GraphQL error: {}", error["message"]);
}
}
}
// Access HTTP response metadata
println!("API call limit: {:?}", response.api_call_limit);Include extra information like query cost:
use shopify_sdk::GraphqlClient;
use std::collections::HashMap;
let client = GraphqlClient::new(&session, None);
let mut headers = HashMap::new();
headers.insert("X-GraphQL-Cost-Include-Fields".to_string(), "true".to_string());
let response = client.query(
"query { shop { name } }",
None,
Some(headers),
None
).await?;
// Query cost info is in extensions
if let Some(extensions) = response.body.get("extensions") {
println!("Query cost: {:?}", extensions["cost"]);
}Control which API version to use:
use shopify_sdk::{GraphqlClient, ApiVersion};
// Use the latest version (from session default)
let client = GraphqlClient::new(&session, None);
// Use a specific version
let client = GraphqlClient::new(&session, Some(ApiVersion::V2026_04));Handle errors appropriately:
use shopify_sdk::{GraphqlClient, GraphqlError};
match client.query("query { shop { name } }", None, None, None).await {
Ok(response) => {
println!("Success: {:?}", response.body);
}
Err(GraphqlError::HttpError(e)) => {
println!("HTTP error: {}", e);
}
Err(e) => {
println!("GraphQL error: {}", e);
}
}The SDK automatically handles rate limiting with retries. You can customize the retry behavior:
use shopify_sdk::GraphqlClient;
let response = client.query(
"query { shop { name } }",
None,
None,
Some(5), // max retries
).await?;Tip: Monitor the
api_call_limitin responses to understand your rate limit usage.
-
Request only needed fields - GraphQL allows precise field selection; use it to minimize response size
-
Use fragments for repeated fields - DRY up your queries:
fragment ProductFields on Product { id title status } query { products(first: 10) { edges { node { ...ProductFields } } } }
-
Handle user errors - Mutations return
userErrorsseparately from GraphQL errors -
Use cursor-based pagination - For listing resources:
query($cursor: String) { products(first: 50, after: $cursor) { pageInfo { hasNextPage endCursor } edges { node { id title } } } }
-
Batch operations - Use bulk operations for large data sets (see Shopify documentation)
- Storefront API - Build headless commerce experiences
- Webhooks - Subscribe to real-time events
- REST Admin API - Legacy REST API (when needed)