Smithery Logo
MCPsSkillsDocsPricing
Login
Smithery Logo

Accelerating the Agent Economy

Resources

DocumentationPrivacy PolicySystem Status

Company

PricingAboutBlog

Connect

© 2026 Smithery. All rights reserved.

    alinaqi

    woocommerce

    alinaqi/woocommerce
    Coding
    467
    3 installs

    About

    SKILL.md

    Install

    Install via Skills CLI

    or add to your agent
    • Claude Code
      Claude Code
    • Codex
      Codex
    • OpenClaw
      OpenClaw
    • Cursor
      Cursor
    • Amp
      Amp
    • GitHub Copilot
      GitHub Copilot
    • Gemini CLI
      Gemini CLI
    • Kilo Code
      Kilo Code
    • Junie
      Junie
    • Replit
      Replit
    • Windsurf
      Windsurf
    • Cline
      Cline
    • Continue
      Continue
    • OpenCode
      OpenCode
    • OpenHands
      OpenHands
    • Roo Code
      Roo Code
    • Augment
      Augment
    • Goose
      Goose
    • Trae
      Trae
    • Zencoder
      Zencoder
    • Antigravity
      Antigravity
    ├─
    ├─
    └─

    About

    WooCommerce REST API - products, orders, customers, webhooks

    SKILL.md

    WooCommerce Development Skill

    For integrating with WooCommerce stores via REST API - products, orders, customers, webhooks, and custom extensions.

    Sources: WooCommerce REST API | Developer Docs


    Prerequisites

    Store Requirements

    # WooCommerce store must have:
    # 1. WordPress with WooCommerce plugin installed
    # 2. HTTPS enabled (required for API auth)
    # 3. Permalinks set to anything except "Plain"
    #    WordPress Admin → Settings → Permalinks → Post name (recommended)
    

    Generate API Keys

    1. Go to WooCommerce → Settings → Advanced → REST API
    2. Click Add key
    3. Set Description, User (admin), and Permissions (Read/Write)
    4. Click Generate API key
    5. Copy Consumer Key and Consumer Secret (shown only once)

    API Basics

    Base URL

    https://your-store.com/wp-json/wc/v3/
    

    Authentication

    // Node.js - Basic Auth (recommended)
    const WooCommerceRestApi = require("@woocommerce/woocommerce-rest-api").default;
    
    const api = new WooCommerceRestApi({
      url: "https://your-store.com",
      consumerKey: process.env.WC_CONSUMER_KEY,
      consumerSecret: process.env.WC_CONSUMER_SECRET,
      version: "wc/v3"
    });
    
    # Python
    from woocommerce import API
    
    wcapi = API(
        url="https://your-store.com",
        consumer_key=os.environ["WC_CONSUMER_KEY"],
        consumer_secret=os.environ["WC_CONSUMER_SECRET"],
        version="wc/v3"
    )
    

    Query String Auth (Fallback)

    # Only use if Basic Auth fails (some hosting configurations)
    curl https://your-store.com/wp-json/wc/v3/products \
      ?consumer_key=ck_xxx&consumer_secret=cs_xxx
    

    Installation

    Node.js

    npm install @woocommerce/woocommerce-rest-api
    
    // lib/woocommerce.ts
    import WooCommerceRestApi from "@woocommerce/woocommerce-rest-api";
    
    const api = new WooCommerceRestApi({
      url: process.env.WC_STORE_URL!,
      consumerKey: process.env.WC_CONSUMER_KEY!,
      consumerSecret: process.env.WC_CONSUMER_SECRET!,
      version: "wc/v3",
      queryStringAuth: false, // Set true for HTTP (dev only)
    });
    
    export default api;
    

    Python

    pip install woocommerce
    
    # lib/woocommerce.py
    import os
    from woocommerce import API
    
    wcapi = API(
        url=os.environ["WC_STORE_URL"],
        consumer_key=os.environ["WC_CONSUMER_KEY"],
        consumer_secret=os.environ["WC_CONSUMER_SECRET"],
        version="wc/v3",
        timeout=30
    )
    

    Products

    List Products

    // Node.js
    async function getProducts(page = 1, perPage = 20) {
      const response = await api.get("products", {
        page,
        per_page: perPage,
        status: "publish",
      });
      return response.data;
    }
    
    // With filters
    async function searchProducts(search: string, category?: number) {
      const response = await api.get("products", {
        search,
        category: category || undefined,
        orderby: "popularity",
        order: "desc",
      });
      return response.data;
    }
    
    # Python
    def get_products(page=1, per_page=20):
        response = wcapi.get("products", params={
            "page": page,
            "per_page": per_page,
            "status": "publish"
        })
        return response.json()
    

    Get Single Product

    async function getProduct(productId: number) {
      const response = await api.get(`products/${productId}`);
      return response.data;
    }
    

    Create Product

    async function createProduct(data: ProductInput) {
      const response = await api.post("products", {
        name: data.name,
        type: "simple", // simple, variable, grouped, external
        regular_price: data.price.toString(),
        description: data.description,
        short_description: data.shortDescription,
        categories: data.categoryIds.map(id => ({ id })),
        images: data.images.map(url => ({ src: url })),
        manage_stock: true,
        stock_quantity: data.stockQuantity,
        status: "publish",
      });
      return response.data;
    }
    

    Update Product

    async function updateProduct(productId: number, data: Partial<ProductInput>) {
      const response = await api.put(`products/${productId}`, data);
      return response.data;
    }
    
    // Update stock only
    async function updateStock(productId: number, quantity: number) {
      const response = await api.put(`products/${productId}`, {
        stock_quantity: quantity,
      });
      return response.data;
    }
    

    Delete Product

    async function deleteProduct(productId: number, force = false) {
      // force: true = permanent delete, false = move to trash
      const response = await api.delete(`products/${productId}`, {
        force,
      });
      return response.data;
    }
    

    Variable Products

    // Create variable product
    async function createVariableProduct(data: VariableProductInput) {
      // 1. Create product with type "variable"
      const product = await api.post("products", {
        name: data.name,
        type: "variable",
        attributes: [
          {
            name: "Size",
            visible: true,
            variation: true,
            options: ["Small", "Medium", "Large"],
          },
          {
            name: "Color",
            visible: true,
            variation: true,
            options: ["Red", "Blue"],
          },
        ],
      });
    
      // 2. Create variations
      for (const variant of data.variants) {
        await api.post(`products/${product.data.id}/variations`, {
          regular_price: variant.price.toString(),
          stock_quantity: variant.stock,
          attributes: [
            { name: "Size", option: variant.size },
            { name: "Color", option: variant.color },
          ],
        });
      }
    
      return product.data;
    }
    
    // Get variations
    async function getVariations(productId: number) {
      const response = await api.get(`products/${productId}/variations`);
      return response.data;
    }
    

    Orders

    List Orders

    async function getOrders(params: OrderQueryParams = {}) {
      const response = await api.get("orders", {
        page: params.page || 1,
        per_page: params.perPage || 20,
        status: params.status || "any", // pending, processing, completed, etc.
        after: params.after, // ISO date string
        before: params.before,
      });
      return response.data;
    }
    
    // Get recent orders
    async function getRecentOrders(days = 7) {
      const after = new Date();
      after.setDate(after.getDate() - days);
    
      const response = await api.get("orders", {
        after: after.toISOString(),
        orderby: "date",
        order: "desc",
      });
      return response.data;
    }
    

    Get Single Order

    async function getOrder(orderId: number) {
      const response = await api.get(`orders/${orderId}`);
      return response.data;
    }
    

    Create Order

    async function createOrder(data: OrderInput) {
      const response = await api.post("orders", {
        payment_method: "stripe",
        payment_method_title: "Credit Card",
        set_paid: false,
        billing: {
          first_name: data.customer.firstName,
          last_name: data.customer.lastName,
          email: data.customer.email,
          phone: data.customer.phone,
          address_1: data.billing.address1,
          city: data.billing.city,
          state: data.billing.state,
          postcode: data.billing.postcode,
          country: data.billing.country,
        },
        shipping: {
          first_name: data.customer.firstName,
          last_name: data.customer.lastName,
          address_1: data.shipping.address1,
          city: data.shipping.city,
          state: data.shipping.state,
          postcode: data.shipping.postcode,
          country: data.shipping.country,
        },
        line_items: data.items.map(item => ({
          product_id: item.productId,
          variation_id: item.variationId,
          quantity: item.quantity,
        })),
        shipping_lines: [
          {
            method_id: "flat_rate",
            method_title: "Flat Rate",
            total: data.shippingCost.toString(),
          },
        ],
      });
      return response.data;
    }
    

    Update Order Status

    async function updateOrderStatus(orderId: number, status: OrderStatus) {
      const response = await api.put(`orders/${orderId}`, {
        status, // pending, processing, on-hold, completed, cancelled, refunded, failed
      });
      return response.data;
    }
    
    // Add order note
    async function addOrderNote(orderId: number, note: string, customerNote = false) {
      const response = await api.post(`orders/${orderId}/notes`, {
        note,
        customer_note: customerNote, // true = visible to customer
      });
      return response.data;
    }
    

    Order Statuses

    Status Description
    pending Awaiting payment
    processing Payment received, awaiting fulfillment
    on-hold Awaiting action (stock, payment confirmation)
    completed Order fulfilled
    cancelled Cancelled by admin or customer
    refunded Refunded
    failed Payment failed

    Customers

    List Customers

    async function getCustomers(params: CustomerQueryParams = {}) {
      const response = await api.get("customers", {
        page: params.page || 1,
        per_page: params.perPage || 20,
        role: "customer",
        orderby: "registered_date",
        order: "desc",
      });
      return response.data;
    }
    
    // Search customers
    async function searchCustomers(email: string) {
      const response = await api.get("customers", {
        email,
      });
      return response.data;
    }
    

    Create Customer

    async function createCustomer(data: CustomerInput) {
      const response = await api.post("customers", {
        email: data.email,
        first_name: data.firstName,
        last_name: data.lastName,
        username: data.email.split("@")[0],
        billing: {
          first_name: data.firstName,
          last_name: data.lastName,
          email: data.email,
          phone: data.phone,
          address_1: data.address1,
          city: data.city,
          state: data.state,
          postcode: data.postcode,
          country: data.country,
        },
        shipping: {
          // Same as billing or different
        },
      });
      return response.data;
    }
    

    Update Customer

    async function updateCustomer(customerId: number, data: Partial<CustomerInput>) {
      const response = await api.put(`customers/${customerId}`, data);
      return response.data;
    }
    

    Webhooks

    Create Webhook

    async function createWebhook(topic: string, deliveryUrl: string) {
      const response = await api.post("webhooks", {
        name: `Webhook for ${topic}`,
        topic, // order.created, order.updated, product.created, etc.
        delivery_url: deliveryUrl,
        status: "active",
        secret: process.env.WC_WEBHOOK_SECRET,
      });
      return response.data;
    }
    

    Webhook Topics

    Topic Trigger
    order.created New order placed
    order.updated Order status/details changed
    order.deleted Order deleted
    product.created New product created
    product.updated Product updated
    product.deleted Product deleted
    customer.created New customer registered
    customer.updated Customer updated
    coupon.created New coupon created

    Verify Webhook Signature

    // Express.js webhook handler
    import crypto from "crypto";
    
    function verifyWooCommerceWebhook(req: Request): boolean {
      const signature = req.headers["x-wc-webhook-signature"] as string;
      const payload = JSON.stringify(req.body);
    
      const expectedSignature = crypto
        .createHmac("sha256", process.env.WC_WEBHOOK_SECRET!)
        .update(payload)
        .digest("base64");
    
      return crypto.timingSafeEqual(
        Buffer.from(signature),
        Buffer.from(expectedSignature)
      );
    }
    
    // Route handler
    app.post("/webhooks/woocommerce", (req, res) => {
      if (!verifyWooCommerceWebhook(req)) {
        return res.status(401).json({ error: "Invalid signature" });
      }
    
      const topic = req.headers["x-wc-webhook-topic"];
      const payload = req.body;
    
      switch (topic) {
        case "order.created":
          handleNewOrder(payload);
          break;
        case "order.updated":
          handleOrderUpdate(payload);
          break;
        // ... other topics
      }
    
      res.status(200).json({ received: true });
    });
    
    # Python/Flask webhook handler
    import hmac
    import hashlib
    import base64
    
    @app.route("/webhooks/woocommerce", methods=["POST"])
    def woocommerce_webhook():
        signature = request.headers.get("X-WC-Webhook-Signature")
        payload = request.get_data()
    
        expected = base64.b64encode(
            hmac.new(
                os.environ["WC_WEBHOOK_SECRET"].encode(),
                payload,
                hashlib.sha256
            ).digest()
        ).decode()
    
        if not hmac.compare_digest(signature, expected):
            return {"error": "Invalid signature"}, 401
    
        topic = request.headers.get("X-WC-Webhook-Topic")
        data = request.json
    
        if topic == "order.created":
            handle_new_order(data)
        elif topic == "order.updated":
            handle_order_update(data)
    
        return {"received": True}, 200
    

    Categories & Tags

    List Categories

    async function getCategories() {
      const response = await api.get("products/categories", {
        per_page: 100,
        orderby: "name",
      });
      return response.data;
    }
    
    // Create category
    async function createCategory(name: string, parentId?: number) {
      const response = await api.post("products/categories", {
        name,
        parent: parentId || 0,
      });
      return response.data;
    }
    

    List Tags

    async function getTags() {
      const response = await api.get("products/tags", {
        per_page: 100,
      });
      return response.data;
    }
    

    Coupons

    Create Coupon

    async function createCoupon(data: CouponInput) {
      const response = await api.post("coupons", {
        code: data.code,
        discount_type: data.type, // percent, fixed_cart, fixed_product
        amount: data.amount.toString(),
        individual_use: true,
        exclude_sale_items: false,
        minimum_amount: data.minimumAmount?.toString(),
        maximum_amount: data.maximumAmount?.toString(),
        usage_limit: data.usageLimit,
        usage_limit_per_user: 1,
        date_expires: data.expiresAt, // ISO date string
      });
      return response.data;
    }
    

    Reports

    Sales Report

    async function getSalesReport(period = "month") {
      const response = await api.get("reports/sales", {
        period, // day, week, month, year
      });
      return response.data;
    }
    
    // Top sellers
    async function getTopSellers(period = "month") {
      const response = await api.get("reports/top_sellers", {
        period,
      });
      return response.data;
    }
    

    Pagination

    Handle Large Datasets

    async function getAllProducts() {
      const allProducts = [];
      let page = 1;
      const perPage = 100;
    
      while (true) {
        const response = await api.get("products", {
          page,
          per_page: perPage,
        });
    
        allProducts.push(...response.data);
    
        // Check headers for total pages
        const totalPages = parseInt(response.headers["x-wp-totalpages"]);
        if (page >= totalPages) break;
    
        page++;
      }
    
      return allProducts;
    }
    

    Pagination Headers

    Header Description
    X-WP-Total Total number of items
    X-WP-TotalPages Total number of pages

    Error Handling

    import WooCommerceRestApi from "@woocommerce/woocommerce-rest-api";
    
    async function safeApiCall<T>(
      operation: () => Promise<{ data: T }>
    ): Promise<T> {
      try {
        const response = await operation();
        return response.data;
      } catch (error: any) {
        if (error.response) {
          // API returned an error
          const { status, data } = error.response;
    
          switch (status) {
            case 400:
              throw new Error(`Bad request: ${data.message}`);
            case 401:
              throw new Error("Invalid API credentials");
            case 404:
              throw new Error("Resource not found");
            case 429:
              // Rate limited - wait and retry
              await new Promise(r => setTimeout(r, 5000));
              return safeApiCall(operation);
            default:
              throw new Error(`API error: ${data.message}`);
          }
        }
        throw error;
      }
    }
    
    // Usage
    const products = await safeApiCall(() => api.get("products"));
    

    Environment Variables

    # .env
    WC_STORE_URL=https://your-store.com
    WC_CONSUMER_KEY=ck_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
    WC_CONSUMER_SECRET=cs_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
    WC_WEBHOOK_SECRET=your_webhook_secret
    

    Add to credentials.md:

    'WC_CONSUMER_KEY': r'ck_[a-f0-9]{40}',
    'WC_CONSUMER_SECRET': r'cs_[a-f0-9]{40}',
    

    Checklist

    Before Integration

    • WooCommerce plugin installed and activated
    • HTTPS enabled on store
    • Permalinks set to non-Plain setting
    • API keys generated with appropriate permissions
    • Webhook secret configured

    Security

    • API keys stored in environment variables
    • Webhook signatures verified
    • HTTPS used for all API calls
    • Rate limiting handled

    Testing

    • Test API connection
    • Test product CRUD operations
    • Test order creation/updates
    • Test webhook delivery
    • Test pagination for large datasets

    Anti-Patterns

    • Plain permalinks - API won't work without pretty permalinks
    • HTTP in production - Always use HTTPS
    • Ignoring rate limits - WooCommerce may throttle requests
    • Large single requests - Use pagination for bulk operations
    • Storing keys in code - Use environment variables
    • Skipping webhook verification - Always verify signatures
    Recommended Servers
    Correkt Commerce
    Correkt Commerce
    Repository
    alinaqi/claude-bootstrap
    Files