Shopify & Amazon SP-API
OAuth, scopes, GraphQL productCreate, SP-API listings, and how rate limits stay isolated.
Shopify setup
- Create a custom app in Shopify Partners or the shop Admin
- Scopes:
write_products,read_inventory(add write inventory if you will push stock) - Destinations → Shopify → OAuth with your
*.myshopify.comdomain
The shop domain is required. A generic “Shopify” login without a shop will not create a destination account.
Tokens are stored encrypted on destination_accounts. Re-connect if you rotate the custom app secret.
Shopify publish path
eListSync posts Admin GraphQL productCreate (and variant payloads) through the Shopify dispatcher. Options come from canonical variant attributes (Color/Size). Images must be HTTPS URLs Shopify can fetch.
Inventory updates after orders use the same destination account. If GraphQL returns a userError (duplicate SKU, missing option), that string is copied into channel_sync_logs.
Amazon setup
- Register an SP-API application in Seller Central
- Complete LWA OAuth; eListSync stores the refresh token encrypted
- Confirm the marketplace id you intend to list on (this is not inferred from the marketing site)
Brand registry / approval is Amazon’s process. eListSync will not invent a brand authorization you do not have.
Amazon publish path
Transformers emit listings items JSON. Jobs run on the **Amazon** bulkhead. Restore-rate 429s trigger backoff on that queue only.
If Amazon rejects an attribute (invalid product type, missing bullet), fix the canonical metadata and republish. Do not edit the transformer for a single SKU.
Queue isolation
Shopify GraphQL cost limits and Amazon restore rates are the usual reason people think “the whole app is slow.” It is not. Bulkheads keep those two from sharing a concurrency pool with TikTok, Woo, or Medusa.
Common errors
- Shopify 401 — app uninstalled or scopes revoked; reconnect
- Shopify userError duplicate SKU — SKU already on that shop; map to update or change SKU
- Amazon 403 — missing role / listing permission
- Amazon 429 — wait; breaker may open after sustained failures
- Empty listing — product had no variants or no price at transform time