Skip to content

HTTP Requests

Workflow steps use the standard global fetch() — the same Web API available in browsers and Cloudflare Workers. There is no api.fetch() wrapper.

When your fetch() URL matches your store’s myshopify.com domain, the platform automatically injects the X-Shopify-Access-Token header. You do not need to manage or pass the token yourself.

Your store domain and API version are available on the global env object:

class Workflow {
async start(data, headers, api) {
// Token is injected automatically — no Authorization header needed
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: `mutation UpdateOrderNote($input: OrderInput!) {
orderUpdate(input: $input) {
order { id note }
userErrors { field message }
}
}`,
variables: { input: { id: `gid://shopify/Order/${data.id}`, note: 'Processed' } },
}),
}
);
const { data: gqlData } = await res.json();
const { order, userErrors } = gqlData.orderUpdate;
if (userErrors.length) { api.log('Errors:', userErrors); return; }
api.log('Updated note:', order.note);
}
}

The same automatic token injection applies to all GraphQL requests:

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 GetOrders {
orders(first: 10) {
nodes { id name }
}
}`,
}),
}
);
const { data } = await res.json();

Use api.getOAuthToken(handle) to get a valid access token for a connected OAuth service, then add it to your request headers manually. The platform automatically refreshes the token if it has expired.

class Workflow {
async start(data, headers, api) {
const { token, error } = await api.getOAuthToken('my-slack');
if (error) { api.log('OAuth error:', error); return; }
await fetch('https://slack.com/api/chat.postMessage', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${token}`,
},
body: JSON.stringify({ channel: '#orders', text: `New order: ${data.id}` }),
});
}
}

The handle is the name you assigned when connecting the service in OAuth Connections.

Store API keys via More actions → Manage variables in the workflow editor and access them via env.*:

const res = await fetch('https://api.example.com/notify', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${env.EXAMPLE_API_KEY}`,
},
body: JSON.stringify({ event: 'order_paid', orderId: data.id }),
});

Pass a plain JavaScript object as the body by serialising it with JSON.stringify. Always set Content-Type: application/json when doing this:

const res = await fetch('https://api.example.com/endpoint', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ key: 'value' }),
});