---
name: manifold-from-shopify
description: Set up Manifold for a merchant who sells on Shopify today, through their agent — the merchant installs the Manifold app from Shopify, then you bind the store's locations, use the store as a template (catalogs, products, stock, customers, companies, and orders — closed ones as history, open ones live), and walk the rest of setup to go-live. Use when a Shopify merchant wants to move their back office, stock or orders onto Manifold.
---

# Setting Manifold up from a Shopify store

**Who this is for:** a merchant whose business runs on a Shopify store and who has no other inventory system they are leaving. Their products, stock, customers and orders live in Shopify; Manifold becomes the back office behind the store.

If they also run Cin7 (or another ERP) beside Shopify, stop and use the **manifold-shopify-and-cin7** skill instead: the order you connect things in matters there.

## What the merchant needs ready

- **Owner or staff access to the Shopify admin** with permission to install apps. Only they can approve the app.
- **A Manifold account**, or ten minutes to make one. Installing the app from Shopify makes one for them if they have none.
- **The Manifold connector** in this client (`https://mcp.getmanifold.io/mcp`). The **manifold-onboarding** skill, step 2, says how to connect it.

## Never

- Never ask for, read out or type a password, an API key, a Shopify access token or a card number. The Shopify install is approved in Shopify's own page; billing is started on Stripe's page or approved on Shopify's, never in this conversation.
- Never install, uninstall or approve the app for them. You cannot, and an agent must not try: it is the merchant's consent.
- Never decide go-live, the plan or who joins the team. Ask, and send them to the screen.
- Never invent data. Everything here comes from the store.

## 1. The install (the merchant's step)

Ask the merchant to install Manifold on their store. Two ways, both theirs:

- **From the Manifold admin:** `https://admin.getmanifold.io/settings/setup?step=source`. In "Where do your products and orders live today?" they pick **Shopify**, type the store's `.myshopify.com` address and approve the app in the Shopify admin it opens.
- **From Shopify:** the Shopify App Store, search "Manifold", **Install**. A store with no Manifold account gets an organization made for it, and the merchant signs in from inside Shopify.

Wait until they say it is done. Then connect the Manifold connector if it is not connected, picking the organization the store joined.

## 2. Find the store

1. `onboarding_get_status`. A journey started by the install has the `app:shopify` step. If there is no journey, `onboarding_start` with `source: "agent"`.
2. `shopify_list_connections`. Take the connection whose `shopDomain` is their store and check its `status` is `connected`. A `pending` store means the approval in Shopify did not finish: send them back to it.
3. `shopify_list_catalog_targets` for the connection. Its first row is the shop's base prices, in the shop's own currency.

## 3. The business profile

`onboarding_set_profile`: business name, country, timezone and the currency **the store prices in** (step 2's base-prices currency). Ask what you do not know: whether they sell retail, wholesale or both, whether they buy from suppliers, and `channels` (at least `store`, for the Shopify store). A currency that differs from the store's makes every price mapping refuse later (`CatalogCurrencyMismatch`).

## 4. Locations

Every Shopify location that holds stock must be bound to one Manifold location. A binding is fixed once made, so ask before each one.

1. `shopify_list_store_locations`. Each row says whether it is bound (`locationId`). Right after the install, the app reads the store's locations and pairs each with a Manifold location of the same name (the store's Main with `Main`). That takes a few seconds: if nothing is bound yet, wait half a minute and read again before binding anything.
2. For each unbound, active location, ask the merchant: is this `Main` (`inventory_list_locations`), or a place of its own? A new place is `inventory_create_location` first.
3. `shopify_update_connection` with `locationMappings` (`shopifyLocationId`, `locationId`, `locationName`): **the whole set**, every binding `shopify_list_store_locations` already shows plus the new ones they agreed. A binding left out counts as dropped.
4. Read `shopify_list_store_locations` again after a few seconds: the binding shows once the reading it started has run.

A `409 LocationBindingLocked` means the call would move or drop a binding that is already made (usually one left out of the set). Read the locations again, send the whole set, and carry on.

## 5. Use the store as a template

`shopify_import_from_store` brings the store across by area. Mint one `jobId` (`job_<uuid>`) for the call and reuse it on any retry. Ask which areas they want:

- **`catalogs`**: a Manifold catalog per Shopify catalog, then the store's products and variants (one SKU each, uppercased), their prices, and opening stock at the bound locations.
- **`customers`**: the store's customers, and, where it sells B2B, its companies with their contacts and locations.
- **`orders`**: orders placed before the store was connected. The ones that ended (fulfilled, refunded, cancelled) come across as history (`fulfillment_list_historical_orders`). The open ones become live orders, with only what is left to ship.

