woocommerce-rest-api について
WooCommerce の REST API を使った連携開発向けのスキルガイドです。Node.js クライアントによる認証、商品や注文の操作、在庫更新、同期の実践方法を扱います。
主な機能
- 01商品、注文、顧客、設定へのアクセス
- 02Node.js クライアントでの認証
- 03商品検索の絞り込みとページ分割
- 04注文作成と在庫更新
- 05一括・差分同期の指針
活用シーン
- 01ヘッドレスストアやモバイルアプリの構築
- 02WooCommerce と ERP、CRM、フルフィルメントシステムの連携
- 03倉庫や POS の在庫同期
- 04商品一括登録や価格更新
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ finsilabs/ awesome-ecommerce-skills --skill woocommerce-rest-apiインストール後、Claude Code で/woocommerce-rest-apiを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
tile.jsonevals/bulk-product-sync-with-concurrency-contr/criteria.jsontask.mdevals/order-creation-and-status-management-wit/criteria.jsontask.mdevals/paginated-product-catalog-with-increment/criteria.jsontask.md詳細
WooCommerce REST API
概要
WooCommerce には、商品、注文、顧客、クーポン、ストア設定を HTTPS 経由で公開する、バージョン管理された REST API(/wp-json/wc/v3/)が用意されています。HTTPS 環境以外では OAuth 1.0a を使用し、HTTPS 経由では Basic Auth(コンシューマーキー/シークレット)を使用します。公式の @woocommerce/woocommerce-rest-api Node.js クライアントは認証を自動的に処理し、CRUD のすべての操作に対応しています。
このスキルを使用する場面
- WooCommerce から商品やカテゴリーを読み取るヘッドレスストアフロントを構築するとき
- WooCommerce を ERP、CRM、またはフルフィルメントシステムと連携するとき
- WordPress Admin の外部で注文管理ダッシュボードを作成するとき
- WooCommerce と倉庫または POS システム間で在庫を同期するとき
- 外部カタログからの商品一括インポートや価格更新を自動化するとき
- WooCommerce ストアのデータにアクセスする必要があるモバイルアプリを構築するとき
主な手順
-
API 認証情報を生成する
WordPress Admin → WooCommerce → Settings → Advanced → REST API → Add Key の順に移動します。
- Description:
My Integration - User:(管理者ユーザー)
- Permissions:Read/Write
コンシューマーキー(
ck_xxx)とコンシューマーシークレット(cs_xxx)が生成されます。これらは環境変数に保存し、ソースコードには決して記載しないでください。WOOCOMMERCE_URL=https://mystore.com WOOCOMMERCE_CONSUMER_KEY=ck_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx WOOCOMMERCE_CONSUMER_SECRET=cs_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx - Description:
-
Node.js クライアントをセットアップする
npm install @woocommerce/woocommerce-rest-api// 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, }, }); -
フィルタリングとページネーションを使用して商品をクエリする
// 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; } -
注文を作成、管理する
// 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"]), }; } -
在庫と商品情報を管理する
// 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; }
使用例
外部カタログから商品をすべて同期する
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;
}
顧客管理
// 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;
}
ベストプラクティス
- 常に HTTPS を使用する — OAuth 1.0a は HTTP 経由でも動作しますが、リクエストごとに認証情報が送信されます。サーバー間通信には、HTTPS と Basic Auth の組み合わせがよりシンプルで安全です
- レート制限を考慮する — WordPress はデフォルトでは API のレート制限を適用しませんが、リクエスト量が多いと PHP-FPM や MySQL が枯渇する可能性があります。一括処理には
p-limitまたはキューを使用してください - 一括更新にはバッチエンドポイントを使用する —
/products/batchは、個別に 100 件リクエストする代わりに、1 回のリクエストで最大 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 の末尾にスラッシュがあると、エンドポイントにスラッシュが重複します
よくある問題
| 問題 | 解決策 |
|---|---|
キーが正しいのに 401 Unauthorized が発生する | サイトで HTTPS が使用されていることを確認してください。HTTP 経由ではクライアントは Basic Auth ではなく OAuth 1.0a を使用する必要があります。クライアント設定で 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
コメント
Markdown 対応