> ## Documentation Index
> Fetch the complete documentation index at: https://www.commercengine.io/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Migration Guide

> Migrate from direct API calls to the type-safe SDK

This guide helps you migrate from direct API calls to the Commerce Engine TypeScript SDK, highlighting the benefits and providing step-by-step migration patterns.

## Why Migrate to the SDK?

<CardGroup cols={2}>
  <Card title="Automatic Token Management" icon="key">
    No more manual token refresh logic - handled automatically by the SDK
  </Card>

  <Card title="100% Type Safety" icon="shield">
    Complete TypeScript support with IntelliSense and compile-time error checking
  </Card>

  <Card title="Simplified Error Handling" icon="circle-exclamation">
    Consistent error patterns with typed error responses across all endpoints
  </Card>

  <Card title="Built-in Best Practices" icon="star">
    Authentication flows and performance optimizations included out of the box
  </Card>
</CardGroup>

## Migration Steps

<Steps>
  <Step title="Install the SDK">
    Replace your manual fetch calls with the SDK:

    ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
    npm install @commercengine/storefront
    ```
  </Step>

  <Step title="Initialize the Client">
    Replace your API configuration with SDK initialization:

    <Tabs>
      <Tab title="Before (Direct API)">
        ```typescript theme={"theme":{"light":"github-light","dark":"github-dark"}}
        // Manual configuration
        const API_BASE_URL = 'https://api.example.com';
        const API_KEY = 'your-api-key';
        let accessToken = '';
        let refreshToken = '';

        // Manual token refresh logic
        async function getValidToken() {
          // Complex token validation and refresh logic
          if (isTokenExpired(accessToken)) {
            const response = await fetch(`${API_BASE_URL}/auth/refresh-token`, {
              method: 'POST',
              headers: { 'Content-Type': 'application/json' },
              body: JSON.stringify({ refresh_token: refreshToken })
            });
            const data = await response.json();
            accessToken = data.access_token;
            refreshToken = data.refresh_token;
          }
          return accessToken;
        }
        ```
      </Tab>

      <Tab title="After (SDK)">
        ```typescript theme={"theme":{"light":"github-light","dark":"github-dark"}}
        import { createStorefront, BrowserTokenStorage } from '@commercengine/storefront';

        // Simple, automated configuration
        const client = createStorefront({
          baseUrl: 'https://api.example.com',
          apiKey: 'your-api-key',
          tokenStorage: new BrowserTokenStorage()
        });

        // Token management is now automatic!
        ```
      </Tab>
    </Tabs>
  </Step>

  <Step title="Update API Calls">
    Replace manual fetch calls with type-safe SDK methods:

    <Tabs>
      <Tab title="Before (Direct API)">
        ```typescript theme={"theme":{"light":"github-light","dark":"github-dark"}}
        // Manual fetch with error handling
        async function fetchProducts(limit: number, categoryId?: string) {
          try {
            const token = await getValidToken();
            const params = new URLSearchParams({ limit: limit.toString() });
            if (categoryId) params.append('category_id', categoryId);
            
            const response = await fetch(`${API_BASE_URL}/catalog/products?${params}`, {
              headers: {
                'Authorization': `Bearer ${token}`,
                'Content-Type': 'application/json'
              }
            });
            
            if (!response.ok) {
              throw new Error(`HTTP ${response.status}: ${response.statusText}`);
            }
            
            const data = await response.json();
            return { success: true, data };
          } catch (error) {
            return { success: false, error: error.message };
          }
        }

        // Usage (no type safety)
        const { data, error } = await fetchProducts(20, 'electronics');
        if (data) {
          data.forEach((product: any) => { // ❌ Any type
            console.log(product.name);
          });
        }
        ```
      </Tab>

      <Tab title="After (SDK)">
        ```typescript theme={"theme":{"light":"github-light","dark":"github-dark"}}
        // Type-safe SDK call
        const { data, error } = await client.catalog.listProducts({
          limit: 20,
          category_id: 'electronics'
        });

        if (data) {
          // ✅ Full type safety with IntelliSense
          data.products.forEach(product => {
            console.log(product.name); // TypeScript knows this is a string
            console.log(product.selling_price); // TypeScript knows this is a number
          });
        } else if (error) {
          // ✅ Typed error handling
          console.error(error.message);
          console.error(error.code);
        }
        ```
      </Tab>
    </Tabs>
  </Step>

  <Step title="Update Authentication">
    Replace manual authentication with SDK auth methods:

    <Tabs>
      <Tab title="Before (Direct API)">
        ```typescript theme={"theme":{"light":"github-light","dark":"github-dark"}}
        // Manual authentication flow
        async function loginWithEmail(email: string) {
          try {
            // Step 1: Initiate login
            const loginResponse = await fetch(`${API_BASE_URL}/auth/login/email`, {
              method: 'POST',
              headers: {
                'Authorization': `Bearer ${await getValidToken()}`,
                'Content-Type': 'application/json'
              },
              body: JSON.stringify({ 
                email, 
                register_if_not_exists: true 
              })
            });
            
            const loginData = await loginResponse.json();
            const otpToken = loginData.content.otp_token;
            
            // Step 2: Get OTP from user (UI logic)
            const otp = await getUserOTPInput();
            
            // Step 3: Verify OTP
            const verifyResponse = await fetch(`${API_BASE_URL}/auth/verify-otp`, {
              method: 'POST',
              headers: {
                'Authorization': `Bearer ${await getValidToken()}`,
                'Content-Type': 'application/json'
              },
              body: JSON.stringify({
                otp,
                otp_token: otpToken,
                otp_action: 'login'
              })
            });
            
            const verifyData = await verifyResponse.json();
            
            // Manual token storage
            accessToken = verifyData.content.access_token;
            refreshToken = verifyData.content.refresh_token;
            localStorage.setItem('access_token', accessToken);
            localStorage.setItem('refresh_token', refreshToken);
            
            return { success: true, user: verifyData.content.user };
          } catch (error) {
            return { success: false, error: error.message };
          }
        }
        ```
      </Tab>

      <Tab title="After (SDK)">
        ```typescript theme={"theme":{"light":"github-light","dark":"github-dark"}}
        // Simplified authentication with automatic token management
        async function loginWithEmail(email: string) {
          // Step 1: Initiate login
          const { data: loginData, error: loginError } = await client.auth.loginWithEmail({
            email,
            register_if_not_exists: true
          });
          
          if (loginError) {
            return { data: null, error: loginError };
          }
          
          const otpToken = loginData.otp_token;
          const otpAction = loginData.otp_action;

          // Step 2: Get OTP from user (UI logic)
          const otp = await getUserOTPInput();

          // Step 3: Verify OTP
          const { data: verifyData, error: verifyError } = await client.auth.verifyOtp({
            otp,
            otp_token: otpToken,
            otp_action: otpAction
          });

          if (verifyData) {
            // ✅ Tokens automatically stored and managed!
            return { data: verifyData, error: null };
          }
          
          return { data: null, error: verifyError };
        }
        ```
      </Tab>
    </Tabs>
  </Step>
</Steps>

## Common Migration Patterns

### Cart Management

<Tabs>
  <Tab title="Before (Direct API)">
    ```typescript theme={"theme":{"light":"github-light","dark":"github-dark"}}
    // Manual cart creation and management
    async function createCartWithItem(productId: string, quantity: number) {
      const token = await getValidToken();
      
      const response = await fetch(`${API_BASE_URL}/carts`, {
        method: 'POST',
        headers: {
          'Authorization': `Bearer ${token}`,
          'Content-Type': 'application/json'
        },
        body: JSON.stringify({
          items: [{ product_id: productId, variant_id: null, quantity }]
        })
      });
      
      if (!response.ok) {
        throw new Error('Failed to create cart');
      }
      
      const cart = await response.json();
      return cart;
    }
    ```
  </Tab>

  <Tab title="After (SDK)">
    ```typescript theme={"theme":{"light":"github-light","dark":"github-dark"}}
    // Type-safe cart management
    async function createCartWithItem(productId: string, quantity: number) {
      const result = await client.cart.createCart({
        items: [{ product_id: productId, variant_id: null, quantity }]
      });
      
      if (result.success) {
        return result.data; // ✅ Fully typed Cart object
      } else {
        throw new Error(result.error.message); // ✅ Typed error
      }
    }
    ```
  </Tab>
</Tabs>

### Error Handling

<Tabs>
  <Tab title="Before (Direct API)">
    ```typescript theme={"theme":{"light":"github-light","dark":"github-dark"}}
    // Manual error handling
    try {
      const response = await fetch(url, options);
      
      if (response.status === 401) {
        // Handle unauthorized
        await refreshTokens();
        // Retry request manually
      } else if (response.status === 400) {
        const error = await response.json();
        // Handle validation errors
      } else if (!response.ok) {
        throw new Error(`HTTP ${response.status}`);
      }
      
      const data = await response.json();
      return data;
    } catch (error) {
      // Generic error handling
    }
    ```
  </Tab>

  <Tab title="After (SDK)">
    ```typescript theme={"theme":{"light":"github-light","dark":"github-dark"}}
    // Consistent error handling across all endpoints
    const result = await client.catalog.getProduct('product-id');

    if (result.success) {
      // ✅ Success - data is fully typed
      console.log(result.data.name);
    } else {
      // ✅ Error - structured error with type safety
      switch (result.error.code) {
        case 'NOT_FOUND':
          // Handle product not found
          break;
        case 'VALIDATION_ERROR':
          // Handle validation errors
          break;
        default:
          // Handle other errors
      }
    }
    ```
  </Tab>
</Tabs>

## Migration Checklist

<Steps>
  <Step title="Replace API Configuration">
    * Install SDK package
    * Replace manual API config with SDK initialization
    * Configure token storage (BrowserTokenStorage, CookieTokenStorage, etc.)
  </Step>

  <Step title="Update Authentication">
    * Replace manual token management with SDK auth methods
    * Remove custom token refresh logic
    * Update login/logout flows to use SDK methods
  </Step>

  <Step title="Migrate API Calls">
    * Replace fetch calls with SDK client methods
    * Add TypeScript types to replace `any` types
    * Update error handling to use SDK error patterns
  </Step>

  <Step title="Test & Optimize">
    * Test all authentication flows
    * Verify token management across browser tabs
    * Enable debug mode for development
    * Add performance monitoring
  </Step>
</Steps>

## Benefits After Migration

<AccordionGroup>
  <Accordion title="Development Experience">
    * **IntelliSense**: Complete autocomplete for all API methods and parameters
    * **Type Safety**: Compile-time error checking prevents runtime issues
    * **Better Debugging**: Built-in logging and error tracking
    * **Reduced Boilerplate**: No more manual token management code
  </Accordion>

  <Accordion title="Authentication & Security">
    * **Automatic Token Refresh**: No more expired token errors
    * **Secure Storage**: Built-in secure token storage options
    * **Cross-tab Sync**: Token updates sync across browser tabs
    * **Session Management**: Handles anonymous-to-authenticated transitions
  </Accordion>

  <Accordion title="Performance & Reliability">
    * **Request Optimization**: Built-in connection pooling and optimization
    * **Error Recovery**: Automatic retry logic for failed requests
    * **Caching Support**: Built-in caching middleware support
    * **Production Ready**: Battle-tested in production environments
  </Accordion>
</AccordionGroup>

## Need Help?

If you encounter issues during migration:

1. **Enable Debug Mode**: Set `debug: true` in SDK configuration
2. **Check Documentation**: Review [API Reference](/api-reference) for endpoint details
3. **Follow Patterns**: Reference [Storefront Guides](/storefront) for business logic
4. **Type Safety**: Use TypeScript for better development experience

<Note>
  The SDK is designed to be a drop-in replacement for direct API calls while providing significant improvements in developer experience, type safety, and reliability.
</Note>
