Guide BigCommerce API : Développement et Intégrations

L’API BigCommerce est l’une des plus robustes du marché e-commerce, alimentant plus de 60,000 boutiques et traitant 28+ milliards de dollars de GMV. Ce guide technique vous révèle comment exploiter pleinement cette API pour créer des intégrations puissantes et des applications e-commerce avancées.

🎯 Vue d’ensemble API BigCommerce

Architecture API

  • REST API : Architecture RESTful standard
  • GraphQL : Pour queries complexes et performance
  • Webhooks : Events en temps réel
  • Rate limits : 20,000 requests/heure (Store API)
  • Authentication : OAuth 2.0, API tokens

Versions disponibles

Store API v2: Legacy (deprecated)
Store API v3: Current standard
GraphQL Storefront API: Frontend queries
Management API: Store management
Customer Login API: SSO integration

🔐 Authentication et Setup

1. API Credentials Setup

Store API Token (Simple) :

# Via BigCommerce Control Panel
# Advanced Settings > API Accounts > Create API Account

# Scopes requis selon usage:
- store_v2_products: read/modify (legacy)
- store_v3_catalog: read/modify (products v3)
- store_v3_customers: read/modify
- store_v3_orders: read/modify
- store_v3_content: read/modify
- store_information: read

OAuth Flow (Apps) :

// OAuth 2.0 Authorization Code Flow
const authUrl = `https://login.bigcommerce.com/oauth2/authorize?client_id=${CLIENT_ID}&response_type=code&redirect_uri=${REDIRECT_URI}&scope=store_v3_catalog_read store_v3_orders_modify`;

// Exchange code for token
const tokenResponse = await fetch('https://login.bigcommerce.com/oauth2/token', {
  method: 'POST',
  headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
  body: new URLSearchParams({
    client_id: CLIENT_ID,
    client_secret: CLIENT_SECRET,
    redirect_uri: REDIRECT_URI,
    grant_type: 'authorization_code',
    code: authorizationCode
  })
});

2. API Client Setup

Node.js Client :

const BigCommerce = require('node-bigcommerce');

const bigCommerce = new BigCommerce({
  logLevel: 'info',
  clientId: process.env.BC_CLIENT_ID,
  secret: process.env.BC_CLIENT_SECRET,
  accessToken: process.env.BC_ACCESS_TOKEN,
  storeHash: process.env.BC_STORE_HASH,
  responseType: 'json',
  apiVersion: 'v3'
});

// Test connection
async function testConnection() {
  try {
    const store = await bigCommerce.get('/store');
    console.log(`Connected to: ${store.name}`);
  } catch (error) {
    console.error('Connection failed:', error);
  }
}

Python Client :

import bigcommerce

# Initialize API client
api = bigcommerce.api.BigcommerceApi(
    client_id=os.getenv('BC_CLIENT_ID'),
    store_hash=os.getenv('BC_STORE_HASH'),
    access_token=os.getenv('BC_ACCESS_TOKEN')
)

# Test connection
try:
    store = api.Store.all()
    print(f"Connected to: {store['name']}")
except Exception as e:
    print(f"Connection failed: {e}")

📦 Catalog API : Gestion Produits

1. Products Management

Créer un produit :

async function createProduct(productData) {
  const product = {
    name: productData.name,
    type: 'physical', // physical, digital, gift_certificate
    weight: productData.weight,
    price: productData.price,
    categories: productData.categoryIds,
    availability: 'available',
    visibility: 'visible',
    inventory_level: productData.stock,
    inventory_warning_level: 5,
    
    // SEO
    meta_description: productData.metaDescription,
    meta_keywords: productData.metaKeywords,
    search_keywords: productData.searchKeywords,
    page_title: productData.seoTitle,
    
    // Advanced fields
    custom_fields: [
      {
        name: 'Material',
        value: productData.material
      },
      {
        name: 'Care Instructions',
        value: productData.careInstructions
      }
    ]
  };

  try {
    const response = await bigCommerce.post('/catalog/products', product);
    console.log(`Product created with ID: ${response.data.id}`);
    return response.data;
  } catch (error) {
    console.error('Product creation failed:', error.response.data);
    throw error;
  }
}

Bulk products import :

