Shopify connector setup

Operator·5 minutes to read

This page is the setup half — creating the Shopify app the connector authorises through, and getting its client id and secret into this deployment. Connecting a shop afterwards is the Authenticate control on the plugin sheet, which is what actually sends a member to their shop.

A member reaches this connector by asking their bot for something that needs it ("look at my orders", "connect my Shopify store"): the bot names the connector, and the card it posts is what the member authorises from. Nothing a bot does installs or authorises it.

1. Create the app in your Shopify Partner dashboard

  1. Open the Shopify Partner dashboard and create an app — this is your own app, not Botseon's.
  2. Under App URL and Allowed redirection URL(s), paste the redirect URL from README.md with shopify as the connector slug.
  3. Request the access scopes below. Request only the ones you want this deployment to be able to ask a member for: a scope the app does not hold is a scope no member can grant.
what it is forread scopewrite scope
products and collectionsread_productswrite_products
orders, refunds and cancellationsread_orderswrite_orders
stock levelsread_inventorywrite_inventory
customersread_customerswrite_customers
discount codesread_discountswrite_discounts
  1. Request protected customer data access for the app (its API access requests page in the Partner Dashboard, which opens the Dev Dashboard for an app made there): Level 1, plus the Email field. Shopify counts every order as protected customer data, so without it the app is refused every order and customer — with a 403, even holding read_orders — while products and stock still read. A member's bot then stops with "the supplier refused access" rather than retrying. An app that is not distributed publicly is granted this without a manual review (vendor note: docs/research/connectors/shopify.md).

The two halves are separate grants, which is the point: a member who wants their bot to watch the shop grants the read half and nothing else, and no write tool is unlocked for them at all. Collections have no scope of their own in Shopify's vocabulary — they ride the product scopes.

2. Put the credentials in

The client id and secret go in with botseon oauth-app set (the secret on standard input; see README.md). No key goes in the repository.

Shopify's OAuth endpoints are on the shop's own domain, not on a central host, so this deployment builds them from the shop each member names and does not read them from the app row. The auth_url and token_url columns still have to hold an https URL — use Shopify's own pattern for any one shop, for example a development store:

columnwhat goes in it
auth_urlhttps://<shop>.myshopify.com/admin/oauth/authorize
token_urlhttps://<shop>.myshopify.com/admin/oauth/access_token

Each member is sent to their own shop's consent screen, and their code is exchanged at that shop. Two members of one organisation can connect two different shops through the one app, as long as the app is installable on both.

NEEDS OPERATOR: the kind of app. The connector asks for Shopify's non-expiring offline token and calls the REST Admin API. Shopify allows both for a custom-distribution app (one you distribute to the shops you serve) and has withdrawn both from new public apps. Create the app for custom distribution. Until an operator has stored the app here, Authenticate sends the member back to the plugin sheet and nothing is sent to any shop.

3. The member's own setting

The plugin sheet asks each member for one value:

variablewhat it is
shopthe shop's myshopify.com domain. For https://acme.myshopify.com/admin, enter acme.myshopify.com.

Authenticate asks for it on its own small page the first time, before the member is sent anywhere, and remembers it. A pasted admin address or the bare shop name is accepted and stored as the domain.

Only a *.myshopify.com domain is accepted — a custom storefront domain does not serve the Admin API, and a value that is not that domain is refused before any request is made.

What needs approval

Every tool that changes the shop raises an approval card naming what it is about to act on, and none of them is released by default:

  • a price, title, status, stock level, customer field or collection change — a card per change;
  • a refund — a card per refund, and one that no saved "always allow" rule can ever cover, because a refund moves money to a customer;
  • a cancellation — likewise, because a cancelled order is something the customer sees and nothing here can undo it.

Reads raise no card.

Taking it back

Removing the account on the plugin sheet (or uninstalling the plugin) clears the stored token here and takes the grant back at the shop. Shopify has no narrower way to do that than removing the app from that shop, so that is what happens: every connection through this app to that shop ends with it. If the shop cannot be reached, the local token is cleared anyway and the member is told the shop may still list the app — the connection stops working either way, which is the direction that has to be true.

Checking it against a live store

The nightly connector-live run reads products, orders and stock from a development store and holds one write for approval. Setting up that store and its credential is ../operations/connector-live-setup/shopify.md.

Last verified against build 8efb618.