JavaScript/TypeScript SDK

The official JavaScript and TypeScript SDK for Unified Commerce Platform. Built with modern TypeScript, featuring full type safety, React hooks, and comprehensive error handling.

Version: 2.1.0 | License: MIT | Bundle Size: ~45KB (minified + gzipped)

Installation

Install the SDK using your preferred package manager:

# npm
npm install @unified-commerce/sdk

# yarn
yarn add @unified-commerce/sdk

# pnpm
pnpm add @unified-commerce/sdk

# bun
bun add @unified-commerce/sdk

TypeScript Configuration

For the best TypeScript experience, ensure your tsconfig.json includes:

{
  "compilerOptions": {
    "target": "ES2020",
    "lib": ["ES2020"],
    "module": "ESNext",
    "moduleResolution": "bundler",
    "esModuleInterop": true,
    "strict": true,
    "skipLibCheck": true
  }
}

Quick Start

Basic Setup

import { UnifiedCommerce } from '@unified-commerce/sdk';

const client = new UnifiedCommerce({
  apiKey: process.env.UNIFIED_COMMERCE_API_KEY,
  environment: 'production', // or 'sandbox' for testing
});

// Query products
const products = await client.products.list({
  limit: 10,
  category: 'electronics'
});

console.log(products);

React Setup

The SDK includes built-in React hooks for seamless integration:

import { UnifiedCommerceProvider, useProducts } from '@unified-commerce/sdk/react';

// Wrap your app with the provider
function App() {
  return (
    <UnifiedCommerceProvider
      apiKey={process.env.NEXT_PUBLIC_UNIFIED_COMMERCE_API_KEY}
      environment="production"
    >
      <ProductList />
    </UnifiedCommerceProvider>
  );
}

// Use hooks in your components
function ProductList() {
  const { data: products, loading, error } = useProducts({
    limit: 20,
    category: 'electronics'
  });

  if (loading) return <div>Loading...</div>;
  if (error) return <div>Error: {error.message}</div>;

  return (
    <div>
      {products.map(product => (
        <ProductCard key={product.id} product={product} />
      ))}
    </div>
  );
}

Configuration

Client Options

interface UnifiedCommerceConfig {
  // Required: Your API key
  apiKey: string;

  // Environment: 'production' | 'sandbox'
  environment?: string;

  // Custom API endpoint (optional)
  apiUrl?: string;

  // Request timeout in milliseconds (default: 30000)
  timeout?: number;

  // Maximum retry attempts (default: 3)
  maxRetries?: number;

  // Enable debug logging (default: false)
  debug?: boolean;

  // Custom headers to include in all requests
  headers?: Record<string, string>;

  // HTTP agent for Node.js environments
  httpAgent?: any;
}

const client = new UnifiedCommerce({
  apiKey: process.env.UNIFIED_COMMERCE_API_KEY,
  environment: 'production',
  timeout: 60000,
  maxRetries: 5,
  debug: process.env.NODE_ENV === 'development',
  headers: {
    'X-Custom-Header': 'value'
  }
});

Environment Variables

Store your configuration in environment variables:

# .env.local
UNIFIED_COMMERCE_API_KEY=uc_live_xxxxxxxxxxxxx
NEXT_PUBLIC_UNIFIED_COMMERCE_API_KEY=uc_live_xxxxxxxxxxxxx # For client-side Next.js

Authentication

API Key Authentication

The SDK uses API key authentication. All requests include the API key in the Authorization header:

const client = new UnifiedCommerce({
  apiKey: 'uc_live_xxxxxxxxxxxxx'
});

// The SDK automatically includes:
// Authorization: Bearer uc_live_xxxxxxxxxxxxx

Per-Request Authentication

Override the API key for specific requests:

const products = await client.products.list(
  { limit: 10 },
  { apiKey: 'different_api_key' }
);

Token Refresh (Coming Soon)

OAuth token refresh will be supported in version 2.2:

const client = new UnifiedCommerce({
  oauth: {
    clientId: 'your_client_id',
    clientSecret: 'your_client_secret',
    refreshToken: 'refresh_token'
  }
});

Core Concepts

Products

// List products with filters
const products = await client.products.list({
  category: 'electronics',
  minPrice: 100,
  maxPrice: 1000,
  inStock: true,
  limit: 20,
  offset: 0,
  sortBy: 'price',
  sortOrder: 'asc'
});

