woocommerce-rest-api

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

WooCommerce REST API

WooCommerce REST API

Overview

概述

WooCommerce ships a versioned REST API (
/wp-json/wc/v3/
) that exposes products, orders, customers, coupons, and store settings over HTTPS. It uses OAuth 1.0a for non-HTTPS environments and Basic Auth (consumer key/secret) over HTTPS. The official
@woocommerce/woocommerce-rest-api
Node.js client handles authentication automatically and supports the full CRUD surface.
WooCommerce 提供了一个版本化的 REST API(
/wp-json/wc/v3/
),通过 HTTPS 对外暴露产品、订单、客户、优惠券和店铺设置相关接口。在非 HTTPS 环境中使用 OAuth 1.0a 认证,在 HTTPS 环境中则使用 Basic Auth(消费者密钥/密钥密码)。官方的
@woocommerce/woocommerce-rest-api
Node.js 客户端会自动处理认证,并支持完整的 CRUD 操作。

When to Use This Skill

何时使用此技能

  • When building a headless storefront that reads products and categories from WooCommerce
  • When integrating WooCommerce with an ERP, CRM, or fulfillment system
  • When creating an order management dashboard outside of WordPress Admin
  • When syncing inventory between WooCommerce and a warehouse or POS system
  • When automating bulk product imports or price updates from an external catalog
  • When building a mobile app that needs access to WooCommerce store data
  • 构建从 WooCommerce 读取产品和分类信息的无头店铺前端时
  • 将 WooCommerce 与 ERP、CRM 或履约系统集成时
  • 在 WordPress 后台之外创建订单管理仪表盘时
  • 在 WooCommerce 与仓库或 POS 系统之间同步库存时
  • 从外部目录自动批量导入产品或更新价格时
  • 构建需要访问 WooCommerce 店铺数据的移动应用时

Core Instructions

