shopify-client
A type-safe, async Rust client for the Shopify Admin API
Getting Started • API Coverage • Examples • Bulk Operations • Docs
let client = new;
// One client, every API
let order = client.order.get_with_id.await?;
let products = client.bulk_operation.export_products.await?;
let shop = client.shop.get.await?;
Highlights
| 9 service modules | Orders, Subscriptions, Discounts, Cart Transforms, App Installation, Shopify Functions, Shop, Storefront Tokens, Bulk Operations |
| Bulk Operations | Prebuilt export templates for products, orders, collections, customers, inventory, and draft orders with typed JSONL parsing |
| Typed everything | Strongly typed requests, responses, filters, and JSONL export lines — no raw strings |
| Async / await | Built on reqwest with tokio — non-blocking by default |
| Webhook parsing | HMAC-verified parsing for customer data, customer redact, and shop redact compliance webhooks |
| Request callbacks | Optional before/after hooks for logging, metrics, and observability |
Getting Started
Add to your Cargo.toml:
[]
= "0.16.0"
use ShopifyClient;
async
API Coverage
| Service | Protocol | Operations |
|---|---|---|
client.order |
REST | get_with_id, get_with_name, patch |
client.subscription |
GraphQL | create_recurring, create_usage, create_combined, cancel, extend_trial, update_capped_amount, create_usage_record, get_active_subscriptions |
client.discount |
GraphQL | create_automatic_app_discount, update_automatic_app_discount, get_discount_nodes |
client.app_installation |
GraphQL | get_current, set_metafields, get_metafield, list_metafields |
client.cart_transform |
GraphQL | create, set_metafields |
client.shopify_functions |
GraphQL | list |
client.shop |
GraphQL | get |
client.storefront_access_token |
GraphQL | create, delete |
client.bulk_operation |
GraphQL | run_query, run_mutation, cancel, get, list, create_staged_upload, export_*, stream_* |
Examples
Orders
// Get by ID
let resp = client.order.get_with_id.await?;
println!;
// Get by name
let resp = client.order.get_with_name.await?;
// Update tags
let patch = PatchOrderRequest ;
client.order.patch.await?;
Subscriptions
use *;
let request = CreateRecurringSubscriptionRequest ;
let resp = client.subscription.create_recurring.await?;
println!;
Shop Info
let resp = client.shop.get.await?;
println!;
println!;
Create Automatic Discount
use DiscountAutomaticAppInput;
let input = DiscountAutomaticAppInput ;
client.discount.create_automatic_app_discount.await?;
Create Cart Transform
use ;
let input = new
.with_function_handle
.with_block_on_failure
.with_metafields;
client.cart_transform.create.await?;
Update Metafields with CAS
use MetafieldsSetInput;
let metafields = vec!;
client.cart_transform.set_metafields.await?;
Bulk Operations
The bulk operations API lets you export or import millions of objects asynchronously. This client provides two layers:
| Layer | For | Example |
|---|---|---|
| Prebuilt templates | Common exports with zero GraphQL | client.bulk_operation.export_products(params) |
| Raw operations | Custom queries / mutations | client.bulk_operation.run_query(graphql, None) |
Export Templates
Six prebuilt exports, each with typed filter params and comprehensive field coverage:
| Template | Resource | Children | Filter Struct |
|---|---|---|---|
export_products |
Products | Variants, Media | ProductQueryParams |
export_orders |
Orders | LineItems | OrderQueryParams |
export_collections |
Collections | Products | CollectionQueryParams |
export_customers |
Customers | Addresses | CustomerQueryParams |
export_inventory_items |
InventoryItems | Levels | InventoryItemQueryParams |
export_draft_orders |
DraftOrders | LineItems | DraftOrderQueryParams |
Typed Filters
Build search filters with type safety — no raw query strings:
use *;
use DateFilter;
let params = OrderQueryParams ;
client.bulk_operation.export_orders.await?;
Available filter primitives:
| Filter | Variants |
|---|---|
DateFilter |
Exact, Before, After, OnOrBefore, OnOrAfter, Range |
NumericFilter<T> |
Exact, GreaterThan, LessThan, GreaterOrEqual, LessOrEqual |
Full Export Workflow
Bulk exports are a three-step process: start the export, poll until Shopify finishes, then consume the result. The JSONL result URL points to a temporary file hosted by Shopify that can be multi-GB for large shops (millions of products/orders). The stream_* methods download and parse this file in chunks so your app uses constant memory regardless of file size.
use ShopifyClient;
use ;
use ;
let client = new;
// 1. Start the export
let params = ProductQueryParams ;
let resp = client.bulk_operation.export_products.await?;
let op = resp.bulk_operation_run_query.bulk_operation.ok_or?;
// 2. Poll until Shopify finishes processing
let url = loop ;
// 3. Stream results — constant memory, processes batch_size items at a time
client.bulk_operation.stream_products.await?;
Each prebuilt export has a matching stream_* method that takes a batch_size and an async callback:
| Export | Stream | Line Enum |
|---|---|---|
export_products |
stream_products |
ProductExportLine |
export_orders |
stream_orders |
OrderExportLine |
export_collections |
stream_collections |
CollectionExportLine |
export_customers |
stream_customers |
CustomerExportLine |
export_inventory_items |
stream_inventory_items |
InventoryItemExportLine |
export_draft_orders |
stream_draft_orders |
DraftOrderExportLine |
All stream_* methods accumulate up to batch_size parsed items before invoking your async callback. The last batch may contain fewer items. Lines that fail to parse are silently skipped.
// Process 100 products at a time — great for DB writes, API calls, S3 uploads
client.bulk_operation.stream_products.await?;
Custom Bulk Queries
For queries the templates don't cover, use run_query with your own GraphQL and stream_jsonl to consume the result:
let query = r#"{
products {
edges {
node { id title tags }
}
}
}"#;
client.bulk_operation.run_query.await?;
// ... poll until complete, get the url ...
// Stream raw JSON lines in batches of 100
client.bulk_operation.stream_jsonl.await?;
If you already have JSONL content in memory (e.g. read from a local file), each export enum has a parse_line() method:
use ProductExportLine;
let parsed = parse_line?;
Webhooks
Parse Shopify compliance webhooks with type safety:
use ;
match parse_webhook_with_header
Request Callbacks
Add observability with before/after hooks on every request:
use ShopifyClient;
use Arc;
let client = new_with_callbacks;
- Fires on every REST and GraphQL request
- Access token is never passed to callbacks
- Panic-safe — callback panics won't crash your app
Error Handling
All methods return Result<T, APIError>:
Project Structure
src/
├── lib.rs # ShopifyClient entry point
├── types/ # Public type definitions
│ ├── order.rs # Order types + query enums (OrderStatus, ...)
│ ├── product.rs # ProductStatus, ProductQueryParams
│ ├── collection.rs # CollectionType, CollectionQueryParams
│ ├── customer.rs # CustomerAccountState, CustomerQueryParams
│ ├── inventory.rs # InventoryItemQueryParams
│ ├── draft_order.rs # DraftOrderFilterStatus, DraftOrderQueryParams
│ ├── subscription.rs # Subscription requests & responses
│ ├── discount.rs # Discount inputs & responses
│ ├── app_installation.rs # Metafield management types
│ ├── cart_transform.rs # Cart transform inputs & CAS metafields
│ ├── shop.rs # Shop, StaffMember, ShopPlan, ...
│ ├── shopify_functions.rs # Function listing types
│ ├── storefront_access_token.rs # Token create/delete types
│ └── bulk_operation.rs # Bulk ops: core types, JSONL export types
├── services/ # Internal service implementations
│ ├── order/ # REST: get, patch
│ ├── subscription/ # GraphQL: create, cancel, extend, ...
│ ├── discount/ # GraphQL: create, update, list
│ ├── app_installation/ # GraphQL: metafields CRUD
│ ├── cart_transform/ # GraphQL: create, set metafields
│ ├── shop/ # GraphQL: get shop info
│ ├── shopify_functions/ # GraphQL: list functions
│ ├── storefront_access_token/ # GraphQL: create, delete tokens
│ └── bulk_operation/ # GraphQL: queries, mutations, exports
├── webhooks/ # Webhook parsing & types
└── common/ # Shared HTTP, error types, query filters
Requirements
- Rust 2021 edition (1.56+)
- Dependencies:
reqwest,serde,serde_json,hmac,sha2,base64
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
License
This project is licensed under the MIT License.
This is an unofficial client library. For official Shopify documentation, visit shopify.dev.