Flow Unified API

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/sdk
import { 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();

On this page