核心操作步骤

  1. Generate API credentials
    In WordPress Admin → WooCommerce → Settings → Advanced → REST API → Add Key:
    • Description:
      My Integration
    • User: (admin user)
    • Permissions: Read/Write
    This generates a Consumer Key (
    ck_xxx
    ) and Consumer Secret (
    cs_xxx
    ). Store them in environment variables, never in source code.
    bash
    WOOCOMMERCE_URL=https://mystore.com
    WOOCOMMERCE_CONSUMER_KEY=ck_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
    WOOCOMMERCE_CONSUMER_SECRET=cs_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
  2. Set up the Node.js client
    bash
    npm install @woocommerce/woocommerce-rest-api
    typescript
    // lib/woocommerce.ts
    import WooCommerceRestApi from "@woocommerce/woocommerce-rest-api";
    
    export const woo = new WooCommerceRestApi({
      url: process.env.WOOCOMMERCE_URL!,
      consumerKey: process.env.WOOCOMMERCE_CONSUMER_KEY!,
      consumerSecret: process.env.WOOCOMMERCE_CONSUMER_SECRET!,
      version: "wc/v3",
      axiosConfig: {
        timeout: 15000,
      },
    });
  3. Query products with filtering and pagination
    typescript
    // lib/products.ts
    interface ProductQuery {
      page?: number;
      perPage?: number;
      category?: number;
      status?: "publish" | "draft" | "private";
      stockStatus?: "instock" | "outofstock" | "onbackorder";
      orderby?: "date" | "popularity" | "price" | "title";
    }
    
    export async function getProducts(params: ProductQuery = {}) {
      const response = await woo.get("products", {
        page: params.page ?? 1,
        per_page: params.perPage ?? 20,
        status: params.status ?? "publish",
        stock_status: params.stockStatus,
        orderby: params.orderby ?? "date",
        category: params.category,
      });
    
      return {
        products: response.data,
        totalPages: parseInt(response.headers["x-wp-totalpages"]),
        totalProducts: parseInt(response.headers["x-wp-total"]),
      };
    }
    
    export async function getProductById(id: number) {
      const response = await woo.get(`products/${id}`);
      return response.data;
    }
    
    // Get product variations
    export async function getProductVariations(productId: number) {
      const response = await woo.get(`products/${productId}/variations`, {
        per_page: 100,
      });
      return response.data;
    }
  4. Create and manage orders
    typescript
    // lib/orders.ts
    interface OrderLineItem {
      product_id: number;
      variation_id?: number;
      quantity: number;
    }
    
    interface CreateOrderParams {
      billing: {
        first_name: string;
        last_name: string;
        email: string;
        address_1: string;
        city: string;
        postcode: string;
        country: string;
      };
      line_items: OrderLineItem[];
      payment_method?: string;
    }
    
    export async function createOrder(params: CreateOrderParams) {
      const response = await woo.post("orders", {
        ...params,
        status: "pending",
        payment_method: params.payment_method ?? "stripe",
        payment_method_title: "Credit Card",
        set_paid: false,
      });
      return response.data;
    }
    
    export async function updateOrderStatus(
      orderId: number,
      status: "pending" | "processing" | "on-hold" | "completed" | "cancelled" | "refunded",
      note?: string
    ) {
      const updateData: any = { status };
      if (note) {
        // Add an order note
        await woo.post(`orders/${orderId}/notes`, { note });
      }
      const response = await woo.put(`orders/${orderId}`, updateData);
      return response.data;
    }
    
    export async function getOrders(params: {
      status?: string;
      after?: string; // ISO 8601 date
      page?: number;
    } = {}) {
      const response = await woo.get("orders", {
        status: params.status ?? "processing",
        after: params.after,
        per_page: 50,
        page: params.page ?? 1,
      });
      return {
        orders: response.data,
        totalPages: parseInt(response.headers["x-wp-totalpages"]),
      };
    }
  5. Manage inventory and product updates
    typescript
    // Update stock quantity for a product or variation
    export async function updateStock(productId: number, quantity: number, variationId?: number) {
      const endpoint = variationId
        ? `products/${productId}/variations/${variationId}`
        : `products/${productId}`;
    
      const response = await woo.put(endpoint, {
        stock_quantity: quantity,
        manage_stock: true,
      });
      return response.data;
    }
    
    // Batch update products (up to 100 per request)
    export async function batchUpdateProducts(
      updates: Array<{ id: number; regular_price?: string; stock_quantity?: number; status?: string }>
    ) {
      const response = await woo.post("products/batch", { update: updates });
      return response.data;
    }
  1. 生成API凭证
    在 WordPress 后台 → WooCommerce → 设置 → 高级 → REST API → 添加密钥:
    • 描述:
      My Integration
    • 用户:(管理员用户)
    • 权限:读/写
    这会生成一个消费者密钥(
    ck_xxx
    )和消费者密钥密码(
    cs_xxx
    )。请将它们存储在环境变量中,绝对不要存放在源代码里。
    bash
    WOOCOMMERCE_URL=https://mystore.com
    WOOCOMMERCE_CONSUMER_KEY=ck_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
    WOOCOMMERCE_CONSUMER_SECRET=cs_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
  2. 设置Node.js客户端
    bash
    npm install @woocommerce/woocommerce-rest-api
    typescript
    // lib/woocommerce.ts
    import WooCommerceRestApi from "@woocommerce/woocommerce-rest-api";
    
    export const woo = new WooCommerceRestApi({
      url: process.env.WOOCOMMERCE_URL!,
      consumerKey: process.env.WOOCOMMERCE_CONSUMER_KEY!,
      consumerSecret: process.env.WOOCOMMERCE_CONSUMER_SECRET!,
      version: "wc/v3",
      axiosConfig: {
        timeout: 15000,
      },
    });
  3. 带筛选和分页的产品查询
    typescript
    // lib/products.ts
    interface ProductQuery {
      page?: number;
      perPage?: number;
      category?: number;
      status?: "publish" | "draft" | "private";
      stockStatus?: "instock" | "outofstock" | "onbackorder";
      orderby?: "date" | "popularity" | "price" | "title";
    }
    
    export async function getProducts(params: ProductQuery = {}) {
      const response = await woo.get("products", {
        page: params.page ?? 1,
        per_page: params.perPage ?? 20,
        status: params.status ?? "publish",
        stock_status: params.stockStatus,
        orderby: params.orderby ?? "date",
        category: params.category,
      });
    
      return {
        products: response.data,
        totalPages: parseInt(response.headers["x-wp-totalpages"]),
        totalProducts: parseInt(response.headers["x-wp-total"]),
      };
    }
    
    export async function getProductById(id: number) {
      const response = await woo.get(`products/${id}`);
      return response.data;
    }
    
    // 获取产品变体
    export async function getProductVariations(productId: number) {
      const response = await woo.get(`products/${productId}/variations`, {
        per_page: 100,
      });
      return response.data;
    }
  4. 创建和管理订单
    typescript
    // lib/orders.ts
    interface OrderLineItem {
      product_id: number;
      variation_id?: number;
      quantity: number;
    }
    
    interface CreateOrderParams {
      billing: {
        first_name: string;
        last_name: string;
        email: string;
        address_1: string;
        city: string;
        postcode: string;
        country: string;
      };
      line_items: OrderLineItem[];
      payment_method?: string;
    }
    
    export async function createOrder(params: CreateOrderParams) {
      const response = await woo.post("orders", {
        ...params,
        status: "pending",
        payment_method: params.payment_method ?? "stripe",
        payment_method_title: "Credit Card",
        set_paid: false,
      });
      return response.data;
    }
    
    export async function updateOrderStatus(
      orderId: number,
      status: "pending" | "processing" | "on-hold" | "completed" | "cancelled" | "refunded",
      note?: string
    ) {
      const updateData: any = { status };
      if (note) {
        // 添加订单备注
        await woo.post(`orders/${orderId}/notes`, { note });
      }
      const response = await woo.put(`orders/${orderId}`, updateData);
      return response.data;
    }
    
    export async function getOrders(params: {
      status?: string;
      after?: string; // ISO 8601 日期格式
      page?: number;
    } = {}) {
      const response = await woo.get("orders", {
        status: params.status ?? "processing",
        after: params.after,
        per_page: 50,
        page: params.page ?? 1,
      });
      return {
        orders: response.data,
        totalPages: parseInt(response.headers["x-wp-totalpages"]),
      };
    }
  5. 库存和产品更新管理
    typescript
    // 更新产品或变体的库存数量
    export async function updateStock(productId: number, quantity: number, variationId?: number) {
      const endpoint = variationId
        ? `products/${productId}/variations/${variationId}`
        : `products/${productId}`;
    
      const response = await woo.put(endpoint, {
        stock_quantity: quantity,
        manage_stock: true,
      });
      return response.data;
    }
    
    // 批量更新产品(每次请求最多100个)
    export async function batchUpdateProducts(
      updates: Array<{ id: number; regular_price?: string; stock_quantity?: number; status?: string }>
    ) {
      const response = await woo.post("products/batch", { update: updates });
      return response.data;
    }

