Skip to content

Every executable step method, including start and any named continuation step you schedule later, receives three arguments:

async start(data, headers, api) { ... }
ArgumentDescription
dataThe trigger payload or step payload (order object, HTTP body, scheduled context, or the payload from api.scheduleNextStep())
headersTrigger/request headers when the step was entered from an HTTP-style source. For scheduled runs and most continuation steps, treat this as optional context and do not rely on it unless the trigger docs say it is present.
apiThe JsWorkflows API object, which exposes platform capabilities
MethodDescription
api.scheduleNextStep()Schedule the next step (or fan-out to multiple steps)
api.waitForEvent()Pause a run and resume it when an external event arrives
api.dedupe()Prevent duplicate processing within a time window for your own business logic or external-event idempotency
api.getOAuthToken()Get a valid access token for a connected OAuth service
api.google.getServiceAccountToken()Get a Google access token using a service account key (cached 58 min)
api.google.sheet.*Google Sheets helpers such as appendRows, readRows, updateRows, and clearRange
api.csv.*Import a CSV from a URL, split it into chunks, and process each chunk in a separate step
api.runStore.*Store and retrieve values scoped to the current run
console.log()Write debug output visible in the test runner and run history
api.getAttachment()Retrieve an email attachment as an ArrayBuffer (email-trigger workflows only)
api.deleteAttachment()Delete an email attachment from storage (email-trigger workflows only)
api.sendToFlow()Fire a JsWorkflow Data Received trigger in Shopify Flow from any step
api.sendEmail()Send a notification email to your configured notification address (paid plans)

All secret variables you store via More actions → Manage variables in the workflow editor are available as properties on the global env object:

export class Workflow {
async start(data, headers, api) {
const apiKey = env.MY_API_KEY; // a secret you stored
const shop = env.SHOPIFY_STORE; // auto-injected: "mystore.myshopify.com"
const ver = env.SHOPIFY_API_VERSION; // auto-injected: e.g. "2026-04"
}
}

Two values are always present regardless of your stored secrets:

KeyValue
env.SHOPIFY_STOREYour store’s myshopify.com domain
env.SHOPIFY_API_VERSIONThe Shopify API version configured for your app

For Shopify webhook triggers, duplicate delivery protection already happens before your workflow code runs. api.dedupe() is still useful when you need your own workflow-specific or business-level deduplication rules.

Use the global fetch() to call any URL. For Shopify Admin API requests, the platform automatically injects the X-Shopify-Access-Token header when the URL matches your store domain, so no extra configuration is needed:

// Shopify GraphQL, token injected automatically
const res = await fetch(
`https://${env.SHOPIFY_STORE}/admin/api/${env.SHOPIFY_API_VERSION}/graphql.json`,
{
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ query: `query { orders(first: 10) { nodes { id name } } }` }),
}
);
const { data } = await res.json();

For OAuth-connected services, retrieve the token with api.getOAuthToken() and add it yourself:

const { token } = await api.getOAuthToken('my-slack');
const res = await fetch('https://slack.com/api/chat.postMessage', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${token}`,
},
body: JSON.stringify({ channel: '#orders', text: 'Hello' }),
});

Your Workflow class can optionally define two lifecycle hooks that run once when the entire run reaches a terminal state. These hooks do not use the normal (data, headers, api) step signature:

export class Workflow {
async start(data, headers, api) { ... }
// Called when the entire run (all branches) completes successfully
async onWorkflowComplete(api) { ... }
// Called when a step throws an uncaught error that terminates the run
async onWorkflowError(err, api) { ... }
}

Inside hooks, api is restricted to: getOAuthToken, google, log, dedupe, runStore, and sendEmail. The methods scheduleNextStep, waitForEvent, and csv are not available. The global fetch() API is still available inside hooks.

See Lifecycle Hooks for full behavioral rules and examples.