// Get a single product
const product = await client.products.get('product-123');

// Create a product
const newProduct = await client.products.create({
  name: 'Wireless Headphones',
  description: 'Premium noise-cancelling headphones',
  price: 299.99,
  category: 'electronics',
  sku: 'WH-1000XM5',
  inventory: {
    quantity: 100,
    trackInventory: true
  }
});

// Update a product
const updated = await client.products.update('product-123', {
  price: 279.99,
  inventory: {
    quantity: 150
  }
});

// Delete a product
await client.products.delete('product-123');

Orders

// Create an order
const order = await client.orders.create({
  items: [
    {
      productId: 'product-123',
      quantity: 2,
      price: 299.99
    },
    {
      productId: 'product-456',
      quantity: 1,
      price: 149.99
    }
  ],
  customer: {
    id: 'customer-789',
    email: 'customer@example.com',
    name: 'John Doe'
  },
  shippingAddress: {
    street: '123 Main St',
    city: 'San Francisco',
    state: 'CA',
    postalCode: '94105',
    country: 'US'
  },
  billingAddress: {
    // Same as shipping or different
  },
  paymentMethod: {
    type: 'card',
    token: 'pm_xxxxxxxxxxxxx'
  }
});

// List orders
const orders = await client.orders.list({
  customerId: 'customer-789',
  status: 'pending',
  limit: 20
});

// Get order details
const orderDetails = await client.orders.get('order-123');

// Update order status
await client.orders.update('order-123', {
  status: 'shipped',
  tracking: {
    carrier: 'UPS',
    trackingNumber: '1Z999AA10123456784'
  }
});

// Cancel an order
await client.orders.cancel('order-123', {
  reason: 'Customer requested cancellation'
});

Customers

// Create a customer
const customer = await client.customers.create({
  email: 'customer@example.com',
  name: 'John Doe',
  phone: '+1234567890',
  addresses: [{
    type: 'shipping',
    street: '123 Main St',
    city: 'San Francisco',
    state: 'CA',
    postalCode: '94105',
    country: 'US'
  }]
});

// List customers
const customers = await client.customers.list({
  search: 'john',
  limit: 20
});

// Update customer
await client.customers.update('customer-123', {
  phone: '+9876543210'
});

Inventory

// Get inventory for a product
const inventory = await client.inventory.get('product-123');

// Update inventory
await client.inventory.update('product-123', {
  quantity: 100,
  location: 'warehouse-1',
  reservedQuantity: 5
});

// Bulk update
await client.inventory.bulkUpdate([
  { productId: 'product-123', quantity: 100 },
  { productId: 'product-456', quantity: 50 }
]);

// Track inventory movements
const movements = await client.inventory.movements('product-123', {
  startDate: '2024-01-01',
  endDate: '2024-01-31'
});

React Hooks

useProducts

import { useProducts } from '@unified-commerce/sdk/react';

function ProductList() {
  const {
    data: products,
    loading,
    error,
    refetch,
    hasMore,
    loadMore
  } = useProducts({
    category: 'electronics',
    limit: 20
  });

  if (loading) return <Spinner />;
  if (error) return <Error message={error.message} />;

  return (
    <>
      <ProductGrid products={products} />
      {hasMore && (
        <button onClick={loadMore}>Load More</button>
      )}
    </>
  );
}

useOrder

import { useOrder } from '@unified-commerce/sdk/react';

function OrderDetails({ orderId }: { orderId: string }) {
  const { data: order, loading, error, update } = useOrder(orderId);

  const handleUpdateStatus = async () => {
    await update({
      status: 'shipped',
      tracking: { carrier: 'UPS', trackingNumber: '123456' }
    });
  };

  if (loading) return <Spinner />;
  if (error) return <Error message={error.message} />;

  return (
    <div>
      <h1>Order {order.id}</h1>
      <button onClick={handleUpdateStatus}>Mark as Shipped</button>
    </div>
  );
}

useCreateOrder

import { useCreateOrder } from '@unified-commerce/sdk/react';

function Checkout({ cart }) {
  const { createOrder, loading, error } = useCreateOrder();

  const handleCheckout = async () => {
    try {
      const order = await createOrder({
        items: cart.items,
        customer: { /* ... */ },
        shippingAddress: { /* ... */ }
      });

      // Redirect to success page
      router.push(`/orders/${order.id}/success`);
    } catch (err) {
      console.error('Checkout failed:', err);
    }
  };

  return (
    <button onClick={handleCheckout} disabled={loading}>
      {loading ? 'Processing...' : 'Place Order'}
    </button>
  );
}

