Shopify Partners SDK
Modern Python SDK for Shopify Partners API - Comprehensive GraphQL client with type safety, automatic pagination, and dual query approaches (raw GraphQL + dynamic FieldSelector). Built for developers who want powerful functionality without complex abstractions.
🚀 Key Features
🎯 Dual Query Approaches
- Raw GraphQL - Execute queries directly with full control
- Dynamic FieldSelector - Build queries programmatically with type safety
🛡️ Production-Ready
- Type Safety - Full type hints throughout the codebase
- Automatic Pagination - Built-in cursor-based pagination support
- Intelligent Rate Limiting - Exponential backoff with retry logic
- Comprehensive Error Handling - Detailed GraphQL and HTTP error messages
🚀 Developer Experience
- Zero Complex Abstractions - Direct GraphQL access with minimal overhead
- Synchronous API - Simple, intuitive Python interface
- Extensible Architecture - Easy to extend with custom field selections
- Rich Documentation - Comprehensive examples and API reference
📦 Installation
Using pip
pip install shopify-partners-sdk
Using Poetry
poetry add shopify-partners-sdk
Development Installation
# Clone the repository
git clone https://github.com/amitray007/shopify-partners-sdk.git
cd shopify-partners-sdk
# Install with Poetry
poetry install
# Or with pip in development mode
pip install -e .
⚡ Quick Start
1. Get Your Credentials
Get your credentials from the Shopify Partners Dashboard:
- Settings → API credentials
- Create or select an API credential
- Copy your Organization ID and Access Token (starts with
prtapi_)
2. Choose Your Approach
The SDK provides two ways to interact with the Shopify Partners API:
🎯 Option 1: FieldSelector (Recommended)
from shopify_partners_sdk import ShopifyPartnersClient, FieldSelector
# Initialize the client
client = ShopifyPartnersClient(
organization_id="your-org-id",
access_token="prtapi_your-access-token",
api_version="2025-04"
)
# Build and execute query with FieldSelector
fields = FieldSelector().add_fields('id', 'title', 'handle')
result = client.query('app', fields, id='your-app-id')
print(f"App: {result['app']['title']}")
client.close()
🔧 Option 2: Raw GraphQL
from shopify_partners_sdk import ShopifyPartnersClient
# Initialize the client
client = ShopifyPartnersClient(
organization_id="your-org-id",
access_token="prtapi_your-access-token",
api_version="2025-04"
)
# Execute raw GraphQL
query = """
query GetApp($id: ID!) {
app(id: $id) {
id
title
handle
}
}
"""
response = client.execute_raw(query, {"id": "your-app-id"})
result = response["data"]
print(f"App: {result['app']['title']}")
client.close()
3. Environment Variables
You can also configure the client using environment variables:
export SHOPIFY_PARTNERS_ORGANIZATION_ID="your-org-id"
export SHOPIFY_PARTNERS_ACCESS_TOKEN="prtapi_your-access-token"
export SHOPIFY_PARTNERS_API_VERSION="2025-04"
from shopify_partners_sdk import ShopifyPartnersClient
# Client will automatically use environment variables
client = ShopifyPartnersClient()
📚 Usage Examples
FieldSelector Approach (Recommended)
from shopify_partners_sdk import FieldSelector, CommonFields
# Simple query
fields = FieldSelector().add_fields('id', 'title', 'handle', 'apiKey')
result = client.query('app', fields, id='app-id')
# Query with nested fields
app_fields = (FieldSelector()
.add_fields('id', 'title', 'handle')
.add_nested_field('shop', FieldSelector().add_fields('name', 'myshopifyDomain')))
result = client.query('app', app_fields, id='app-id')
# Paginated connection query
app_fields = CommonFields.basic_app() # Predefined common fields
result = client.connection_query('apps', app_fields, first=25)
# Complex nested query with money fields
transaction_fields = (FieldSelector()
.add_fields('id', 'createdAt', 'type')
.add_money_field('netAmount') # Automatically adds amount and currencyCode
.add_nested_field('app', CommonFields.basic_app())
.add_nested_field('shop', CommonFields.basic_shop()))
result = client.connection_query('transactions', transaction_fields, first=50)
# Complex query with nested connections
event_fields = FieldSelector().add_field('type')
app_fields = (FieldSelector()
.add_field('name')
.add_connection_field('events', event_fields, first=10)) # Connection with args
result = client.query('app', app_fields, id='app-id')
Raw GraphQL Approach
# Get a single app
query = """
query GetApp($id: ID!) {
app(id: $id) {
id
title
handle
apiKey
}
}
"""
response = client.execute_raw(query, {"id": "app-id"})
app = response["data"]["app"]
# Get API versions
query = """
query GetApiVersions {
publicApiVersions {
handle
displayName
supported
}
}
"""
response = client.execute_raw(query)
versions = response["data"]["publicApiVersions"]
# Get paginated apps
query = """
query GetApps($first: Int!, $after: String) {
apps(first: $first, after: $after) {
edges {
cursor
node {
id
title
handle
}
}
pageInfo {
hasNextPage
hasPreviousPage
}
}
}
"""
response = client.execute_raw(query, {"first": 25})
apps = response["data"]["apps"]
Mutations
FieldSelector Mutations (Recommended)
# Create an app credit with FieldSelector
result_fields = (FieldSelector()
.add_nested_field('appCredit', FieldSelector()
.add_fields('id', 'description')
.add_money_field('amount'))
.add_nested_field('userErrors', FieldSelector()
.add_fields('field', 'message')))
input_data = {
"appId": "your-app-id",
"amount": {"amount": "10.00", "currencyCode": "USD"},
"description": "Refund for billing issue"
}
result = client.mutation('appCreditCreate', result_fields, input=input_data)
if result.get("userErrors"):
print("Errors:", result["userErrors"])
else:
print("Credit created:", result["appCredit"])
Raw GraphQL Mutations
# Create an app credit
mutation = """
mutation CreateAppCredit($input: AppCreditCreateInput!) {
appCreditCreate(input: $input) {
appCredit {
id
description
amount {
amount
currencyCode
}
}
userErrors {
field
message
}
}
}
"""
input_data = {
"appId": "your-app-id",
"amount": {"amount": "10.00", "currencyCode": "USD"},
"description": "Refund for billing issue"
}
response = client.execute_raw(mutation, {"input": input_data})
result = response["data"]
🏗️ Advanced Usage
Custom HTTP Client
import requests
from shopify_partners_sdk import ShopifyPartnersClient
# Custom HTTP client with specific settings
session = requests.Session()
session.timeout = 60.0
client = ShopifyPartnersClient(
organization_id="your-org-id",
access_token="your-token",
http_client=session
)
Error Handling
from shopify_partners_sdk.exceptions import (
AuthenticationError,
RateLimitError,
GraphQLError
)
try:
# FieldSelector approach
fields = FieldSelector().add_fields('id', 'title')
result = client.query('app', fields, id='invalid-id')
except AuthenticationError:
print("Invalid credentials")
except RateLimitError as e:
print(f"Rate limited. Retry after: {e.retry_after} seconds")
except GraphQLError as e:
print(f"GraphQL error: {e.message}")
try:
# Raw GraphQL approach
query = """
query GetApp($id: ID!) {
app(id: $id) { id title }
}
"""
response = client.execute_raw(query, {"id": "invalid-id"})
if response.get("errors"):
print("GraphQL errors:", response["errors"])
else:
result = response["data"]
except AuthenticationError:
print("Invalid credentials")
except RateLimitError as e:
print(f"Rate limited. Retry after: {e.retry_after} seconds")
Configuration
from shopify_partners_sdk.config import ShopifyPartnersSDKSettings
# Custom configuration
settings = ShopifyPartnersSDKSettings(
organization_id="your-org-id",
access_token="your-token",
api_version="2025-04",
base_url="https://partners.shopify.com",
timeout_seconds=30.0,
max_retries=3,
log_level="INFO"
)
client = ShopifyPartnersClient.from_settings(settings)
🔍 Available Types and Fields
Core Types
- App:
id,name,apiKey,events - Shop:
id,name,myshopifyDomain,avatarUrl - Organization:
id,name,avatarUrl - Transaction:
id,createdAt(interface) - Money:
amount,currencyCode - AppEvent:
type,occurredAt,app,shop(interface)
Billing Types
- AppCharge:
id,amount,name,test(interface) - AppCredit:
id,amount,name,test - AppSubscription:
id,amount,name,test,billingOn - AppPurchaseOneTime:
id,amount,name,test
Enums
- Currency:
USD,EUR,GBP,CAD,AUD, etc. - AppEventTypes:
RELATIONSHIP_INSTALLED,CREDIT_APPLIED,SUBSCRIPTION_CHARGE_ACCEPTED, etc. - TransactionType:
APP_ONE_TIME_SALE,APP_SUBSCRIPTION_SALE,SERVICE_SALE, etc. - AppPricingInterval:
EVERY_30_DAYS,ANNUAL
🛠️ Development
Setup Development Environment
# Clone the repository
git clone https://github.com/amitray007/shopify-partners-sdk.git
cd shopify-partners-sdk
# Install Poetry (if not already installed)
curl -sSL https://install.python-poetry.org | python3 -
# Install dependencies
poetry install
# Install pre-commit hooks
poetry run pre-commit install
🤝 Contributing
Contributions are welcome! Please read our Contributing Guide for details on our code of conduct and the process for submitting pull requests.
Development Workflow
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Make your changes
- Add tests for your changes
- Ensure all tests pass (
poetry run pytest) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
📄 License
This project is licensed under the MIT License - see the LICENSE file for details.
🔗 Links
📋 Changelog
See CHANGELOG.md for a list of changes and version history.
💬 Community & Support
- 📖 Documentation - Comprehensive guides and API reference
- 🐛 Issue Tracker - Bug reports and feature requests
- 💬 Discussions - Community Q&A and support
- 🚀 Examples - Real-world usage examples
🙏 Acknowledgments
- Built with Requests for reliable HTTP client functionality
- Uses Pydantic for data validation and settings management
- Inspired by the official Shopify GraphQL APIs and developer feedback
Made with ❤️ for the Shopify developer community
Metadata
Release files for shopify-partners-sdk 0.3.2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| shopify_partners_sdk-0.3.2.tar.gz | 47.2 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| shopify_partners_sdk-0.3.2-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 103.9 kB
Release files / shopify_partners_sdk-0.3.2.tar.gz
| Download URL | shopify_partners_sdk-0.3.2.tar.gz |
|---|---|
| Size | 47.2 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
d2c35205af4a14336b69dd3344e9fdf4279c979e77fada37d72fc1d7ca8d6428
|
|
BLAKE2b-256 checksum How to use checksums |
a46c6bb9177478eb482599b54050c12d0f797747843bab3e2a64bf41e25df6ab
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 21, 2025.
Transparency logRelease files / shopify_partners_sdk-0.3.2-py3-none-any.whl
| Download URL | shopify_partners_sdk-0.3.2-py3-none-any.whl |
|---|---|
| Size | 56.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
2d08232191c8e84ddc2204487d7499d5f8387aa3f5ac81214185795086839958
|
|
BLAKE2b-256 checksum How to use checksums |
f6cdbcc049ade251489550d90f11ccc3f4d73cdd07ee9f168c0aebcfd0584ceb
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 21, 2025.
Transparency log