Webhooks work with personal tokens when webhooks.read and webhooks.write scopes are enabled during token generation. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
10 KiB
Printify Integration Research
Research notes from investigating Printify API integration, product syncing, and order submission risks. This document captures findings for future implementation work.
Product Identity & Matching
What identifiers exist?
| Field | Stable? | Notes |
|---|---|---|
id (provider_product_id) |
❌ | Changes if product deleted & recreated |
sku (variant level) |
❌ | Auto-generated per product creation |
blueprint_id |
✅ | The base product type (e.g., Gildan 5000) |
print_provider_id |
✅ | The fulfillment provider |
title |
✅ | User-defined, stable unless edited |
Our matching strategy
- Primary: Match by
provider_product_id - Fallback: Match by
slug(derived from title) - Potential improvement: Match by
blueprint_id + print_provider_id + title
The slug fallback handles cases where Printify product IDs change (e.g., product deleted and recreated with same title).
How Shopify/Printify official integration works
- SKU is generated once when first published to Shopify
- SKU becomes the stable link for future updates
- Republishing matches by SKU
- The "publish lock" prevents editing after publishing
Duplicate Products
When duplicates occur
- Mock/test product generators run multiple times
- User accidentally creates products twice in Printify
- Migration scenarios with orphaned products
- Using multiple POD providers on same store
How we detect duplicates
Same title (and therefore same slug) but different provider_product_id.
In our test case, Printify returned 30 products but only 16 unique titles - every product existed twice with different IDs but identical:
titleblueprint_idprint_provider_id
How we handle duplicates
Our upsert_product/2 function matches by slug when provider_product_id lookup fails, treating them as the same product and updating the provider_product_id to the latest value.
Is this a common real-world issue?
Research suggests no - duplicate products aren't commonly reported. Main sync issues are:
- Orders not syncing
- Store connection expiring
- Publishing failures
- Product info being overwritten on republish
The official Shopify integration handles product identity well through SKUs.
Sales Channel Integration Options
Option 1: Personal API Token (current)
- Pull products via API
- Works immediately, no approval needed
- We don't appear in Printify's "Publish to..." UI
- Products not "locked" after sync
Option 2: OAuth Platform Integration
- Apply at printify.com/printify-api
- ~1 week approval process
- Merchants authorize SimpleShop via OAuth
- We appear in Printify's publishing UI alongside Shopify/Etsy
- Products get "published" TO us with lock
- Webhooks for real-time updates
How publishing works in Option 2:
- Merchant clicks "Publish to SimpleShop" in Printify
- Printify sends
product:publish:startedwebhook - We create the product on our side
- We call
publishing_succeeded.jsonto confirm - Product locked in Printify, shows as "Published to SimpleShop"
Benefits of official integration:
- Publish lock prevents editing after publishing (data consistency)
- Real-time webhooks
- "Official" feel for merchants
- Better UX in Printify dashboard
Downsides:
- Approval process
- More complex OAuth auth
- Ongoing partnership relationship
Order Submission Risks
How order submission works
We send to Printify:
%{
product_id: "printify_product_id",
variant_id: 12345,
quantity: 2
}
We do not send price. Printify charges their current wholesale cost.
Risk scenarios
| Scenario | Result | Who bears cost? |
|---|---|---|
| Wholesale cost increased | Order succeeds | Shop owner (you) |
| Wholesale cost decreased | Order succeeds | Shop owner profits more |
| Variant discontinued | Order fails | Customer experience |
| Product deleted | Order fails | Customer experience |
| Design changed | Order succeeds with new design | Customer gets wrong item |
Why the publish lock matters
In official integrations, the publish lock prevents merchants from editing products after publishing. This ensures:
- Price consistency between storefront and fulfillment cost
- Variant availability guaranteed
- Design matches what customer saw
Without the lock (our current approach), products can change between sync and order.
Recommended mitigations
-
Webhooks / frequent polling
- Subscribe to
product:updated,product:deletedevents - Or poll every N minutes for changes
- Update local product data immediately
- Subscribe to
-
Pre-checkout validation
- Before completing checkout, call Printify API
- Verify variant still exists
- Get current cost, compare to stored cost
- Alert or block if significant difference
-
Cost monitoring
- Store
costfrom Printify on each variant - During sync, compare old vs new cost
- Alert shop owner if cost increased significantly
- Consider auto-adjusting retail price
- Store
-
Graceful order failure handling
- Catch "variant not found" errors
- Notify customer immediately
- Offer refund or alternative
- Don't leave order in limbo
-
Stale data warnings
- Track
last_synced_atper product - Warn in admin if product not synced recently
- Consider blocking orders for very stale products
- Track
API Rate Limits
From Printify documentation:
- 600 requests/minute global
- 100 requests/minute for catalog endpoints
- 50 products per page max
- Product publishing: 200 requests per 30 minutes
Implementation Status
Completed
- Product sync with pagination
- Parallel processing (5 concurrent)
- Slug-based fallback matching
- Error recovery (try/rescue)
- Checksum-based change detection
Not yet implemented
- Webhook endpoint for real-time updates
- Pre-checkout variant validation
- Cost change monitoring/alerts
- OAuth platform integration (requires Printify approval)
blueprint_id + print_provider_idmatching
Open Source vs Managed Hosting Considerations
The core tension
SimpleShop exists in two forms:
- Open source - self-hosted by anyone
- Managed hosting - SaaS service run by us
Printify's integration options have different implications for each.
Personal API Token (current approach)
How it works:
- Each merchant creates their own Printify API token
- Token entered in SimpleShop admin
- Direct API access, no intermediary
Open source: ✅ Works perfectly
- Each self-hosted instance uses merchant's own token
- No central service required
- Full functionality
Managed hosting: ✅ Works perfectly
- Same as self-hosted
- Each tenant uses their own token
- No special relationship with Printify needed
Downsides:
- Merchants must manually create/manage API tokens
- No "Connect with Printify" button UX
- Products not locked after sync (data consistency risk)
Note: Webhooks DO work with personal tokens - merchant just needs to enable webhooks.read and webhooks.write scopes when generating the token.
OAuth Platform Integration
How it works:
- Register SimpleShop as an app with Printify
- Get OAuth client ID/secret
- Merchants click "Connect" and authorize
- We receive access tokens, appear in Printify UI
Open source: ❌ Problematic
- OAuth requires registered callback URLs
- Can't register infinite self-hosted domains
- Would need to proxy through a central service
- Defeats the "fully self-hosted" value proposition
Managed hosting: ✅ Works well
- Single registered callback URL
- "Connect with Printify" button
- Appears as official integration
- Real-time webhooks
- Publish lock for data consistency
Hybrid approach possibilities
Option A: Token for open source, OAuth for managed
- Open source uses personal API tokens (current)
- Managed hosting uses OAuth integration
- Two code paths, more maintenance
- Clear value differentiation
Option B: Webhook proxy service
- Register OAuth app
- Self-hosted instances connect through managed webhook proxy
- Proxy forwards webhooks to self-hosted URLs
- Adds dependency on central service
- Could be free tier for open source users
Option C: OAuth with self-registration
- Document how to register own OAuth app with Printify
- Self-hosters go through Printify approval themselves
- Complex, unlikely many would do this
- Each instance is independent
Business model implications
| Approach | Open Source | Managed Hosting |
|---|---|---|
| Personal API Token | Full feature parity | No differentiation |
| OAuth (managed only) | Basic sync only | Premium "official" integration |
| Webhook proxy | Depends on proxy | Full features |
Potential differentiation for managed hosting:
- Official "Publish to SimpleShop" in Printify UI
- Real-time sync via webhooks
- Publish lock (data consistency guarantee)
- Pre-checkout validation (verify before order)
- No token management for merchants
What open source keeps:
- Full product sync (polling-based)
- Order submission
- All admin features
- Self-hosted independence
Printify partnership considerations
What registering as an app might require:
- Application/approval process (~1 week)
- Technical integration review
- Ongoing partnership relationship
- Support obligations?
- Usage/volume commitments?
Questions to research:
- What are Printify's requirements for app partners?
- Are there fees or revenue sharing?
- Can we register once for managed hosting only?
- What support/SLA obligations exist?
- Can app be limited to specific redirect URIs (managed only)?
Recommendation
Phase 1 (now): Personal API tokens for both versions
- Works everywhere
- No partnership dependencies
- Validates product-market fit first
Phase 2 (if managed hosting gains traction): OAuth for managed only
- Apply for Printify app registration
- Implement OAuth flow for managed platform
- Keep token-based flow for open source
- Use as value differentiator
Phase 3 (optional): Webhook proxy for open source
- If demand exists for real-time sync in self-hosted
- Could be free or paid add-on
- Maintains open source independence while adding capability