useInventory

import { useInventory } from '@unified-commerce/sdk/react';

function InventoryStatus({ productId }: { productId: string }) {
  const {
    data: inventory,
    loading,
    update,
    subscribe // Real-time updates
  } = useInventory(productId);

  useEffect(() => {
    const unsubscribe = subscribe((updated) => {
      console.log('Inventory updated:', updated);
    });
    return unsubscribe;
  }, [subscribe]);

  const handleUpdateQuantity = async (quantity: number) => {
    await update({ quantity });
  };

  if (loading) return <Spinner />;

  return (
    <div>
      <p>Available: {inventory.quantity}</p>
      <button onClick={() => handleUpdateQuantity(inventory.quantity + 10)}>
        Add 10
      </button>
    </div>
  );
}

Error Handling

Error Types

The SDK provides typed errors for better error handling:

import {
  UnifiedCommerceError,
  AuthenticationError,
  ValidationError,
  NotFoundError,
  RateLimitError,
  NetworkError
} from '@unified-commerce/sdk';

try {
  const product = await client.products.get('invalid-id');
} catch (error) {
  if (error instanceof NotFoundError) {
    console.error('Product not found:', error.message);
  } else if (error instanceof AuthenticationError) {
    console.error('Invalid API key:', error.message);
  } else if (error instanceof RateLimitError) {
    console.error('Rate limit exceeded. Retry after:', error.retryAfter);
  } else if (error instanceof ValidationError) {
    console.error('Validation errors:', error.errors);
  } else {
    console.error('Unexpected error:', error);
  }
}

Automatic Retries

The SDK automatically retries failed requests with exponential backoff:

const client = new UnifiedCommerce({
  apiKey: 'your-api-key',
  maxRetries: 5, // Retry up to 5 times
  retryDelay: 1000, // Initial delay of 1 second
  retryMultiplier: 2 // Double the delay each retry
});

// The SDK will automatically retry on:
// - Network errors
// - 5xx server errors
// - Rate limit errors (with retry-after header)

Custom Error Handling

const client = new UnifiedCommerce({
  apiKey: 'your-api-key',
  onError: (error) => {
    // Custom error logging
    console.error('SDK Error:', error);
    // Send to error tracking service
    Sentry.captureException(error);
  }
});

Webhooks

Webhook Verification

import { verifyWebhook } from '@unified-commerce/sdk';

// Express.js example
app.post('/webhooks/unified-commerce', async (req, res) => {
  const signature = req.headers['x-unified-commerce-signature'];
  const payload = req.body;

  try {
    const event = verifyWebhook(
      payload,
      signature,
      process.env.WEBHOOK_SECRET
    );

    // Handle the verified event
    switch (event.type) {
      case 'order.created':
        await handleOrderCreated(event.data);
        break;
      case 'order.updated':
        await handleOrderUpdated(event.data);
        break;
      case 'inventory.low':
        await handleLowInventory(event.data);
        break;
    }

    res.json({ received: true });
  } catch (error) {
    console.error('Webhook verification failed:', error);
    res.status(400).json({ error: 'Invalid signature' });
  }
});

Webhook Types

type WebhookEvent =
  | { type: 'order.created'; data: Order }
  | { type: 'order.updated'; data: Order }
  | { type: 'order.cancelled'; data: Order }
  | { type: 'payment.succeeded'; data: Payment }
  | { type: 'payment.failed'; data: Payment }
  | { type: 'inventory.low'; data: InventoryAlert }
  | { type: 'customer.created'; data: Customer }
  | { type: 'customer.updated'; data: Customer };

Advanced Features

GraphQL Support

Use GraphQL queries for more flexibility:

import { gql } from '@unified-commerce/sdk';

const CUSTOM_QUERY = gql`
  query GetProductsWithReviews($category: String!) {
    products(category: $category) {
      id
      name
      price
      reviews {
        id
        rating
        comment
        author {
          name
        }
      }
    }
  }
`;

const result = await client.query({
  query: CUSTOM_QUERY,
  variables: { category: 'electronics' }
});

Batch Operations

// Batch create products
const products = await client.products.batchCreate([
  { name: 'Product 1', price: 99.99 },
  { name: 'Product 2', price: 149.99 },
  { name: 'Product 3', price: 199.99 }
]);

