Skip to Content
BridgesCreating

Creating a Bridge

This guide walks you through creating a new bridge integration using the Orderly CLI.

Prerequisites

  • Node.js 18+ and pnpm installed
  • The hub monorepo cloned locally
  • Access to the platform you’re integrating with

Step 1: Scaffold the Bridge

From the hub/ directory, run:

pnpm orderly bridge create

The CLI will prompt you for:

  • Bridge name (kebab-case, e.g., my-platform)
  • Category (ecommerce, shipping, marketplace, or erp)
  • Display name (human-readable, e.g., “My Platform”)
  • Description
  • Auth methods (API key, OAuth2, access token)

This creates a new package at hub/packages/bridges/<name>/ with the following structure:

packages/bridges/my-platform/ ├── package.json ├── tsconfig.json ├── src/ │ ├── index.ts # BridgeImplementation export │ ├── manifest.ts # BridgeManifest declaration │ ├── tasks/ │ │ ├── grab-orders.ts │ │ ├── get-order.ts │ │ └── push-fulfillment.ts │ └── lib/ │ └── client.ts # Platform API client └── tests/ └── index.test.ts

Step 2: Define the Manifest

Edit src/manifest.ts to declare your bridge’s metadata:

import type { BridgeManifest } from '@orderly/shared'; export const manifest: BridgeManifest = { name: 'my-platform', displayName: 'My Platform', description: 'Sync orders from My Platform', version: '1.0.0', category: 'ecommerce', integrationType: 'api', icon: 'shopping-cart', authMethods: { apiKey: true, accessToken: false, oauth2: false, }, configFields: [ { name: 'apiKey', label: 'API Key', type: 'password', required: true, placeholder: 'Enter your API key', helpText: 'Find this in your platform dashboard under Settings > API', }, { name: 'storeUrl', label: 'Store URL', type: 'url', required: true, placeholder: 'https://mystore.example.com', }, ], tasks: [ { name: 'grab-orders', displayName: 'Grab Orders', description: 'Fetch orders from the platform', category: 'sync', supportsSchedule: true, }, // ... other tasks ], };

Step 3: Implement Tasks

Each task is a function that receives a BridgeTaskContext and input, and returns a BridgeTaskResult:

// src/tasks/grab-orders.ts import type { BridgeTaskContext, BridgeTaskResult } from '@orderly/shared'; export async function grabOrders( context: BridgeTaskContext, input: Record<string, unknown> ): Promise<BridgeTaskResult> { const { config, logger, storage } = context; const apiKey = config.credentials.apiKey; // Get the last sync cursor const lastCursor = await storage.get<string>('orders:cursor'); logger.info('Fetching orders', { since: lastCursor }); // Call the platform API const response = await fetch(`${config.credentials.storeUrl}/api/orders`, { headers: { 'Authorization': `Bearer ${apiKey}` }, }); const data = await response.json(); // Save cursor for next sync if (data.nextCursor) { await storage.set('orders:cursor', data.nextCursor); } return { success: true, data: data.orders, metrics: { recordsProcessed: data.orders.length, recordsCreated: data.orders.length, }, pagination: { hasMore: !!data.nextCursor, cursor: data.nextCursor, }, }; }

Step 4: Wire Up the Implementation

In src/index.ts, implement the BridgeImplementation interface:

import type { BridgeImplementation, BridgeRuntimeConfig, BridgeTaskContext, BridgeTaskResult } from '@orderly/shared'; import { manifest } from './manifest'; import { grabOrders } from './tasks/grab-orders'; export const bridge: BridgeImplementation = { manifest, async initialize(config: BridgeRuntimeConfig) { // Set up API client, validate tokens, etc. }, async validateConfig(config: BridgeRuntimeConfig) { try { const res = await fetch(`${config.credentials.storeUrl}/api/ping`, { headers: { 'Authorization': `Bearer ${config.credentials.apiKey}` }, }); return { valid: res.ok }; } catch { return { valid: false, error: 'Failed to connect to platform' }; } }, async executeTask(taskName: string, context: BridgeTaskContext, input: Record<string, unknown>): Promise<BridgeTaskResult> { switch (taskName) { case 'grab-orders': return grabOrders(context, input); default: return { success: false, error: { code: 'UNKNOWN_TASK', message: `Unknown: ${taskName}` } }; } }, };

Step 5: Deploy

See Deploying a Bridge for how to register your bridge with the platform.