async function bulkImportProducts(productsArray) {
  const batchSize = 10; // BC recommends max 10 per batch
  const results = [];
  
  for (let i = 0; i < productsArray.length; i += batchSize) {
    const batch = productsArray.slice(i, i + batchSize);
    
    try {
      const promises = batch.map(product => createProduct(product));
      const batchResults = await Promise.allSettled(promises);
      
      results.push(...batchResults);
      
      // Rate limiting: wait between batches
      if (i + batchSize < productsArray.length) {
        await new Promise(resolve => setTimeout(resolve, 1000));
      }
    } catch (error) {
      console.error(`Batch ${i/batchSize + 1} failed:`, error);
    }
  }
  
  return results;
}

2. Product Variants

Managing variants :

async function createProductVariants(productId, variantOptions) {
  // First, create option (Size, Color, etc.)
  const option = await bigCommerce.post(`/catalog/products/${productId}/options`, {
    display_name: 'Size',
    type: 'dropdown', // dropdown, radio_buttons, rectangles, etc.
    sort_order: 1,
    option_values: [
      { label: 'Small', sort_order: 1 },
      { label: 'Medium', sort_order: 2 },
      { label: 'Large', sort_order: 3 }
    ]
  });

  // Create variants based on options
  const variants = [
    {
      cost_price: 15.00,
      price: 25.00,
      sale_price: 20.00,
      retail_price: 30.00,
      weight: 1.5,
      width: 10,
      depth: 10,
      height: 2,
      sku: 'SHIRT-S-001',
      upc: '123456789012',
      inventory_level: 100,
      bin_picking_number: 'A1-001',
      option_values: [
        {
          option_display_name: 'Size',
          label: 'Small'
        }
      ]
    }
  ];

  return await bigCommerce.post(`/catalog/products/${productId}/variants`, variants);
}

3. Categories Management

Hierarchical categories :

async function createCategoryHierarchy(categories) {
  const categoryMap = new Map();
  
  // Sort by level (parents first)
  const sortedCategories = categories.sort((a, b) => (a.level || 0) - (b.level || 0));
  
  for (const category of sortedCategories) {
    const categoryData = {
      name: category.name,
      description: category.description,
      sort_order: category.sortOrder || 0,
      page_title: category.seoTitle,
      meta_keywords: category.metaKeywords,
      meta_description: category.metaDescription,
      is_visible: true,
      default_product_sort: 'use_store_settings'
    };
    
    // Set parent if exists
    if (category.parentSlug && categoryMap.has(category.parentSlug)) {
      categoryData.parent_id = categoryMap.get(category.parentSlug);
    }
    
    const response = await bigCommerce.post('/catalog/categories', categoryData);
    categoryMap.set(category.slug, response.data.id);
  }
  
  return categoryMap;
}

🛒 Orders API : Gestion Commandes

1. Orders Retrieval

Advanced order queries :

async function getOrdersWithFilters(filters = {}) {
  const params = new URLSearchParams();
  
  // Date filters
  if (filters.dateFrom) params.append('min_date_created', filters.dateFrom);
  if (filters.dateTo) params.append('max_date_created', filters.dateTo);
  
  // Status filters
  if (filters.status) params.append('status_id', filters.status);
  
  // Customer filters
  if (filters.customerId) params.append('customer_id', filters.customerId);
  
  // Pagination
  params.append('page', filters.page || 1);
  params.append('limit', filters.limit || 50);
  
  // Include related data
  params.append('include', 'line_items,billing_address,shipping_address');
  
  const response = await bigCommerce.get(`/orders?${params}`);
  
  return {
    orders: response.data,
    pagination: response.meta?.pagination
  };
}

2. Order Processing

Order fulfillment workflow :

class OrderProcessor {
  constructor(bigCommerceClient) {
    this.bc = bigCommerceClient;
  }
  
  async processOrder(orderId) {
    try {
      // 1. Get order details
      const order = await this.bc.get(`/orders/${orderId}`);
      
      // 2. Validate inventory
      await this.validateInventory(order.data);
      
      // 3. Process payment if needed
      await this.processPayment(order.data);
      
      // 4. Create shipment
      const shipment = await this.createShipment(order.data);
      
      // 5. Update order status
      await this.updateOrderStatus(orderId, 'shipped', shipment.tracking_number);
      
      // 6. Send notification
      await this.sendShippingNotification(order.data, shipment);
      
      return { success: true, shipment };
    } catch (error) {
      console.error(`Order ${orderId} processing failed:`, error);
      await this.updateOrderStatus(orderId, 'failed', null, error.message);
      throw error;
    }
  }
  
