Guide BigCommerce API : Intégration et Développement Avancé
Guide développeur pour maîtriser l'API BigCommerce : authentication, endpoints, webhooks, intégrations et développement d'applications complètes.
📋 Table des Matières
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 :
- Architecture solide : Error handling, rate limiting, caching
- Performance focus : Batch operations, efficient queries
- Monitoring continu : Logs, metrics, alerting
- 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 ! 🚀