Expand description
§Shopify API Rust SDK
A Rust SDK for the Shopify API, providing type-safe configuration, authentication handling, and HTTP client functionality for Shopify app development.
§Overview
This SDK provides:
- Type-safe configuration via
ShopifyConfigandShopifyConfigBuilder - Validated newtypes for API credentials and domain values
- OAuth scope handling with implied scope support
- OAuth 2.0 authorization code flow via
auth::oauth - Token exchange for embedded apps via
auth::oauth - Client credentials for private/organization apps via
auth::oauth - Token refresh for expiring access tokens via
auth::oauth - Session management for authenticated API calls
- Async HTTP client with retry logic and rate limit handling
- REST API client with convenient methods for Admin API operations
- REST resource infrastructure with CRUD operations and dirty tracking
- GraphQL API client for modern Admin API operations (recommended)
- Storefront API client for headless commerce applications
- Webhook registration system for event subscriptions
§Quick Start
use shopify_sdk::{ShopifyConfig, ApiKey, ApiSecretKey, ApiVersion, AuthScopes};
// Create configuration using the builder pattern
let config = ShopifyConfig::builder()
.api_key(ApiKey::new("your-api-key").unwrap())
.api_secret_key(ApiSecretKey::new("your-api-secret").unwrap())
.scopes("read_products,write_orders".parse().unwrap())
.api_version(ApiVersion::latest())
.build()
.unwrap();§OAuth Authentication
For apps that need to authenticate with Shopify stores:
use shopify_sdk::{ShopifyConfig, ApiKey, ApiSecretKey, ShopDomain, HostUrl};
use shopify_sdk::auth::oauth::{begin_auth, validate_auth_callback, AuthQuery};
// Step 1: Configure the SDK
let config = ShopifyConfig::builder()
.api_key(ApiKey::new("your-api-key").unwrap())
.api_secret_key(ApiSecretKey::new("your-secret").unwrap())
.host(HostUrl::new("https://your-app.com").unwrap())
.scopes("read_products".parse().unwrap())
.build()
.unwrap();
// Step 2: Begin authorization
let shop = ShopDomain::new("example-shop").unwrap();
let result = begin_auth(&config, &shop, "/auth/callback", true, None)?;
// Redirect user to result.auth_url
// Store result.state in session
// Step 3: Handle callback
let session = validate_auth_callback(&config, &query, &stored_state).await?;
// session is now ready for API calls§Token Exchange (Embedded Apps)
For embedded apps using App Bridge session tokens:
use shopify_sdk::{ShopifyConfig, ApiKey, ApiSecretKey, ShopDomain};
use shopify_sdk::auth::oauth::{exchange_online_token, exchange_offline_token};
// Configure the SDK (must be embedded)
let config = ShopifyConfig::builder()
.api_key(ApiKey::new("your-api-key").unwrap())
.api_secret_key(ApiSecretKey::new("your-secret").unwrap())
.is_embedded(true)
.build()
.unwrap();
let shop = ShopDomain::new("example-shop").unwrap();
let session_token = "eyJ..."; // JWT from App Bridge
// Exchange for an online access token
let session = exchange_online_token(&config, &shop, session_token).await?;
// Or exchange for an offline access token
let session = exchange_offline_token(&config, &shop, session_token).await?;§Client Credentials (Private/Organization Apps)
For private or organization apps without user interaction:
use shopify_sdk::{ShopifyConfig, ApiKey, ApiSecretKey, ShopDomain};
use shopify_sdk::auth::oauth::exchange_client_credentials;
// Configure the SDK (must NOT be embedded)
let config = ShopifyConfig::builder()
.api_key(ApiKey::new("your-api-key").unwrap())
.api_secret_key(ApiSecretKey::new("your-secret").unwrap())
// is_embedded defaults to false, which is required
.build()
.unwrap();
let shop = ShopDomain::new("example-shop").unwrap();
// Exchange client credentials for an offline access token
let session = exchange_client_credentials(&config, &shop).await?;
println!("Access token: {}", session.access_token);§Token Refresh (Expiring Tokens)
For apps using expiring offline access tokens:
use shopify_sdk::{ShopifyConfig, ApiKey, ApiSecretKey, ShopDomain};
use shopify_sdk::auth::oauth::{refresh_access_token, migrate_to_expiring_token};
// Refresh an expiring access token
if session.expired() {
if let Some(refresh_token) = &session.refresh_token {
let new_session = refresh_access_token(&config, &shop, refresh_token).await?;
println!("New access token: {}", new_session.access_token);
}
}
// Or migrate from non-expiring to expiring tokens (one-time, irreversible)
let new_session = migrate_to_expiring_token(&config, &shop, &old_access_token).await?;§Session Management
Sessions represent authenticated connections to a Shopify store. They can be either offline (app-level) or online (user-specific):
use shopify_sdk::{Session, ShopDomain, AuthScopes, AssociatedUser};
// Create an offline session (no expiration, no user)
let offline_session = Session::new(
Session::generate_offline_id(&ShopDomain::new("my-store").unwrap()),
ShopDomain::new("my-store").unwrap(),
"access-token".to_string(),
"read_products".parse().unwrap(),
false,
None,
);
// Sessions can be serialized for storage
let json = serde_json::to_string(&offline_session).unwrap();§Making GraphQL API Requests (Recommended)
The GraphqlClient provides methods for GraphQL Admin API operations:
use shopify_sdk::{GraphqlClient, Session, ShopDomain, AuthScopes};
use serde_json::json;
// Create a session
let session = Session::new(
"session-id".to_string(),
ShopDomain::new("my-store").unwrap(),
"access-token".to_string(),
AuthScopes::new(),
false,
None,
);
// Create a GraphQL client (no deprecation warning - this is the recommended API)
let client = GraphqlClient::new(&session, None);
// Simple query
let response = client.query("query { shop { name } }", None, None, None).await?;
println!("Shop: {}", response.body["data"]["shop"]["name"]);
// Query with variables
let response = client.query(
"query GetProduct($id: ID!) { product(id: $id) { title } }",
Some(json!({ "id": "gid://shopify/Product/123" })),
None,
None
).await?;
// Check for GraphQL errors (returned with HTTP 200)
if let Some(errors) = response.body.get("errors") {
println!("GraphQL errors: {}", errors);
}§Making Storefront API Requests
The StorefrontClient provides methods for Storefront API operations:
use shopify_sdk::{StorefrontClient, StorefrontToken, ShopDomain};
use serde_json::json;
let shop = ShopDomain::new("my-store").unwrap();
// With public token (client-side safe)
let token = StorefrontToken::Public("public-access-token".to_string());
let client = StorefrontClient::new(&shop, Some(token), None);
// With private token (server-side only)
let token = StorefrontToken::Private("private-access-token".to_string());
let client = StorefrontClient::new(&shop, Some(token), None);
// Tokenless access for basic features
let client = StorefrontClient::new(&shop, None, None);
// Query products
let response = client.query(
"query { products(first: 10) { edges { node { title } } } }",
None,
None,
None
).await?;
// Access response data
let products = &response.body["data"]["products"];§Webhook Registration
The WebhookRegistry provides webhook subscription management with support
for HTTP, Amazon EventBridge, and Google Cloud Pub/Sub delivery methods:
use shopify_sdk::{
WebhookRegistry, WebhookRegistrationBuilder, WebhookTopic, WebhookDeliveryMethod
};
// Configure webhooks at startup
let mut registry = WebhookRegistry::new();
// HTTP delivery
registry
.add_registration(
WebhookRegistrationBuilder::new(
WebhookTopic::OrdersCreate,
WebhookDeliveryMethod::Http {
uri: "https://example.com/api/webhooks/orders".to_string(),
},
)
.build()
)
// Amazon EventBridge delivery
.add_registration(
WebhookRegistrationBuilder::new(
WebhookTopic::ProductsUpdate,
WebhookDeliveryMethod::EventBridge {
arn: "arn:aws:events:us-east-1::event-source/aws.partner/shopify.com/123/source".to_string(),
},
)
.build()
)
// Google Cloud Pub/Sub delivery
.add_registration(
WebhookRegistrationBuilder::new(
WebhookTopic::CustomersCreate,
WebhookDeliveryMethod::PubSub {
project_id: "my-gcp-project".to_string(),
topic_id: "shopify-webhooks".to_string(),
},
)
.filter("vendor:MyApp".to_string())
.build()
);
// Later, register with Shopify when session is available:
// let results = registry.register_all(&session, &config).await?;§Making REST API Requests (Deprecated)
The RestClient provides convenient methods for REST API operations:
use shopify_sdk::{RestClient, Session, ShopDomain, AuthScopes};
// Create a session
let session = Session::new(
"session-id".to_string(),
ShopDomain::new("my-store").unwrap(),
"access-token".to_string(),
AuthScopes::new(),
false,
None,
);
// Create a REST client (logs deprecation warning)
let client = RestClient::new(&session, None)?;
// GET request
let response = client.get("products", None).await?;
// POST request with body
let body = serde_json::json!({"product": {"title": "New Product"}});
let response = client.post("products", body, None).await?;§Making Low-Level HTTP Requests
For more control, use the low-level HttpClient:
use shopify_sdk::{Session, ShopDomain, AuthScopes};
use shopify_sdk::clients::{HttpClient, HttpRequest, HttpMethod};
// Create a session
let session = Session::new(
"session-id".to_string(),
ShopDomain::new("my-store").unwrap(),
"access-token".to_string(),
AuthScopes::new(),
false,
None,
);
// Create an HTTP client
let client = HttpClient::new("/admin/api/2024-10", &session, None);
// Build and send a request
let request = HttpRequest::builder(HttpMethod::Get, "products.json")
.build()
.unwrap();
let response = client.request(request).await?;§Design Principles
- No global state: Configuration is instance-based and passed explicitly
- Fail-fast validation: All newtypes validate on construction
- Thread-safe: All types are
Send + Sync - Async-first: Designed for use with Tokio async runtime
- Immutable sessions: Sessions are immutable after creation
Re-exports§
pub use auth::AssociatedUser;pub use auth::AuthScopes;pub use auth::Session;pub use config::ApiKey;pub use config::ApiSecretKey;pub use config::ApiVersion;pub use config::DeprecationCallback;pub use config::HostUrl;pub use config::ShopDomain;pub use config::ShopifyConfig;pub use config::ShopifyConfigBuilder;pub use error::ConfigError;pub use clients::ApiCallLimit;pub use clients::ApiDeprecationInfo;pub use clients::DataType;pub use clients::HttpClient;pub use clients::HttpError;pub use clients::HttpMethod;pub use clients::HttpRequest;pub use clients::HttpRequestBuilder;pub use clients::HttpResponse;pub use clients::HttpResponseError;pub use clients::InvalidHttpRequestError;pub use clients::MaxHttpRetriesExceededError;pub use clients::PaginationInfo;pub use clients::RestClient;pub use clients::RestError;pub use clients::GraphqlClient;pub use clients::GraphqlError;pub use clients::StorefrontClient;pub use clients::StorefrontToken;pub use auth::oauth::begin_auth;pub use auth::oauth::exchange_client_credentials;pub use auth::oauth::exchange_offline_token;pub use auth::oauth::exchange_online_token;pub use auth::oauth::migrate_to_expiring_token;pub use auth::oauth::refresh_access_token;pub use auth::oauth::validate_auth_callback;pub use auth::oauth::AuthQuery;pub use auth::oauth::BeginAuthResult;pub use auth::oauth::OAuthError;pub use auth::oauth::StateParam;pub use rest::ResourceError;pub use rest::ResourceOperation;pub use rest::ResourcePath;pub use rest::ResourceResponse;pub use rest::RestResource;pub use rest::TrackedResource;pub use webhooks::WebhookDeliveryMethod;pub use webhooks::WebhookError;pub use webhooks::WebhookRegistration;pub use webhooks::WebhookRegistrationBuilder;pub use webhooks::WebhookRegistrationResult;pub use webhooks::WebhookRegistry;pub use webhooks::WebhookTopic;
Modules§
- auth
- Authentication types for the Shopify API SDK.
- clients
- HTTP client types for Shopify API communication.
- config
- Configuration types for the Shopify API SDK.
- error
- Error types for the Shopify API SDK.
- rest
- REST Resource infrastructure for Shopify API.
- webhooks
- Webhook registration and verification system for the Shopify API SDK.