  async createShipment(order) {
    const shipment = {
      order_id: order.id,
      line_items: order.line_items.physical_items.map(item => ({
        order_product_id: item.id,
        quantity: item.quantity
      })),
      shipping_provider: 'fedex',
      shipping_method: 'ground',
      tracking_number: this.generateTrackingNumber(),
      comments: 'Order shipped via FedEx Ground'
    };
    
    const response = await this.bc.post(`/orders/${order.id}/shipments`, shipment);
    return response.data;
  }
  
  async updateOrderStatus(orderId, status, trackingNumber = null, message = null) {
    const updateData = { status_id: this.getStatusId(status) };
    
    if (message) {
      updateData.staff_notes = message;
    }
    
    await this.bc.put(`/orders/${orderId}`, updateData);
    
    // Add order status history
    if (trackingNumber) {
      await this.bc.post(`/orders/${orderId}/status_emails`, {
        to: 'customer',
        subject: 'Your order has shipped!',
        message: `Your order is on its way. Tracking number: ${trackingNumber}`
      });
    }
  }
}

3. Refunds and Returns

Refund processing :

async function processRefund(orderId, refundData) {
  const refund = {
    items: refundData.items.map(item => ({
      item_id: item.orderProductId,
      item_type: 'PRODUCT',
      quantity: item.quantity,
      reason: item.reason || 'requested_by_customer'
    })),
    payments: [{
      provider_id: refundData.paymentProviderId,
      amount: refundData.amount,
      offline: false
    }]
  };
  
  try {
    const response = await bigCommerce.post(`/orders/${orderId}/payment_actions/refunds`, refund);
    
    // Update inventory if needed
    await updateInventoryForRefund(refundData.items);
    
    // Send confirmation email
    await sendRefundConfirmation(orderId, refund);
    
    return response.data;
  } catch (error) {
    console.error('Refund processing failed:', error);
    throw error;
  }
}

👥 Customers API : Gestion Clients

1. Customer Management

Advanced customer operations :

class CustomerManager {
  constructor(bigCommerceClient) {
    this.bc = bigCommerceClient;
  }
  
  async createCustomer(customerData) {
    const customer = {
      email: customerData.email,
      first_name: customerData.firstName,
      last_name: customerData.lastName,
      company: customerData.company,
      phone: customerData.phone,
      registration_ip_address: customerData.ipAddress,
      customer_group_id: customerData.groupId || 0,
      
      // Custom fields for segmentation
      custom_fields: [
        {
          name: 'acquisition_channel',
          value: customerData.acquisitionChannel
        },
        {
          name: 'preferred_communication',
          value: customerData.preferredCommunication
        }
      ]
    };
    
    const response = await this.bc.post('/customers', [customer]);
    return response.data[0];
  }
  
  async getCustomerInsights(customerId) {
    const [customer, orders, addresses] = await Promise.all([
      this.bc.get(`/customers/${customerId}`),
      this.bc.get(`/orders?customer_id=${customerId}`),
      this.bc.get(`/customers/${customerId}/addresses`)
    ]);
    
    const insights = {
      profile: customer.data,
      orderHistory: orders.data,
      addresses: addresses.data,
      
      // Calculate metrics
      totalSpent: orders.data.reduce((sum, order) => sum + parseFloat(order.total_inc_tax), 0),
      averageOrderValue: orders.data.length > 0 ? 
        orders.data.reduce((sum, order) => sum + parseFloat(order.total_inc_tax), 0) / orders.data.length : 0,
      lastOrderDate: orders.data.length > 0 ? 
        new Date(Math.max(...orders.data.map(o => new Date(o.date_created)))) : null,
      
      // Segmentation
      segment: this.calculateCustomerSegment(customer.data, orders.data)
    };
    
    return insights;
  }
  
  calculateCustomerSegment(customer, orders) {
    const totalSpent = orders.reduce((sum, order) => sum + parseFloat(order.total_inc_tax), 0);
    const orderCount = orders.length;
    const daysSinceLastOrder = orders.length > 0 ? 
      Math.floor((Date.now() - new Date(Math.max(...orders.map(o => new Date(o.date_created))))) / (1000 * 60 * 60 * 24)) : 365;
    
    if (totalSpent > 1000 && orderCount > 5 && daysSinceLastOrder < 90) {
      return 'VIP';
    } else if (totalSpent > 500 && orderCount > 3 && daysSinceLastOrder < 180) {
      return 'Loyal';
    } else if (orderCount > 1 && daysSinceLastOrder < 365) {
      return 'Regular';
    } else if (orderCount === 1 && daysSinceLastOrder < 30) {
      return 'New';
    } else {
      return 'At Risk';
    }
  }
}

