Connect Shopify to Back-mund
Back-mund is the customer's product information manager. It will push products, variants, prices, images and inventory into Shopify automatically. The install uses Shopify's Dev Dashboard custom-distribution flow — no App Store, no embedded UI. Total setup on your side: ~30 seconds after the app is configured.
System status
TL;DR checklist
partners.shopify.com/dashboard): create a new app named Back-mund PIMback-mund.humanji.se/admin/api → Connection. Green panel = done.1. Pre-flight
What you need before starting
- A Shopify Partners account with Dev Dashboard access (
partners.shopify.com) — free - The
*.myshopify.com-domain of the merchant's store you want to install on - A secure channel (1Password, Bitwarden, encrypted email) to share the access token with Humanji
Why Dev Dashboard, not legacy Custom Apps?
2. Create the app in Dev Dashboard
- Log in at partners.shopify.com/dashboard
- Click Apps in the left nav → Create app → Create app manually
- Name it
Back-mund PIM - Click Create
3. Configure URLs
On the new app's Configuration page, set these values exactly:
App URL https://back-mund.humanji.se
Allowed redirection URL(s) https://back-mund.humanji.se/api/shopify/install-callbackClick Save.
⚠ The redirection URL must match exactly
redirect_uri_mismatch and you land on a 4xx page instead of Back-mund.4. Configure Admin API scopes
Still on Configuration → Admin API integration → Configure. Enable exactly these seven scopes:
| Scope | Why Back-mund needs it |
|---|---|
| read_products | Look up existing Shopify products by handle (idempotent upsert) |
| write_products | Create or update product titles, variants, descriptions, prices |
| read_inventory | Read existing inventory levels (sanity check) |
| write_inventory | Push the merchant's stock levels from PIM into Shopify |
| read_locations | Find the merchant's default inventory location |
| read_files | Pre-flight check that media uploads will work |
| write_files | Upload product image media via productCreateMedia |
Click Save. Then bump the app version (Versions tab) so the scopes apply.
5. Set up custom distribution
Go to the Distribution tab → Custom distribution:
- Add the merchant's store domain (the
*.myshopify.comform) - Click Generate install link
The link is one-time-use per install. If you misplace it, just generate a new one.
6. Install — and copy the env-snippet
- Open the install link in a browser where you're logged in to the merchant's Shopify Admin
- Confirm the install in Shopify's prompt
- You're redirected to Back-mund's success page on
back-mund.humanji.se/api/shopify/install-callback - Click Kopiera env-snippet on that page
⚠ Critical: the token is shown only once on the success page
The snippet looks like this:
SHOPIFY_STORE_DOMAIN=<storename>.myshopify.com
SHOPIFY_ADMIN_TOKEN=shpat_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx7. Hand the snippet to Humanji
Send via 1Password / encrypted email — never in plaintext chat. Humanji pastes the two values into Vercel (back-mund project → Settings → Environment Variables → Production), and triggers a redeploy.
Optional extra env-vars Humanji can set: SHOPIFY_API_VERSION (default 2026-04) and SHOPIFY_LOCATION_ID (auto-discovered if omitted).
8. Verify
In the Back-mund admin: back-mund.humanji.se/admin/api → Connection tab → click Test connection.
Expected (green panel):
Connected to <Shop name>
Domain <storename>.myshopify.com
Primary URL https://<custom-domain>/
Currency SEK
API version 2026-04
Location gid://shopify/Location/<numeric>If you get an error, see “Troubleshooting” below.
Field mapping
What Back-mund pushes into Shopify
| Back-mund | Shopify | Pushed by |
|---|---|---|
| products.slug | handle (idempotency key) | full upsert |
| products.title | title | full upsert |
| products.description | descriptionHtml | full upsert |
| products.brand | vendor | full upsert |
| products.color | tag | full upsert |
| products.is_published | status (ACTIVE / DRAFT) | full upsert |
| product_variants.size | option Storlek value | full upsert |
| product_variants.sell_price | price | full upsert only |
| product_variants.sku | sku | full upsert |
| product_variants.ean | barcode | full upsert |
| product_variants.stock | inventory @ default location | both paths |
| product_images.url (first 10) | media originalSource | full upsert |
Note: Back-mund won't overwrite manually-edited Shopify prices on the daily delta sync. Only a full upsert (when a product first appears, or a manual re-sync) writes price.
Daily flow after setup
After the env vars are in place, the merchant doesn't have to do anything. The pipeline runs itself:
- Every morning the supplier emails an .xlsx attachment to
feed@inbound.humanji.se - Postmark Inbound forwards it as a webhook to Back-mund
- Back-mund queues the rows; a Vercel Cron worker drains them in 100-row chunks every 2 minutes (~30–40 min total)
- When the import is done,
productSet+inventorySetQuantitiespush changes into Shopify - The merchant sees the result in
/admin/api → History
Troubleshooting
Install link → 4xx redirect_uri_mismatch+
The Allowed redirection URL on Configuration must match https://back-mund.humanji.se/api/shopify/install-callback exactly — including the path. No trailing slash, no extra query params. Save and try the install link again.
Success page shows 'HMAC-validering misslyckades'+
Either the install link was tampered with mid-flight, or Humanji's SHOPIFY_CLIENT_SECRETin Vercel doesn't match the one in Dev Dashboard. Re-copy the client secret from Dev Dashboard → Configuration and have Humanji re-set it on Vercel + redeploy.
Success page shows 'Saknade env-vars'+
Humanji hasn't set SHOPIFY_CLIENT_ID + SHOPIFY_CLIENT_SECRETin Vercel yet, or hasn't redeployed since. These are required on the Back-mund side before you run the install link.
Token exchange fails / Shopify 400 'invalid_request'+
The OAuth code is one-shot — if you reload the success page after a successful exchange, you'll see this error on the second hit (the first hit already used the code). Just generate a new install link from Dev Dashboard.
"Connection failed" / 401 from Shopify in /admin/api+
- Verify the token in Vercel starts with
shpat_(notshpss_or anything else) and has no whitespace - Make sure all 7 scopes are enabled in Dev Dashboard, and a new app version is shipped
- Confirm the app shows as installed on the merchant's store (Shopify Admin → Settings → Apps and sales channels)
"Connection failed" / 404 on the shop+
SHOPIFY_STORE_DOMAIN must be the *.myshopify.com form, not the custom domain. Even if the public storefront is shop.example.com, the API hostname stays <storename>.myshopify.com.
inventorySetQuantities userErrors mention 'location'+
The store has multiple locations and Back-mund picked the wrong one. Set SHOPIFY_LOCATION_ID explicitly to the numeric ID from Shopify Admin → Settings → Locations → click the location → URL contains the ID.
Rate-limited+
Shopify GraphQL has a calculated query cost bucket. If a sync hits 429 the cron worker stops the batch and resumes from the unfinished item on the next 2-minute tick. No manual intervention needed.
What about Shopify apps for the storefront?
The integration does not require any Shopify app on the storefront side. You can build the store with whichever theme and apps the merchant prefers. Common picks for this type of business:
| Need | Common app(s) |
|---|---|
| Reviews | Loox, Yotpo, Judge.me |
| Translation | Translate & Adapt (built-in), Weglot |
| Email + SMS | Klaviyo, Omnisend |
| SEO | Search & Discovery (built-in), JSON-LD for SEO |
| Currency / market | Markets (built-in), Geolocation |
| Cookies / GDPR | Pandectes, Customer Privacy (built-in) |
These are independent of Back-mund and can be added/removed at any time.
Reference
- Shopify Admin GraphQL API — shopify.dev/docs/api/admin-graphql
- Authorization code grant (OAuth) — shopify.dev/.../authorization-code-grant
- Custom distribution apps — shopify.dev/.../custom-distribution
productSet— shopify.dev/.../mutations/productSetinventorySetQuantities— shopify.dev/.../mutations/inventorySetQuantities- Rate limits — shopify.dev/docs/api/usage/rate-limits