DPP Agent docs

Shopify — integration guide

DPP Agent connects to Shopify via the Admin REST API with an OAuth-installable app. One pass populates a DPP per variant SKU, with the variant's barcode acting as the GTIN.

What the adapter does, in one sentence

DPP Agent paginates /admin/api/<version>/products.json, splits each Product into one DPP row per variant whose barcode is a valid GTIN (8–14 digits), and ingests through the conflict-aware pipeline. Read-only, no Shopify-side changes, no write-back.

Authentication

OAuth Admin app install — the standard Shopify app flow:

  1. Operator clicks Connect Shopify in DPP Agent
  2. Redirect to <shop>.myshopify.com/admin/oauth/authorize with the requested scopes
  3. Merchant approves
  4. Shopify redirects back to our OAuth callback at /api/integrations/shopify/oauth-callback with a code
  5. We exchange the code for a permanent access token, encrypt it, store it

All subsequent calls use X-Shopify-Access-Token: <token>.

Credential handling

Same envelope as the other adapters: AES-256-GCM at rest, redacted in the UI, decrypted in-memory only, never logged. Uninstalling the DPP Agent app from the Shopify admin revokes the token immediately.

Scope limitation

1. Single OAuth scope: read_products

The app installs with only read_products. No customers, no orders, no draft orders, no inventory levels, no app billing data — nothing beyond the product catalogue.

If your store enables the Customer Data protected scopes, our install flow does not request them and Shopify will not grant them.

2. Status filter

settings.product_status = "active" (default) restricts the fetch to live products. Drafts and archived items are not returned.

3. Barcode-as-GTIN gate

Variants without a valid 8–14 digit barcode are dropped at the mapper before they reach the ingest pipeline. This means:

  • Apparel SKUs with no EAN never produce a DPP row
  • Products that use SKU instead of barcode are not mapped
  • You can backfill barcodes in Shopify and re-sync

4. Network IP allowlist

Shopify does not expose a firewall, but Vercel-side egress IPs are published if your monitoring infrastructure wants to verify caller origin.

Settings reference

Setting Required Purpose
shop_domain yes <your-shop>.myshopify.com
api_version no Default 2025-07
product_status no Default active. Can be draft or archived for one-off pulls.

The OAuth access token is stored in the encrypted credential vault and is not editable from the UI — to rotate, uninstall + reinstall the app from the Shopify admin.

Sync semantics

Conflict policy is the platform default:

  • Draft DPPs are overwritten
  • Active DPPs spawn dpp_revisions(status=pending) for human review
  • Withdrawn / archived / recalled DPPs are skipped

Deletion: if a product disappears from Shopify, the corresponding DPP remains in dpp_runtime. Same EN 18219 / EN 18223 retention reasoning as the other adapters.

Onboarding sequence

  1. Operator clicks Connect Shopify, picks the store domain
  2. OAuth consent → approve read_products
  3. Callback exchanges code for token, stores it, redirects back
  4. Adapter runs a connection test against /admin/api/<v>/shop.json and reports the store name
  5. First sync, sync_max_pages = 2-3, validates the product → DPP mapping
  6. Full sync once mapping is locked
  7. Cron picks up the schedule (6h default)

Compliance hooks

ESPR field Shopify path
espr.pid.gtin variants[].barcode (must be 8–14 digits)
espr.pid.product_name title
espr.pid.product_description body_html (HTML stripped, capped at 600 chars)
espr.pid.color variants[].option1
espr.pid.size variants[].option2
tex.product.brand_category product_type
tex.pid.model_number variants[].sku
tex.product.hero_image_url images[0].src

Shopify doesn't structure supplier or supply-chain data — for AGEC traceability connect Delogue or TrusTrace alongside.

Troubleshooting

  • OAuth callback returns "invalid scope" — your custom Shopify app was configured without read_products; reinstall after fixing scope
  • HTTP 401 on sync — token revoked (app was uninstalled from Shopify admin); reinstall via DPP Agent → Integrations
  • HTTP 429 with Retry-After — Shopify rate limit; the adapter honours the header automatically. Repeated 429 means the store is under heavy load; lower page_size or schedule sync off-peak
  • Empty products — all products are draft/archived but product_status is set to active
  • GTIN missing on many rows — variants don't have barcodes filled. Bulk-update via Shopify CSV before relaunching the sync

Open a ticket at support@dppagent.com with the integration ID + log.