2. Customer Segmentation

Automated segmentation :

async function runCustomerSegmentation() {
  const customers = await bigCommerce.get('/customers?limit=250');
  const segments = {
    vip: [],
    loyal: [],
    regular: [],
    new: [],
    atRisk: []
  };
  
  for (const customer of customers.data) {
    const insights = await customerManager.getCustomerInsights(customer.id);
    segments[insights.segment.toLowerCase()].push(customer);
    
    // Update customer group based on segment
    const groupId = getCustomerGroupId(insights.segment);
    if (customer.customer_group_id !== groupId) {
      await bigCommerce.put(`/customers/${customer.id}`, {
        customer_group_id: groupId
      });
    }
  }
  
  return segments;
}

🎣 Webhooks : Events en Temps Réel

1. Webhook Setup

Creating webhooks :

async function setupWebhooks() {
  const webhooks = [
    {
      scope: 'store/order/created',
      destination: 'https://your-app.com/webhooks/order-created',
      is_active: true,
      headers: {
        'X-Auth-Token': process.env.WEBHOOK_SECRET
      }
    },
    {
      scope: 'store/order/statusUpdated',
      destination: 'https://your-app.com/webhooks/order-updated',
      is_active: true
    },
    {
      scope: 'store/product/created',
      destination: 'https://your-app.com/webhooks/product-created',
      is_active: true
    },
    {
      scope: 'store/customer/created',
      destination: 'https://your-app.com/webhooks/customer-created',
      is_active: true
    }
  ];
  
  const results = [];
  for (const webhook of webhooks) {
    try {
      const response = await bigCommerce.post('/hooks', webhook);
      results.push(response.data);
    } catch (error) {
      console.error('Webhook creation failed:', error);
    }
  }
  
  return results;
}

2. Webhook Handler

Express.js webhook handler :

const express = require('express');
const crypto = require('crypto');
const app = express();

// Middleware for webhook verification
function verifyWebhook(req, res, next) {
  const signature = req.headers['x-bc-webhook-signature'];
  const body = JSON.stringify(req.body);
  
  const hash = crypto
    .createHmac('sha256', process.env.WEBHOOK_SECRET)
    .update(body)
    .digest('hex');
  
  if (signature !== hash) {
    return res.status(401).send('Unauthorized');
  }
  
  next();
}

app.use(express.json());

// Order created webhook
app.post('/webhooks/order-created', verifyWebhook, async (req, res) => {
  try {
    const { scope, store_id, data, producer } = req.body;
    
    console.log(`New order created: ${data.id} in store ${store_id}`);
    
    // Process the order
    await processNewOrder(data.id);
    
    // Send to CRM
    await syncOrderToCRM(data.id);
    
    // Trigger fulfillment workflow
    await triggerFulfillment(data.id);
    
    res.status(200).send('OK');
  } catch (error) {
    console.error('Webhook processing failed:', error);
    res.status(500).send('Internal Server Error');
  }
});

// Product updated webhook
app.post('/webhooks/product-updated', verifyWebhook, async (req, res) => {
  try {
    const { data } = req.body;
    
    // Update search index
    await updateSearchIndex(data.id);
    
    // Update recommendations
    await updateProductRecommendations(data.id);
    
    // Sync to external systems
    await syncProductToChannels(data.id);
    
    res.status(200).send('OK');
  } catch (error) {
    console.error('Product webhook processing failed:', error);
    res.status(500).send('Internal Server Error');
  }
});

async function processNewOrder(orderId) {
  // Get full order details
  const order = await bigCommerce.get(`/orders/${orderId}?include=line_items,billing_address,shipping_address`);
  
  // Business logic for new orders
  await Promise.all([
    sendOrderConfirmation(order.data),
    updateInventory(order.data.line_items),
    createShippingLabel(order.data),
    updateCustomerSegment(order.data.customer_id)
  ]);
}

🛍️ Storefront API : Frontend Integration

1. GraphQL Storefront

Product queries :