Turn order bridging on first if open orders should become live ones (§6): an open order is handed to the bridge only when the store bridges orders.

Follow the import with `shopify_get_connection`: its `imports` say where each area stands (`running`, `completed` or `failed`) and what it counted. Read it again every half a minute or so; an import has no status of its own for `manifold_wait`. The `catalogs` area names the product pull it started (`pullId`): `manifold_wait` on `shopify_get_catalog_pull` with that `pullId` until `applied` or `failed`. `shopify_list_jobs` lists the runs behind it all.

**Variants without a SKU** are skipped. If the merchant wants a preview first, or SKUs made from the product handle, use `shopify_request_catalog_pull` instead of the `catalogs` area (`skuFallback: "handle"`, without `applyImmediately`). Wait for it to be `previewed` with `shopify_get_catalog_pull`, show them the summary, and `shopify_apply_catalog_pull` on their word.

## 6. Prices and orders flowing

- **Catalog mappings**: which Manifold catalog prices which Shopify catalog. Read the targets with `shopify_list_catalog_targets`, and the Manifold catalogs with `catalog_list_catalogs`, then propose a mapping and set it, on the merchant's word, with `shopify_update_connection` (`catalogMappings`).
- **Order bridging**: `bridgeOrders: true` on `shopify_update_connection` makes each new Shopify order a Manifold order. An order the bridge refused (an unknown SKU, usually) shows in `shopify_list_unbridged_orders`: fix the cause, then `shopify_retry_order_bridge`.

## 7. The rest of setup

Hand back to the **manifold-onboarding** skill from its step 5 for the checklist: the order pipeline (`fulfillment_set_workflow`), suppliers, the accounting basis, the opening stocktake, books, billing and team. For a Shopify merchant:

- **Billing depends on how the organization was made.** There is no tool that reads it; Settings › Billing shows which, so ask the merchant what it says.
  - **The install made the organization** (they had no Manifold account and installed from the Shopify App Store): billing is on their Shopify bill. The first 30 days are free with no plan. They approve the plan at Settings › Billing, which sends them to Shopify's page.
  - **They signed up on Manifold first** (the website, then the setup walk or Settings › Sales channels): connecting the store does not move billing. They start the 60-day trial on a card at Settings › Billing, through Stripe, like any other organization.
  - Either way it is theirs to do. Never approve a plan or start a trial for them.
- **The opening stocktake** (`inventory_start_stocktake`, `inventory_stocktake_sheet`, `inventory_record_stocktake_counts`) counts what the store said it had. Go through what looks wrong with them.

## What stays read-only until go-live

A new organization is **read-only**: nothing leaves Manifold. Orders, customers and stock still come **in** from Shopify. But no stock level, price, fulfilment or product is pushed **to** Shopify, and a push is refused with `409 ConnectionReadOnly` (`heldBy: "organization"`). That is the safety net while they check Manifold against their store. There is no tool that reads the mode: the badge at the top of the admin shows it. Tell the merchant this when they ask why Shopify did not change.

**Going live** is the owner's or an admin's decision, typed in at Settings › General. It needs every stock SKU costed (the opening stocktake completes at go-live) and, for an organization billed through Shopify, a plan approved there (`409 PlanRequiredToGoLive` otherwise). From then, Manifold drives the store: stock at the next check, prices on the mapped catalogs. Ask them; never imply it has happened.

## Done looks like

- `onboarding_get_status`: `app:shopify`, `products` and `locations` done, the rest done or skipped on the merchant's word, billing started (a plan approved on Shopify, or the card trial).
- `shopify_list_store_locations`: every active location bound.
- `inventory_list_items` matches the store's products. `shopify_list_unbridged_orders` is empty.
- The merchant knows they are read-only until they go live, and where that switch is.

## When it goes wrong

| What you see | What it means | Next |
|---|---|---|
| `shopify_list_connections` is empty | The app is not installed in this organization, or the connector is connected to another one | Ask which organization they installed into; reconnect the connector there |
| `409 ConnectionNotConnected` | The store is `pending`: Shopify's approval did not finish | The merchant reopens the app from the Shopify admin |
| `409 CatalogCurrencyMismatch` | The Manifold catalog prices in another currency than the Shopify one | Map a catalog in the store's currency, or create one (`catalog_create_catalog`) |
| An import area `failed` | Shopify refused, or throttled the read | Read `shopify_list_exchanges` for the call; run `shopify_import_from_store` again under a **new** `jobId` for that area alone |
| Orders in `shopify_list_unbridged_orders` | A line names a SKU Manifold does not have | Import or create the SKU, then `shopify_retry_order_bridge` |
| `409 ConnectionReadOnly` on a push | The organization is read-only | Expected until go-live; say so |
