Scheduled Trigger
The Scheduled trigger runs your workflow at a fixed interval or at a specific point in time — no external event needed.
Schedule types
Section titled “Schedule types”Repeat
Section titled “Repeat”Runs the workflow repeatedly at a fixed interval. Configure in the workflow editor:
| Setting | Options |
|---|---|
| Frequency | Every N minutes, hours, days, or months |
| Start | The date and time of the first run (UTC) |
| End | Never, on a specific date, or after N runs |
Minimum interval: 10 minutes.
Runs the workflow once at a specific date and time, then stops.
The data object
Section titled “The data object”For scheduled triggers, data contains run context:
{ counter: 1, // How many times this workflow has run (1-indexed) next_schedule_time: 3600000 // Milliseconds until the next scheduled run (0 if no next run)}counter starts at 1 on the first run and increments on each subsequent run. Use it to differentiate early runs from later ones or to branch logic based on how many times the workflow has executed.
Your store domain and API version are always available via env.SHOPIFY_STORE and env.SHOPIFY_API_VERSION.
Example — daily order count to Slack
Section titled “Example — daily order count to Slack”A workflow that runs every day and posts how many orders were placed in the last 24 hours. start fetches the count from Shopify and passes it to notifySlack, which sends the message:
class Workflow { async start(data, headers, api) { api.log(`Daily summary — run #${data.counter}`);
// Fetch order count for the last 24 hours const since = new Date(Date.now() - 24 * 60 * 60 * 1000).toISOString(); const resp = 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 OrdersCount($query: String!) { ordersCount(query: $query) { count precision } }`, variables: { query: `created_at:>${since}` }, }), } ); const { data: gqlData } = await resp.json(); const { count, precision } = gqlData.ordersCount; const countLabel = precision === 'EXACT' ? `${count}` : `${count}+`;
await api.scheduleNextStep({ delay: 10, action: 'notifySlack', payload: { counter: data.counter, countLabel }, }); }
async notifySlack({ counter, countLabel }, headers, api) { const { token } = await api.getOAuthToken('my-slack'); await fetch('https://slack.com/api/chat.postMessage', { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${token}`, }, body: JSON.stringify({ channel: '#orders', text: `Daily summary (run #${counter}): ${countLabel} orders in the last 24 hours.`, }), }); }}Set this workflow to run on a Repeat schedule of every 1 day.
For longer workloads (e.g. processing many products), use api.scheduleNextStep() to spread work across steps rather than doing everything in start. See Steps & Workflow Design for patterns.