Skip to Content
BridgesExamplesShopify

Shopify Bridge Example

The Shopify bridge is an e-commerce category bridge that demonstrates OAuth authentication, webhook handling, and order syncing.

Manifest

const manifest: BridgeManifest = { name: 'shopify', displayName: 'Shopify', description: 'Sync orders and push fulfillments to Shopify stores', version: '1.0.0', category: 'ecommerce', integrationType: 'npm', icon: 'shopify', authMethods: { apiKey: false, accessToken: true, oauth2: true }, configFields: [ { name: 'shopDomain', label: 'Store Domain', type: 'text', required: true, placeholder: 'mystore.myshopify.com' }, { name: 'accessToken', label: 'Access Token', type: 'password', required: true }, { name: 'webhookSecret', label: 'Webhook Secret', type: 'password', required: false }, ], tasks: [ { name: 'grab-orders', displayName: 'Grab Orders', description: 'Fetch orders from Shopify', category: 'sync', supportsSchedule: true }, { name: 'get-order', displayName: 'Get Order', description: 'Fetch a single order', category: 'sync', supportsSchedule: false }, { name: 'push-fulfillment', displayName: 'Push Fulfillment', description: 'Send fulfillment to Shopify', category: 'push', supportsSchedule: false }, ], webhooks: [ { event: 'orders/create', description: 'New order placed', auth: { type: 'hmac', header: 'x-shopify-hmac-sha256', algorithm: 'sha256', secretField: 'webhookSecret' } }, { event: 'orders/updated', description: 'Order modified', auth: { type: 'hmac', header: 'x-shopify-hmac-sha256', algorithm: 'sha256', secretField: 'webhookSecret' } }, { event: 'orders/fulfilled', description: 'Order fulfilled', auth: { type: 'hmac', header: 'x-shopify-hmac-sha256', algorithm: 'sha256', secretField: 'webhookSecret' } }, ], };

Grab Orders Task

Uses the Shopify Admin API to fetch orders with incremental cursor-based pagination:

async function grabOrders(context: BridgeTaskContext, input: Record<string, unknown>) { const { config, storage, logger } = context; const shopify = createShopifyClient(config.credentials); const since = await storage.get<string>('orders:since') || input.since; const orders = await shopify.order.list({ created_at_min: since, limit: 250, status: 'any', }); // Transform Shopify orders to unified format const unified = orders.map(transformShopifyOrder); // Save cursor for next sync if (orders.length > 0) { const latest = orders[orders.length - 1].created_at; await storage.set('orders:since', latest); } return { success: true, data: unified, metrics: { recordsProcessed: orders.length, recordsCreated: unified.length }, pagination: { hasMore: orders.length === 250 }, }; }

Push Fulfillment Task

Sends tracking info back to Shopify:

async function pushFulfillment(context: BridgeTaskContext, input: Record<string, unknown>) { const shopify = createShopifyClient(context.config.credentials); const fulfillment = await shopify.fulfillment.create(input.orderId, { tracking_number: input.trackingNumber, tracking_company: input.carrier, line_items: input.lineItems, }); return { success: true, data: { fulfillmentId: fulfillment.id }, metrics: { recordsCreated: 1 }, }; }

Webhook Handler

Processes real-time order events:

async handleWebhook(event: string, payload: Record<string, unknown>, context: BridgeTaskContext) { const order = transformShopifyOrder(payload); return { success: true, data: { action: event === 'orders/create' ? 'create' : 'update', order, }, }; }