- OAuth 2.0 authorization code flow with PKCE; /api/etsy/connect returns the
consent URL, /api/etsy/callback exchanges the code (validated via one-time
state, no JWT) and stores tokens per user with automatic refresh
- /api/etsy/sync pulls all shop receipts and upserts orders by receipt id:
items with SKU/variations, totals, shipping address, tracking, and status,
with catalog costs snapshotted at sync time
- Product matching by exact title/alias first, then etsyListingId
(size-disambiguated); listing ids are learned onto products on first match
- Packing-slip items with cost data are preserved when synced items can't all
be matched
- Settings page: Connect Etsy Shop, Sync Orders Now, Disconnect, and a list
of unmatched item titles after each sync
- Requires ETSY_API_KEY and ETSY_REDIRECT_URI env vars (see .env.example)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>