query getProducts($first: Int, $categoryId: Int) {
  site {
    products(first: $first, filters: { categoryEntityId: $categoryId }) {
      edges {
        node {
          entityId
          name
          sku
          description
          availabilityV2 {
            status
          }
          prices {
            price {
              value
              currencyCode
            }
            salePrice {
              value
            }
          }
          defaultImage {
            url: urlTemplate
            altText
          }
          variants(first: 50) {
            edges {
              node {
                entityId
                sku
                inventory {
                  aggregated {
                    availableToSell
                  }
                }
                options {
                  edges {
                    node {
                      displayName
                      values {
                        edges {
                          node {
                            label
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
      pageInfo {
        hasNextPage
        hasPreviousPage
        startCursor
        endCursor
      }
    }
  }
}

React integration :

import { ApolloClient, InMemoryCache, gql, useQuery } from '@apollo/client';

const client = new ApolloClient({
  uri: `https://store-${storeHash}.mybigcommerce.com/graphql`,
  cache: new InMemoryCache(),
  headers: {
    Authorization: `Bearer ${storefrontToken}`
  }
});

function ProductGrid({ categoryId }) {
  const { loading, error, data, fetchMore } = useQuery(GET_PRODUCTS, {
    variables: { first: 12, categoryId },
    client
  });

  if (loading) return <ProductGridSkeleton />;
  if (error) return <ErrorMessage error={error} />;

  const products = data?.site?.products?.edges || [];
  const pageInfo = data?.site?.products?.pageInfo;

  return (
    <div className="product-grid">
      {products.map(({ node: product }) => (
        <ProductCard key={product.entityId} product={product} />
      ))}
      
      {pageInfo?.hasNextPage && (
        <button
          onClick={() => fetchMore({
            variables: { cursor: pageInfo.endCursor },
            updateQuery: (prev, { fetchMoreResult }) => {
              return {
                site: {
                  products: {
                    edges: [...prev.site.products.edges, ...fetchMoreResult.site.products.edges],
                    pageInfo: fetchMoreResult.site.products.pageInfo
                  }
                }
              };
            }
          })}
        >
          Load More
        </button>
      )}
    </div>
  );
}

2. Cart Management

Advanced cart operations :

class CartManager {
  constructor(storefrontToken, storeHash) {
    this.client = new ApolloClient({
      uri: `https://store-${storeHash}.mybigcommerce.com/graphql`,
      cache: new InMemoryCache(),
      headers: { Authorization: `Bearer ${storefrontToken}` }
    });
  }
  
  async addToCart(cartId, lineItems) {
    const ADD_TO_CART = gql`
      mutation AddCartLineItems($cartId: String!, $data: AddCartLineItemsInput!) {
        cart {
          addCartLineItems(input: { cartEntityId: $cartId, data: $data }) {
            cart {
              entityId
              lineItems {
                totalQuantity
                physicalItems {
                  entityId
                  name
                  quantity
                  extendedSalePrice {
                    value
                  }
                }
              }
              amount {
                value
                currencyCode
              }
            }
          }
        }
      }
    `;
    
    const { data } = await this.client.mutate({
      mutation: ADD_TO_CART,
      variables: {
        cartId,
        data: { lineItems }
      }
    });
    
    return data.cart.addCartLineItems.cart;
  }
  
  async applyCoupon(cartId, couponCode) {
    const APPLY_COUPON = gql`
      mutation ApplyCoupon($cartId: String!, $couponCode: String!) {
        cart {
          applyCoupon(input: { cartEntityId: $cartId, data: { couponCode: $couponCode } }) {
            cart {
              entityId
              discounts {
                value
                discountType
              }
              amount {
                value
              }
            }
          }
        }
      }
    `;
    
    return await this.client.mutate({
      mutation: APPLY_COUPON,
      variables: { cartId, couponCode }
    });
  }
}

📊 Advanced Integrations

1. ERP Integration

SAP Business One integration :

class ERPIntegration {
  constructor(bigCommerceClient, sapClient) {
    this.bc = bigCommerceClient;
    this.sap = sapClient;
  }
  
  async syncProducts() {
    // Get products from SAP
    const sapProducts = await this.sap.getProducts();
    
    for (const sapProduct of sapProducts) {
      try {
        // Check if product exists in BC
        const bcProducts = await this.bc.get(`/catalog/products?sku=${sapProduct.ItemCode}`);
        
        if (bcProducts.data.length > 0) {
          // Update existing product
          await this.updateBCProduct(bcProducts.data[0].id, sapProduct);
        } else {
          // Create new product
          await this.createBCProduct(sapProduct);
        }
      } catch (error) {
        console.error(`Sync failed for product ${sapProduct.ItemCode}:`, error);
      }
    }
  }
  
  async syncInventory() {
    const sapInventory = await this.sap.getInventoryLevels();
    
    for (const item of sapInventory) {
      try {
        const bcProducts = await this.bc.get(`/catalog/products?sku=${item.ItemCode}&include=variants`);
        
        if (bcProducts.data.length > 0) {
          const product = bcProducts.data[0];
          
          // Update main product inventory
          await this.bc.put(`/catalog/products/${product.id}`, {
            inventory_level: item.OnHand,
            inventory_warning_level: item.MinStock || 5
          });
          
          // Update variants if any
          if (product.variants) {
            for (const variant of product.variants) {
              const variantInventory = await this.sap.getVariantInventory(item.ItemCode, variant.sku);
              if (variantInventory) {
                await this.bc.put(`/catalog/products/${product.id}/variants/${variant.id}`, {
                  inventory_level: variantInventory.OnHand
                });
              }
            }
          }
        }
      } catch (error) {
        console.error(`Inventory sync failed for ${item.ItemCode}:`, error);
      }
    }
  }
  
  async syncOrders() {
    // Get new BC orders
    const orders = await this.bc.get('/orders?status_id=1&limit=50'); // Pending orders
    
    for (const order of orders.data) {
      try {
        // Create sales order in SAP
        const sapOrder = await this.createSAPSalesOrder(order);
        
        // Update BC order with SAP reference
        await this.bc.put(`/orders/${order.id}`, {
          staff_notes: `SAP Order: ${sapOrder.DocNum}`,
          external_id: sapOrder.DocEntry.toString()
        });
        
        // Update order status
        await this.bc.put(`/orders/${order.id}`, {
          status_id: 2 // Processing
        });
        
      } catch (error) {
        console.error(`Order sync failed for BC order ${order.id}:`, error);
      }
    }
  }
}

2. Marketing Automation

HubSpot integration :

class HubSpotIntegration {
  constructor(bigCommerceClient, hubspotClient) {
    this.bc = bigCommerceClient;
    this.hs = hubspotClient;
  }
  
  async syncCustomers() {
    const customers = await this.bc.get('/customers?limit=250');
    
    for (const customer of customers.data) {
      try {
        const orderHistory = await this.bc.get(`/orders?customer_id=${customer.id}`);
        
        // Calculate customer metrics
        const metrics = this.calculateCustomerMetrics(orderHistory.data);
        
        // Create/update contact in HubSpot
        const hsContact = {
          properties: {
            email: customer.email,
            firstname: customer.first_name,
            lastname: customer.last_name,
            phone: customer.phone,
            company: customer.company,
            
            // Custom properties
            total_orders: metrics.totalOrders,
            total_spent: metrics.totalSpent,
            average_order_value: metrics.averageOrderValue,
            last_order_date: metrics.lastOrderDate,
            customer_segment: metrics.segment,
            
            // Behavioral data
            preferred_categories: metrics.preferredCategories.join(';'),
            shopping_frequency: metrics.shoppingFrequency,
            price_sensitivity: metrics.priceSensitivity
          }
        };
        
        await this.hs.crm.contacts.basicApi.createOrUpdate(customer.email, hsContact);
        
      } catch (error) {
        console.error(`Customer sync failed for ${customer.email}:`, error);
      }
    }
  }
  
  async triggerAbandonedCartCampaign(cartData) {
    // Create abandoned cart workflow in HubSpot
    const contact = await this.hs.crm.contacts.basicApi.getByEmail(cartData.email);
    
    if (contact) {
      // Add to abandoned cart workflow
      await this.hs.automation.workflows.enrollContact(
        process.env.HUBSPOT_ABANDONED_CART_WORKFLOW_ID,
        contact.id,
        {
          cart_url: cartData.cart_url,
          cart_value: cartData.total,
          product_names: cartData.line_items.map(item => item.name).join(', ')
        }
      );
    }
  }
}

🔧 Development Tools & Testing

1. SDK Development

Custom SDK wrapper :

class BigCommerceSDK {
  constructor(config) {
    this.client = new BigCommerce(config);
    this.cache = new Map();
    this.rateLimiter = new RateLimiter(20000, 3600000); // 20k requests per hour
  }
  
  async request(method, endpoint, data = null, options = {}) {
    // Rate limiting
    await this.rateLimiter.acquire();
    
    // Caching for GET requests
    const cacheKey = `${method}:${endpoint}`;
    if (method === 'GET' && this.cache.has(cacheKey) && !options.bypassCache) {
      const cached = this.cache.get(cacheKey);
      if (Date.now() - cached.timestamp < (options.cacheDuration || 300000)) {
        return cached.data;
      }
    }
    
    try {
      let response;
      switch (method.toLowerCase()) {
        case 'get':
          response = await this.client.get(endpoint);
          break;
        case 'post':
          response = await this.client.post(endpoint, data);
          break;
        case 'put':
          response = await this.client.put(endpoint, data);
          break;
        case 'delete':
          response = await this.client.delete(endpoint);
          break;
      }
      
      // Cache successful GET requests
      if (method === 'GET' && response.data) {
        this.cache.set(cacheKey, {
          data: response.data,
          timestamp: Date.now()
        });
      }
      
      return response.data;
    } catch (error) {
      // Enhanced error handling
      if (error.response) {
        const errorData = {
          status: error.response.status,
          statusText: error.response.statusText,
          data: error.response.data,
          endpoint,
          method
        };
        
        throw new BigCommerceAPIError(errorData);
      }
      
      throw error;
    }
  }
  
  // Convenience methods
  async getProducts(params = {}) {
    const queryString = new URLSearchParams(params).toString();
    return this.request('GET', `/catalog/products${queryString ? '?' + queryString : ''}`);
  }
  
  async createProduct(productData) {
    return this.request('POST', '/catalog/products', productData);
  }
  
  async updateProduct(productId, productData) {
    return this.request('PUT', `/catalog/products/${productId}`, productData);
  }
}

class BigCommerceAPIError extends Error {
  constructor(errorData) {
    super(`BigCommerce API Error: ${errorData.status} ${errorData.statusText}`);
    this.name = 'BigCommerceAPIError';
    this.status = errorData.status;
    this.statusText = errorData.statusText;
    this.data = errorData.data;
    this.endpoint = errorData.endpoint;
    this.method = errorData.method;
  }
}

2. Testing Framework

API Testing Suite :

const { describe, it, expect, beforeAll, afterAll } = require('@jest/globals');

describe('BigCommerce API Integration', () => {
  let sdk;
  let testProduct;
  
  beforeAll(async () => {
    sdk = new BigCommerceSDK({
      clientId: process.env.TEST_BC_CLIENT_ID,
      secret: process.env.TEST_BC_CLIENT_SECRET,
      accessToken: process.env.TEST_BC_ACCESS_TOKEN,
      storeHash: process.env.TEST_BC_STORE_HASH
    });
    
    // Create test product
    testProduct = await sdk.createProduct({
      name: 'Test Product API',
      type: 'physical',
      price: 29.99,
      weight: 1,
      categories: [18]
    });
  });
  
  afterAll(async () => {
    // Clean up test product
    if (testProduct) {
      await sdk.request('DELETE', `/catalog/products/${testProduct.id}`);
    }
  });
  
  it('should create a product successfully', async () => {
    expect(testProduct).toBeDefined();
    expect(testProduct.name).toBe('Test Product API');
    expect(testProduct.price).toBe('29.99');
  });
  
  it('should retrieve product by ID', async () => {
    const product = await sdk.request('GET', `/catalog/products/${testProduct.id}`);
    
    expect(product).toBeDefined();
    expect(product.id).toBe(testProduct.id);
    expect(product.name).toBe('Test Product API');
  });
  
  it('should update product successfully', async () => {
    const updatedProduct = await sdk.updateProduct(testProduct.id, {
      name: 'Updated Test Product',
      price: 39.99
    });
    
    expect(updatedProduct.name).toBe('Updated Test Product');
    expect(updatedProduct.price).toBe('39.99');
  });
  
  it('should handle rate limiting gracefully', async () => {
    const requests = [];
    
    // Make multiple rapid requests
    for (let i = 0; i < 5; i++) {
      requests.push(sdk.getProducts({ limit: 1 }));
    }
    
    const results = await Promise.all(requests);
    
    // All requests should succeed (rate limiting handled internally)
    results.forEach(result => {
      expect(result).toBeDefined();
      expect(Array.isArray(result)).toBe(true);
    });
  });
});

🎯 Best Practices et Optimisations

1. Performance Optimization

Batch operations :

class BatchProcessor {
  constructor(sdk, batchSize = 10) {
    this.sdk = sdk;
    this.batchSize = batchSize;
  }
  
  async processBatch(items, processor, delayMs = 1000) {
    const results = [];
    
    for (let i = 0; i < items.length; i += this.batchSize) {
      const batch = items.slice(i, i + this.batchSize);
      
      try {
        const batchPromises = batch.map(item => processor(item));
        const batchResults = await Promise.allSettled(batchPromises);
        
        results.push(...batchResults);
        
        // Respect rate limits
        if (i + this.batchSize < items.length) {
          await new Promise(resolve => setTimeout(resolve, delayMs));
        }
      } catch (error) {
        console.error(`Batch ${Math.floor(i / this.batchSize) + 1} failed:`, error);
      }
    }
    
    return results;
  }
}

// Usage
const batchProcessor = new BatchProcessor(sdk, 5);
const results = await batchProcessor.processBatch(
  productsToUpdate,
  async (product) => sdk.updateProduct(product.id, product.data)
);

2. Error Handling

Comprehensive error handling :

class ErrorHandler {
  static handle(error, context = {}) {
    const errorInfo = {
      timestamp: new Date().toISOString(),
      context,
      error: {
        name: error.name,
        message: error.message,
        stack: error.stack
      }
    };
    
    if (error instanceof BigCommerceAPIError) {
      errorInfo.api = {
        status: error.status,
        statusText: error.statusText,
        endpoint: error.endpoint,
        method: error.method,
        data: error.data
      };
      
      // Handle specific API errors
      switch (error.status) {
        case 429:
          return this.handleRateLimit(error, context);
        case 422:
          return this.handleValidationError(error, context);
        case 404:
          return this.handleNotFound(error, context);
        case 500:
          return this.handleServerError(error, context);
      }
    }
    
    // Log error
    console.error('BigCommerce API Error:', errorInfo);
    
    // Send to monitoring service
    this.sendToMonitoring(errorInfo);
    
    throw error;
  }
  
  static async handleRateLimit(error, context) {
    const retryAfter = error.data?.['x-rate-limit-time-reset-ms'] || 60000;
    
    console.log(`Rate limited. Retrying after ${retryAfter}ms`);
    
    await new Promise(resolve => setTimeout(resolve, retryAfter));
    
    // Retry the operation
    return context.retry?.();
  }
  
  static handleValidationError(error, context) {
    const validationErrors = error.data?.errors || [];
    
    console.error('Validation errors:', validationErrors);
    
    // Format errors for user-friendly display
    const formattedErrors = validationErrors.map(err => ({
      field: err.field,
      message: err.message,
      code: err.code
    }));
    
    throw new ValidationError('Data validation failed', formattedErrors);
  }
}

📋 Checklist Intégration

Setup Initial

  • API Credentials configurées et testées
  • Webhooks configurés pour events critiques
  • Rate limiting géré correctement
  • Error handling robuste implementé
  • Logging et monitoring configurés

Développement

  • SDK wrapper pour API calls
  • Batch processing pour opérations bulk
  • Caching pour améliorer performance
  • Testing suite avec cas edge
  • Documentation API complète

Production

  • Environment separation (dev/staging/prod)
  • Security : tokens chiffrés, HTTPS only
  • Monitoring : uptime, performance, errors
  • Backup strategy pour données critiques
  • Disaster recovery plan testé

Optimisation

  • Performance benchmarks établis
  • Caching strategy optimisée
  • Database indexing pour queries fréquentes
  • CDN pour assets statiques
  • Load testing effectué

🎯 Conclusion

L’API BigCommerce offre une flexibilité exceptionnelle pour créer des expériences e-commerce sur-mesure. Les clés du succès :

  1. Architecture solide : Error handling, rate limiting, caching
  2. Performance focus : Batch operations, efficient queries
  3. Monitoring continu : Logs, metrics, alerting
  4. Testing rigoureux : Unit tests, integration tests, load tests

Pro tip : Commencez simple avec les APIs essentielles (Products, Orders, Customers), puis évoluez vers des intégrations complexes. L’API BigCommerce récompense la patience et la méthodologie !

Votre intégration BigCommerce est maintenant prête à alimenter votre croissance e-commerce ! 🚀