Examples

示例

Full product sync from external catalog

从外部目录完整同步产品

typescript
import pLimit from "p-limit";

export async function syncProductsFromCatalog(
  externalProducts: Array<{ sku: string; price: number; stock: number }>
) {
  const limit = pLimit(5); // Max 5 concurrent API calls

  const results = await Promise.allSettled(
    externalProducts.map((ext) =>
      limit(async () => {
        // Look up WooCommerce product by SKU
        const searchResponse = await woo.get("products", { sku: ext.sku });
        const existing = searchResponse.data[0];

        if (existing) {
          // Update existing product
          return woo.put(`products/${existing.id}`, {
            regular_price: ext.price.toFixed(2),
            stock_quantity: ext.stock,
            manage_stock: true,
          });
        } else {
          console.warn(`SKU not found in WooCommerce: ${ext.sku}`);
          return null;
        }
      })
    )
  );

  const failed = results.filter((r) => r.status === "rejected");
  if (failed.length > 0) {
    console.error(`${failed.length} products failed to sync`);
  }

  return results;
}
typescript
import pLimit from "p-limit";

export async function syncProductsFromCatalog(
  externalProducts: Array<{ sku: string; price: number; stock: number }>
) {
  const limit = pLimit(5); // 最多5个并发API调用

  const results = await Promise.allSettled(
    externalProducts.map((ext) =>
      limit(async () => {
        // 通过SKU查找WooCommerce产品
        const searchResponse = await woo.get("products", { sku: ext.sku });
        const existing = searchResponse.data[0];

        if (existing) {
          // 更新现有产品
          return woo.put(`products/${existing.id}`, {
            regular_price: ext.price.toFixed(2),
            stock_quantity: ext.stock,
            manage_stock: true,
          });
        } else {
          console.warn(`WooCommerce中未找到SKU:${ext.sku}`);
          return null;
        }
      })
    )
  );

  const failed = results.filter((r) => r.status === "rejected");
  if (failed.length > 0) {
    console.error(`${failed.length}个产品同步失败`);
  }

  return results;
}

Customer management

客户管理

typescript
// Create or update customer
export async function upsertCustomer(email: string, data: Record<string, any>) {
  const searchResponse = await woo.get("customers", { email });
  const existing = searchResponse.data[0];

  if (existing) {
    const response = await woo.put(`customers/${existing.id}`, data);
    return response.data;
  } else {
    const response = await woo.post("customers", { email, ...data });
    return response.data;
  }
}

// Get customer order history
export async function getCustomerOrders(customerId: number) {
  const response = await woo.get("orders", {
    customer: customerId,
    per_page: 50,
    orderby: "date",
    order: "desc",
  });
  return response.data;
}
typescript
// 创建或更新客户
export async function upsertCustomer(email: string, data: Record<string, any>) {
  const searchResponse = await woo.get("customers", { email });
  const existing = searchResponse.data[0];

  if (existing) {
    const response = await woo.put(`customers/${existing.id}`, data);
    return response.data;
  } else {
    const response = await woo.post("customers", { email, ...data });
    return response.data;
  }
}