// Batch update
await client.products.batchUpdate([
  { id: 'product-1', price: 89.99 },
  { id: 'product-2', price: 139.99 }
]);

Pagination

// Cursor-based pagination
let cursor: string | undefined;
const allProducts: Product[] = [];

do {
  const result = await client.products.list({
    limit: 100,
    cursor
  });

  allProducts.push(...result.data);
  cursor = result.nextCursor;
} while (cursor);

// Or use async iterator
for await (const product of client.products.iterate({ category: 'electronics' })) {
  console.log(product);
}

File Uploads

// Upload product image
const image = await client.products.uploadImage('product-123', {
  file: imageFile, // File or Blob
  alt: 'Product image',
  position: 0
});

// Multiple images
await client.products.uploadImages('product-123', [
  { file: image1, alt: 'Front view' },
  { file: image2, alt: 'Side view' },
  { file: image3, alt: 'Back view' }
]);

Performance Optimization

Caching

import { UnifiedCommerce, CacheStrategy } from '@unified-commerce/sdk';

const client = new UnifiedCommerce({
  apiKey: 'your-api-key',
  cache: {
    strategy: CacheStrategy.StaleWhileRevalidate,
    ttl: 300, // 5 minutes
    maxSize: 100 // Max 100 cached items
  }
});

// This will be cached
const products = await client.products.list({ category: 'electronics' });

// This will use cached data and revalidate in background
const cachedProducts = await client.products.list({ category: 'electronics' });

Request Deduplication

// Multiple simultaneous requests for the same resource
// are automatically deduplicated
const [product1, product2, product3] = await Promise.all([
  client.products.get('product-123'),
  client.products.get('product-123'),
  client.products.get('product-123')
]);
// Only one actual HTTP request is made

Lazy Loading

import { lazyLoadClient } from '@unified-commerce/sdk';

// Client is only initialized when first used
const getClient = lazyLoadClient({
  apiKey: process.env.UNIFIED_COMMERCE_API_KEY
});

// Later in your code
const client = getClient();
const products = await client.products.list();

TypeScript Types

Generated Types

All API types are automatically generated from the GraphQL schema:

import type {
  Product,
  Order,
  Customer,
  Inventory,
  OrderStatus,
  PaymentMethod
} from '@unified-commerce/sdk/types';

function processOrder(order: Order): void {
  console.log(order.id);
  console.log(order.status); // Type: OrderStatus
  console.log(order.items); // Type: OrderItem[]
}

Custom Type Guards

import { isProduct, isOrder, isCustomer } from '@unified-commerce/sdk';

function handleEntity(entity: unknown) {
  if (isProduct(entity)) {
    console.log('Product:', entity.name);
  } else if (isOrder(entity)) {
    console.log('Order:', entity.id);
  } else if (isCustomer(entity)) {
    console.log('Customer:', entity.email);
  }
}

Testing

Mock Client

import { createMockClient } from '@unified-commerce/sdk/testing';

const mockClient = createMockClient({
  products: {
    list: jest.fn().mockResolvedValue({
      data: [
        { id: '1', name: 'Test Product', price: 99.99 }
      ],
      total: 1
    })
  }
});

// Use in tests
test('fetches products', async () => {
  const products = await mockClient.products.list();
  expect(products.data).toHaveLength(1);
});

Test Utilities

import {
  mockProduct,
  mockOrder,
  mockCustomer
} from '@unified-commerce/sdk/testing';

const testProduct = mockProduct({
  name: 'Test Product',
  price: 99.99
});

const testOrder = mockOrder({
  items: [{ product: testProduct, quantity: 2 }]
});

Changelog

Version 2.1.0 (Latest)

  • Added React 19 support
  • New useOptimisticUpdate hook for optimistic UI updates
  • Improved TypeScript types with stricter generics
  • Performance improvements in caching layer
  • Added support for Server Components in Next.js 15

Version 2.0.0

  • Breaking: Dropped support for Node.js < 18
  • New GraphQL client with automatic query optimization
  • Added webhook verification utilities
  • Improved error handling with typed errors
  • Added request deduplication

Version 1.9.0

  • Added batch operations support
  • New file upload methods
  • Improved retry logic
  • Added cursor-based pagination

View full changelog →

Resources

Support

Need help? We're here for you:

Was this page helpful?