# Connecting Shopify or WooCommerce

A store connection brings the store's products, stock and orders into Karmaflow.ai and, when you choose, sends products and stock back. Each store is its own connection with its own settings, so a business with a Shopify storefront and a WooCommerce wholesale site can run both. The first decision is who owns the count; everything else follows from it.

## What you'll need

- **Manage Inventory Settings, Locations & Stores** (`inventory:config:manage`) — the seeded **Manager** role.
- **Shopify:** a custom app on the store with Admin API access. In Shopify admin, **Settings → Apps and sales channels → Develop apps → Create an app**; give it Admin API scopes for products, inventory, orders, locations and webhooks (read and write); install it; copy the **Admin API access token** and the **API secret key**.
- **WooCommerce:** a REST API key. In WordPress, **WooCommerce → Settings → Advanced → REST API → Add key** with **Read/Write** permissions; copy the consumer key and secret before leaving the page (WooCommerce shows them once). The site must serve the REST API over HTTPS.

## Connect a store

**Inventory → Setup → Stores** (`/inventory/stores`).

1. Click **Connect a store**.
2. Choose **Shopify** or **WooCommerce** and give the connection a **Name** (how this store is called here).
3. Shopify: enter the **Store domain** (the permanent `myshopify.com` address), the **Admin API access token** and the **API secret key**. WooCommerce: enter the **Store URL**, the **Consumer key** and the **Consumer secret**.
4. Click **Connect & verify**. Karmaflow.ai calls the store once to confirm the credentials and read its name and currency.

Credentials are stored encrypted and never shown again. Nothing syncs until you choose the directions and run a sync; a failed verification shows the store's error on the connection, with **Verify** to try again after you fix the key.

## Who owns the count

Open the connection. The first card, **Who owns the count**, is the one setting that decides what an order does:

| Choice | What happens |
|---|---|
| **The store** | Shopify or WooCommerce already deducts for its own orders. Its stock figure is pulled here on every sync and webhook, and store orders are recorded without touching stock. Right for a store that is already selling and for a business that counts in the store. |
| **Karmaflow** | Stock is managed here — several locations, purchase orders, counts — and the level is pushed to the store after every change. Store orders deduct here, like any other order. Right when the shelf, not the storefront, is the truth. |

Switching from *The store* to *Karmaflow* changes the **Stock** direction to *Here → store* and vice versa; check the levels before the first push, because the next change to a level overwrites the store's figure.

## Directions

- **Products** — *Off*, *Store → here*, *Here → store* or *Both ways*. Pulling brings the store's products in and keeps them updated; pushing sends a product edited here to the store.
- **Stock** — *Store → here* under store authority (pulled on sync and webhooks), *Here → store* under Karmaflow authority (pushed after every change).
- **Orders** — *Off* or *Store → here*. Orders are never pushed to a store.
- **Sync every (minutes)** — the catch-up interval (default 15, minimum 5). Webhooks are the real-time path; this is what survives a missed delivery.
- **Default location** — where store stock lands when nothing maps it.
- **Orders placed after** — older orders are not imported. It is set to the moment you connected, so a store with years of history does not flood the list.
- **Match or create a CRM contact for each order's customer** — on by default; the customer on each imported order is matched to a contact by email or phone, or created.
- **Scheduled sync enabled** — untick to pause the catch-up without disconnecting.

Click **Save**.

### Shopify locations

Under **Locations**, click **Load from Shopify** and pick which of your locations each Shopify location is. Unmapped locations land on the default. Under Karmaflow authority, a level pushed to Shopify goes to the location mapped to it; under store authority, each Shopify location's figure lands on its mapped location.

WooCommerce has one stock figure per product; it lands on, and is pushed from, the connection's default location.

## Sync now, and the history

The **Sync now** card has two buttons:

