An ergonomic Shopify Admin GraphQL API client for Rust.
Version 0.10 is a breaking refactor for Shopify Admin API 2026-04 and newer:
- GraphQL-first client
2026-04minimum API version- static access tokens, client credentials tokens, and expiring offline tokens
- dynamic GraphQL schema download
- Bulk operations using the 2026
bulkOperation(id:)andbulkOperationsAPIs
[dependencies]
shopify_api = "0.10"
tokio = { version = "1", features = ["full"] }
serde = { version = "1", features = ["derive"] }
serde_json = "1"use serde::Deserialize;
use shopify_api::{Shopify, ShopifyAuth, ShopifyConfig};
#[derive(Deserialize)]
struct ShopQuery {
shop: Shop,
}
#[derive(Deserialize)]
struct Shop {
name: String,
}
#[tokio::main]
async fn main() -> Result<(), shopify_api::ShopifyAPIError> {
let shopify = Shopify::new(
"my-shop",
ShopifyAuth::AccessToken("shpat_...".to_string()),
ShopifyConfig::default(),
)?;
let data: ShopQuery = shopify
.graphql(
"query { shop { name } }",
&serde_json::json!({}),
)
.await?;
println!("{}", data.shop.name);
Ok(())
}use shopify_api::{Shopify, ShopifyAuth, ShopifyConfig};
let shopify = Shopify::new(
"my-shop",
ShopifyAuth::client_credentials("client_id", "client_secret"),
ShopifyConfig::default(),
)?;The crate acquires and refreshes 24-hour client-credentials tokens automatically. Add a TokenStore in ShopifyConfig when your app needs to persist refreshed token data.
Public Shopify schema:
# async fn example() -> Result<(), shopify_api::ShopifyAPIError> {
let schema = shopify_api::download_public_admin_schema("2026-04").await?;
# Ok(())
# }cargo install shopify_api --features cli
shopify-api schema download \
--public \
--api-version 2026-04 \
--out graphql.schema.jsonThis uses Shopify's public schema proxy:
https://shopify.dev/admin-graphql-direct-proxy/2026-04The proxy is a GraphQL endpoint for introspection requests, not a static GET file.
Runtime:
use shopify_api::{Shopify, ShopifyAuth, ShopifyConfig};
# async fn example() -> Result<(), shopify_api::ShopifyAPIError> {
let shopify = Shopify::new(
"my-shop",
ShopifyAuth::AccessToken("shpat_...".to_string()),
ShopifyConfig::default(),
)?;
let schema = shopify.download_admin_schema().await?;
# Ok(())
# }CLI:
cargo install shopify_api --features cli
shopify-api schema download \
--shop my-shop \
--access-token "$SHOPIFY_ACCESS_TOKEN" \
--out shop.graphql.schema.jsonThe crate no longer ships built-in Shopify schema JSON files. Use the CLI output as the schema_path for graphql_client.
use shopify_api::{BulkWaitOptions, Shopify, ShopifyAuth, ShopifyConfig};
# async fn example() -> Result<(), shopify_api::ShopifyAPIError> {
let shopify = Shopify::new(
"my-shop",
ShopifyAuth::AccessToken("shpat_...".to_string()),
ShopifyConfig::default(),
)?;
let payload = shopify
.run_bulk_query("{ products { edges { node { id title } } } }")
.await?;
let operation = payload.bulk_operation.unwrap();
let operation = shopify
.wait_for_bulk(&operation.id, BulkWaitOptions::default())
.await?;
if let Some(url) = operation.url {
let rows: Vec<serde_json::Value> = Shopify::download_bulk_jsonl(&url).await?;
println!("{} rows", rows.len());
}
# Ok(())
# }See CHANGELOG.md.