// 获取客户订单历史
export async function getCustomerOrders(customerId: number) {
  const response = await woo.get("orders", {
    customer: customerId,
    per_page: 50,
    orderby: "date",
    order: "desc",
  });
  return response.data;
}

Best Practices

最佳实践

  • Always use HTTPS — OAuth 1.0a works over HTTP but transmits credentials with every request; HTTPS + Basic Auth is simpler and safer for server-to-server calls
  • Respect rate limits — WordPress doesn't enforce API rate limits by default, but high request volumes can cause PHP-FPM or MySQL exhaustion; use
    p-limit
    or a queue for bulk operations
  • Use batch endpoints for bulk updates
    /products/batch
    accepts up to 100 create/update/delete operations in one request vs. 100 individual requests
  • Filter fields with
    _fields
    parameter
    ?_fields=id,name,price,stock_quantity
    reduces response payload significantly for large product lists
  • Handle WooCommerce-specific error codes — the API returns
    rest_invalid_param
    ,
    woocommerce_rest_cannot_create
    , etc. in the error body; parse
    response.data.code
    for specific error handling
  • Use
    after
    and
    before
    date filters
    for incremental syncs — avoid full catalog re-scans by filtering orders/products modified since last sync using ISO 8601 timestamps
  • Store the API URL without trailing slash — the WooCommerce client handles URL construction; a trailing slash in the base URL causes double-slash in endpoints
  • 始终使用HTTPS — OAuth 1.0a可在HTTP环境下使用,但每次请求都会传输凭证;对于服务器到服务器的调用,HTTPS + Basic Auth更简单安全
  • 遵守速率限制 — WordPress默认不强制API速率限制,但高请求量会导致PHP-FPM或MySQL资源耗尽;批量操作时使用
    p-limit
    或队列
  • 使用批量端点进行批量更新
    /products/batch
    支持在一个请求中处理最多100个创建/更新/删除操作,替代100次单独请求
  • 使用
    _fields
    参数筛选字段
    ?_fields=id,name,price,stock_quantity
    可大幅减少大型产品列表的响应数据量
  • 处理WooCommerce特定错误码 — API会在错误体中返回
    rest_invalid_param
    woocommerce_rest_cannot_create
    等错误码;解析
    response.data.code
    进行针对性错误处理
  • 使用
    after
    before
    日期筛选器进行增量同步
    — 使用ISO 8601时间戳筛选自上次同步以来修改的订单/产品,避免全目录重新扫描
  • 存储不带末尾斜杠的API URL — WooCommerce客户端会处理URL构建;基础URL中的末尾斜杠会导致端点出现双斜杠

Common Pitfalls

常见问题

ProblemSolution
401 Unauthorized
despite correct keys
Verify the site uses HTTPS; over HTTP the client must use OAuth 1.0a, not Basic Auth — set
isHttps: false
in the client config
Products endpoint returns empty arrayCheck the user assigned to the API key has the correct capabilities; the default
woocommerce_manage_products
capability is required
Order creation fails with product ID errorVariable products require
variation_id
in
line_items
; passing only
product_id
for a variable product causes
invalid_variation
error
Pagination headers missingThe
x-wp-total
and
x-wp-totalpages
headers are only present on list endpoints, not single-resource endpoints
Batch operation partially failsBatch responses include individual errors per item; iterate
response.data.update
array and check each item for
error
property
Slow response on product listingAdd
?_fields=id,name,price
to reduce payload; also consider enabling persistent object cache (Redis) on the WordPress server
问题解决方案
密钥正确但返回
401 Unauthorized
验证网站是否使用HTTPS;在HTTP环境下客户端必须使用OAuth 1.0a而非Basic Auth — 在客户端配置中设置
isHttps: false
产品端点返回空数组检查API密钥关联的用户是否拥有正确权限;默认需要
woocommerce_manage_products
权限
创建订单时因产品ID报错可变产品需要在
line_items
中传入
variation_id
;仅传入
product_id
会导致
invalid_variation
错误
缺少分页头信息
x-wp-total
x-wp-totalpages
头信息仅在列表端点存在,单资源端点不会返回
批量操作部分失败批量响应包含每个项目的单独错误;遍历
response.data.update
数组并检查每个项目的
error
属性
产品列表响应缓慢添加
?_fields=id,name,price
减少数据量;同时考虑在WordPress服务器上启用持久对象缓存(如Redis)

Related Skills

相关技能

  • @woocommerce-plugin-development
  • @woocommerce-subscriptions
  • @woocommerce-performance
  • @headless-commerce-architecture
  • @rest-api-design
  • @woocommerce-plugin-development
  • @woocommerce-subscriptions
  • @woocommerce-performance
  • @headless-commerce-architecture
  • @rest-api-design