- **Sync changes** — products and orders changed since the last run, plus the stock levels. The incremental sync re-reads a few minutes of overlap so nothing between two runs is lost.
- **Full re-sync** — everything, from the start. Use it after changing the directions or the authority, or when the store and Karmaflow.ai disagree and you want the store's current state.

Under the buttons: the last run's figures (products created and updated, levels, pushed, orders) and the run history with each run's trigger (*manual*, *tick*, *webhook*, *connect*), status (*ok*, *partial*, *failed*) and errors.

### Products edited on both sides

A product pulled from the store remembers the values it was synced with. On the next pull, a field you changed here since then is kept, and a field you did not touch takes the store's value — so a description rewritten here survives a price change made in the store. A store-side SKU change that collides with another local SKU keeps the local one.

### Big catalogs

A run reads up to 50 pages of 100 products; a larger catalog is brought in across runs rather than in one request storm, and the run says it was truncated.

## Real-time updates (webhooks)

Click **Register** under **Real-time updates (webhooks)**. Karmaflow.ai registers the topics on the store through its API:

- Shopify: `products/create`, `products/update`, `products/delete`, `inventory_levels/update`, `orders/create`, `orders/updated`, `orders/paid`, `orders/fulfilled`, `orders/cancelled`. Shopify signs each delivery with the app's **API secret key**, so the key must be saved on the connection.
- WooCommerce: `product.created`, `product.updated`, `product.deleted`, `order.created`, `order.updated`, signed with a secret only this workspace knows.

The card shows the **Receiver** URL (copy it if you ever register a webhook by hand), how many are registered, and the last delivery. **Re-register** repairs them; **Remove** deletes them from the store; **Regenerate URL & secret** invalidates the existing registrations until you register again. A delivery with a bad signature is refused and nothing is written.

A store without webhooks still works: changes arrive on the scheduled sync.

## When a sync fails

After three consecutive failures the connection backs off (five minutes, doubling, up to six hours) and raises the notification **A store sync stopped working** — email straight away, by default, to everyone with **Manage Inventory Settings, Locations & Stores** — and the workflow trigger **Store sync failed** fires with the platform and the error. The connection card shows the last error and when it retries; the Settings hub row reads *N stores connected · 1 failing*. A successful run clears the backoff.

## Disconnect

**Disconnect** removes the connection and its webhooks. Products and orders already imported stay, with their store links kept, so reconnecting the same store relinks them instead of creating duplicates.

## Limits

- Orders flow one way: from the store. An order created in Karmaflow.ai is not sent to the store.
- A product created here reaches the store when you click **Publish to <store>** in the **Stores** card of its product page (shown for every connected store the product is not yet listed in); the first push creates it on the store, and a later push updates it. A product edit is not pushed on save.
- Shopify's REST Admin API is used; a very large store may hit Shopify's rate limit, which the client waits out.
- Refunds arrive as a cancelled order, which puts the units back under Karmaflow authority.

## Troubleshooting

- **"Verification failed: 401" (Shopify).** The access token is wrong or the app was uninstalled. Reinstall the app, copy the token again and paste it into **Credentials**.
- **"Verification failed: 401" (WooCommerce).** The key lacks Read/Write, or the site strips the Authorization header. Karmaflow.ai retries with query-string credentials automatically; if that fails too, check the server's `.htaccess` or ask the host.
- **Stock is right in the store but wrong here.** The authority is *Karmaflow* and the levels here were never set. Either count the stock here, or switch to *The store* and run **Full re-sync**.
- **Webhooks registered, nothing arrives.** On Shopify, the **API secret key** is not saved — deliveries are refused as unsigned. Paste it under **Credentials**, save, then **Re-register**.
- **The same product twice.** The store product had no SKU, so it could not be linked to an existing local one. Give both the same SKU and run **Full re-sync**; the next pull links them.

## Next steps

- [Sales and Purchase Orders](/help/inventory/orders) — what an imported order does to stock.
- [AI Assistance and Agent Tools](/help/inventory/ai-assistance) — the automations that run on imported products.
