Node.js SDK
The official TypeScript SDK wraps every Unified API workflow with typed responses, automatic retries, and cursor pagination.
The official TypeScript SDK wraps every Unified API workflow — discovery, account
connection, reads, writes, contracts, and observability — with typed responses, automatic
retries on 429/5xx, and cursor pagination handled for you.
1. Install and create a client
npm install @uniflow/sdkimport { UniflowClient } from '@uniflow/sdk';
const client = new UniflowClient({
apiKey: process.env.UNIFLOW_API_KEY, // sent as x-api-key
environment: 'prod', // 'prod' (default) | 'dev' (staging)
organisationId: process.env.UNIFLOW_ORG_ID, // optional tenant context
timeoutMs: 30_000, // per-request timeout (default 30s)
maxRetries: 2, // automatic retries on 429/5xx
});
// Cheapest way to verify connectivity and environment selection
const health = await client.health();
console.log(health.status); // "healthy"environment: 'dev' targets staging; 'prod' is the default. The API key is sent as
x-api-key, and organisationId becomes a tenant-context header on every request.
2. Discover integrations and their documentation
// List the integration catalogue
const { data: integrations } = await client.integrations.list({ status: 'active' });
// Everything known about one integration — entities, read/write
// capability, filters — in a single call
const docs = await client.docs.describeIntegration(systemId);
for (const entity of docs.entities) {
console.log(entity.entityType, entity.readable, entity.writable);
}
// Just the filters for one entity
const filters = await client.docs.getEntityFilters(systemId, 'order');3. Connect an account
// One connect per merchant per integration
const connection = await client.auth.connectAccount(systemId, 'shopify', {
merchantId: 'merchant-42',
shop: 'demo-store.myshopify.com',
returnUrl: 'https://app.example.com/integrations/done',
});
if (connection.data.authType === 'oauth') {
// OAuth integrations return an authUrl — redirect the user there,
// then poll the connection status
redirect(connection.data.authUrl);
const status = await client.auth.getStatus(accountId);
} else {
// Direct-auth integrations (apikey / basic / bearer) connect immediately
const accountId = connection.data.accountId;
}4. Read unified records
// One page, with filters and page size
const page = await client.records.list(accountId, 'orders', {
pageSize: 50,
filters: { status: 'paid' }, // keys from docs.getEntityFilters(...)
});
console.log(page.data, page.pagination.hasMore);
// Everything — cursor pagination handled for you
for await (const order of client.records.iterate(accountId, 'orders')) {
process(order);
}
// Typed records
interface UnifiedOrder { id: string; status: string; total: number }
const typed = await client.records.list<UnifiedOrder>(accountId, 'orders');5. Write unified records
// Write once in the unified schema — the platform validates against
// the entity contract, transforms to the integration's native shape,
// and pushes
const result = await client.records.create(accountId, 'products', {
name: 'Espresso Beans 1kg',
sku: 'ESP-1KG',
price: 18.5,
});
console.log(result.success, result.data);6. Handle errors
import {
UniflowError, NotFoundError, RateLimitError, ValidationError,
} from '@uniflow/sdk';
// Retries for 429/5xx happen automatically first;
// you only catch what survived them.
try {
await client.records.list(accountId, 'orders');
} catch (err) {
if (err instanceof NotFoundError) {
// unknown account / entity — err.status === 404
} else if (err instanceof ValidationError) {
// payload failed the unified schema — details in err.body
} else if (err instanceof RateLimitError) {
await sleep(err.retryAfterSeconds * 1000);
} else if (err instanceof UniflowError) {
log(err.status, err.message, err.requestId);
} else {
throw err; // programming error — do not swallow
}
}Every failure is a typed subclass of UniflowError with status, message, and
requestId for support escalation.
7. Beyond the basics — contracts, AI generation, observability
// Unified entity contracts — the Zod schema + per-integration mappings
const contracts = await client.entities.list({ onlyEnabled: true });
// Generate contracts with AI — async, poll until done
const { data: task } = await client.entities.generate({ systemIds: [systemId] });
const finished = await client.entities.waitForGeneration(task._id);
// Observability — request logs and rate-limit configs
const logs = await client.requests.list({ accountId, limit: 5 });
const limits = await client.rateLimits.list();