Import shipment tracking numbers into already fulfilled Shopify orders from a CSV file, trigger the customer shipping email, and get a per-row report of what succeeded and what failed.
Architecture and diagrams: docs/ARCHITECTURE.md.
- Reads a CSV with
Shopify Order Number,Tracking Number,Shipping Carrier. - Validates the file: required columns, empty fields, duplicate tracking numbers inside the file.
- Matches each row to an existing fulfilled order via the Shopify Admin GraphQL API.
- Updates the existing fulfillment with the tracking number and carrier.
- Triggers Shopify's customer shipping notification email (
notifyCustomer: true). - Renders a report table: updated rows and errors (order not found, not fulfilled, duplicate tracking).
Each row is independent, so a bad row does not abort the run. It lands in the report with its reason.
npm install
cp env.example .env # fill in your dev store domain and Admin API token
npm run dev # http://localhost:3000Open http://localhost:3000, upload sample.csv, read the report.
You need a Shopify development store and a custom app Admin API access token with order and fulfillment scopes. See the setup steps in docs/ARCHITECTURE.md decisions and the env.example file.
Upload form and the per-row report (styled after the Shopify admin):
Re-uploading the same file is safe: rows whose tracking is already set are skipped and no duplicate email goes to the customer. The Force resend checkbox overrides this when you do want the emails sent again.
What the merchant and the customer see after a run:
The order timeline confirms the app updated tracking and sent the notification:
Node / TypeScript (ESM), Shopify Admin GraphQL API 2026-07 via @shopify/admin-api-client, Express plus multer for the web layer, vitest for tests.
Integration engineer, 16 years building backend and ETL systems for an Enterprise FinTech (under NDA). This repo is a public sample of Shopify Admin API integration work.