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 createThe 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.tsStep 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.