Skip to content

You can connect a Shopify custom app to workflows, not just the store where JsWorkflows is installed. This lets a workflow call another Shopify store, use a separate Shopify app token, or access Shopify API surfaces that are outside the standard JsWorkflows app connection.

For the store where JsWorkflows is installed, you usually do not need this. Use the built-in Shopify Admin API access instead — JsWorkflows automatically injects the installed store’s access token when your workflow calls that store’s Admin API URL.

Use a separate Shopify connection when you need one of these patterns:

  • Multi-store workflows: read from one Shopify store and update another
  • Wholesale or regional stores: sync products, inventory, customer tags, or order data between related stores
  • Migration and backfill jobs: pull data from a source store and write cleaned data into another store
  • Separate Shopify scopes: use scopes that are not part of the main JsWorkflows app installation
  • Agency or developer workflows: manage controlled access to a client’s secondary store
  1. Go to dev.shopify.com/dashboard and log in
  2. Click Create app, then Start from Dev Dashboard
  3. Enter an app name and click Create. This opens the Create version screen

On the Create version screen:

  1. App URL: Enter any URL, or leave the default https://example.com

  2. Scopes: Click Select scopes and choose the Admin API scopes your workflow needs

  3. Redirect URLs: Add the following URL exactly as shown:

    https://oauth.jsworkflows.com/oauth2/callback
  4. Click Release to publish the version

In the left sidebar, click Settings. Under Credentials you will find the Client ID and Secret. Keep the Secret — you will need it when adding the connection.


If the target store is a development store, you can use the standard Custom (OAuth 2.0) connector.

Go to Settings → OAuth2 Tokens, click Connect to Service, and choose Custom (OAuth 2.0).

Fill in the fields:

FieldValue
Client IDFrom Dev Dashboard → Settings → Credentials
Client SecretFrom Dev Dashboard → Settings → Credentials
Authorization URLhttps://your-store.myshopify.com/admin/oauth/authorize
Token URLhttps://your-store.myshopify.com/admin/oauth/access_token
ScopesComma-separated list of your configured scopes. Copy from Versions → [latest version] → Scopes in the Dev Dashboard
OAuth NameA friendly label (e.g. Dev Store)
HandleA short identifier used in workflow code (e.g. dev-store)

Click Generate and Authorize. A popup opens Shopify’s authorization screen. Approve the request — the token is stored and the connection appears in your list.


Live stores require the app to use Custom distribution. This adds an extra step before authorizing.

From the app overview page in the Dev Dashboard:

  1. Click Select distribution method

  2. Select Custom distribution

  3. Enter the live store’s domain. Shopify accepts either format:

    shop1.myshopify.com
    admin.shopify.com/store/shop1

Shopify generates an installation link for the store. Copy that link — you need it in the next steps.

Open the installation link in a browser tab. You will need to be logged in to the target Shopify store. Shopify will install the app on that store.

This step happens outside JsWorkflows and only needs to be done once per store. After the app is installed, you can connect it.

Go to Settings → OAuth2 Tokens, click Connect to Service, and choose Shopify Custom App.

Fill in the fields:

FieldValue
Installation LinkThe full installation link from the Dev Dashboard distribution settings
Client SecretFrom Dev Dashboard → Settings → Credentials
ScopesComma-separated list of your configured scopes. Copy from Versions → [latest version] → Scopes in the Dev Dashboard
OAuth NameA friendly label (e.g. Secondary Store)
HandleA short identifier used in workflow code (e.g. secondary-store)

The Client ID, Authorization URL, and Token URL are extracted and derived automatically from the installation link. You do not need to enter them manually.

Click Generate and Authorize. A popup opens Shopify’s authorization screen for the target store. Approve the request — the token is stored and the connection appears in your list.


export class Workflow {
async start(_data, _headers, api) {
const { token, error } = await api.getOAuthToken('secondary-store');
if (error || !token) throw new Error(error || 'Missing Shopify token');
const res = await fetch(
'https://your-store.myshopify.com/admin/api/2026-04/graphql.json',
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Shopify-Access-Token': token,
},
body: JSON.stringify({
query: `{
products(first: 5) {
edges {
node {
id
title
status
totalInventory
}
}
}
}`,
}),
}
);
if (!res.ok) throw new Error(`Shopify API ${res.status}: ${await res.text()}`);
const { data } = await res.json();
const products = data.products.edges.map(e => e.node);
console.log(`Fetched ${products.length} products`);
}
}

Replace your-store with the store’s myshopify.com subdomain and secondary-store with the handle you chose.

Select the scopes you need from the Select scopes UI in the Dev Dashboard when creating your app version.

ScopeWhat it allows
read_productsRead products and variants
write_productsCreate and update products and variants
read_ordersRead orders (last 60 days)
read_all_ordersRead all orders regardless of age
write_ordersUpdate orders
read_inventoryRead inventory levels and locations
write_inventoryUpdate inventory levels
read_customersRead customer data
write_customersCreate and update customers
read_themesRead theme files
write_themesCreate and update theme files

For a full list, see the Shopify API access scopes reference.