PHPackages                             baldie81/woocommerce-sdk - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [HTTP &amp; Networking](/categories/http)
4. /
5. baldie81/woocommerce-sdk

ActiveLibrary[HTTP &amp; Networking](/categories/http)

baldie81/woocommerce-sdk
========================

Framework-independent PHP SDK for the WooCommerce REST API (v3): products, variations, categories, attributes, orders, customers, coupons, tax, shipping, webhooks, settings and the batch API.

v1.0.0(today)00MITPHPPHP ^8.1CI passing

Since Jun 30Pushed todayCompare

[ Source](https://github.com/baldie81/woocommerce-sdk)[ Packagist](https://packagist.org/packages/baldie81/woocommerce-sdk)[ RSS](/packages/baldie81-woocommerce-sdk/feed)WikiDiscussions main Synced today

READMEChangelog (1)Dependencies (2)Versions (2)Used By (0)

WooCommerce PHP SDK
===================

[](#woocommerce-php-sdk)

A small, **framework-independent** PHP client for the WooCommerce REST API (v3). No WordPress/Laravel/Symfony coupling — just PHP 8.1+ and Guzzle. It wraps the endpoints you actually reach for when integrating a store:

- **Products** — get / create / update / delete, list &amp; paginate, look up by SKU
- **Product variations** — the variations of a variable product
- **Product categories / tags / attributes** — full catalog taxonomy, attribute terms
- **Orders** — get / list, create, partial update, set status, notes &amp; refunds
- **Customers** — get / list, create / update (with inline addresses), look up by email
- **Coupons** — get / list, create / update, look up by code
- **Tax** — tax rates and tax classes
- **Shipping** — zones, their locations, and their methods
- **Webhooks** — register topic → delivery-URL hooks
- **Store config** — payment gateways, system status &amp; tools, settings
- **Batch API** — create/update/delete up to 100 per call, auto-chunked past that

It also gives you fluent value-object builders (`ProductInput`, `VariationInput`, `OrderInput`, `LineItem`, `Address`, `CustomerInput`, `CouponInput`, `CategoryInput`, `MetaData`, `BatchPayload`) that every write method accepts interchangeably with plain arrays, a fluent `Query` builder for list endpoints, typed enums (`ProductStatus`, `ProductType`, `CatalogVisibility`, `StockStatus`, `OrderStatus`, `DiscountType`), and a clean exception hierarchy instead of leaking Guzzle exceptions.

> Scope: this targets the **standard** WooCommerce core REST API (`wc/v3`). Endpoints added by extensions (subscriptions, bookings, …) are out of scope, though their custom fields pass straight through via `meta_data` and the `set()`escape hatches.

Install
-------

[](#install)

```
composer require baldie81/woocommerce-sdk
```

Quick start
-----------

[](#quick-start)

```
use Baldie81\WooCommerceSDK\Configuration;
use Baldie81\WooCommerceSDK\WooCommerceClient;

$woo = WooCommerceClient::create(new Configuration(
    baseUrl:        'https://shop.example.com',
    consumerKey:    'ck_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
    consumerSecret: 'cs_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
    // timeout: 30.0, connectTimeout: 10.0, verifySsl: true,
));

$product = $woo->products()->get(123);
```

Authentication
--------------

[](#authentication)

Create a **consumer key / consumer secret** pair under *WooCommerce → Settings → Advanced → REST API*. Over HTTPS the SDK sends them as HTTP Basic auth, which is all WooCommerce needs.

TLS verification is **on** by default; pass `verifySsl: false` only for local/self-signed environments.

For a non-SSL store (local dev), WooCommerce can't use Basic auth, so set `queryStringAuth: true` to send the credentials as query parameters instead. Don't do this over plain HTTP in production — it exposes the credentials in URLs and logs.

```
new Configuration(
    baseUrl:         'http://localhost:8080',
    consumerKey:     'ck_...',
    consumerSecret:  'cs_...',
    verifySsl:       false,
    queryStringAuth: true,
);
```

Value objects (or arrays)
-------------------------

[](#value-objects-or-arrays)

Every write method accepts **either** a fluent builder **or** a raw array, so you can opt into type-safety without giving up the array escape hatch. The builders all implement `Arrayable`:

```
use Baldie81\WooCommerceSDK\Support\ProductInput;
use Baldie81\WooCommerceSDK\Enum\ProductStatus;
use Baldie81\WooCommerceSDK\Enum\ProductType;

// Builder — a simple product with an image and a variation attribute:
$woo->products()->create(
    ProductInput::make()
        ->name('Example')->type(ProductType::Simple)->sku('SKU-123')
        ->regularPrice('19.90')->status(ProductStatus::Publish)
        ->manageStock(true)->stockQuantity(100)
        ->categories([15, 21])
        ->image('https://example.com/front.jpg', 'Front')
        ->meta('_origin', 'import')
);

// …or the exact same call with a raw array — accepted everywhere:
$woo->products()->create([
    'name'           => 'Example',
    'type'           => 'simple',
    'sku'            => 'SKU-123',
    'regular_price'  => '19.90',
    'status'         => 'publish',
    'manage_stock'   => true,
    'stock_quantity' => 100,
    'categories'     => [['id' => 15], ['id' => 21]],
]);
```

> Money is a **string** in WooCommerce. The builders' price setters accept a string or a number and stringify it for you (`->regularPrice(19.9)` → `"19.9"`).

A variable product carries its variations separately:

```
use Baldie81\WooCommerceSDK\Support\VariationInput;

$parent = $woo->products()->create(
    ProductInput::make()
        ->name('T-Shirt')->type(ProductType::Variable)
        ->attribute('Color', ['Red', 'Blue'], variation: true)
        ->attribute('Size', ['S', 'M', 'L'], variation: true)
);

$variations = $woo->products()->variations($parent['id']);
$variations->create(
    VariationInput::make()
        ->sku('TS-RED-M')->regularPrice('24.90')
        ->attribute('Color', 'Red')->attribute('Size', 'M')
        ->manageStock(true)->stockQuantity(10)
);
```

Orders
------

[](#orders)

```
use Baldie81\WooCommerceSDK\Support\OrderInput;
use Baldie81\WooCommerceSDK\Support\Address;
use Baldie81\WooCommerceSDK\Support\LineItem;
use Baldie81\WooCommerceSDK\Enum\OrderStatus;

$order = $woo->orders()->create(
    OrderInput::make()
        ->status(OrderStatus::Processing)->setPaid(true)
        ->paymentMethod('bacs', 'Direct bank transfer')
        ->billing(
            Address::make()->name('Jane', 'Doe')
                ->line1('1 High St')->city('London')->postcode('EC1A 1AA')->country('GB')
                ->email('jane@example.com')
        )
        ->lineItem(LineItem::make()->product(93)->quantity(2))
        ->shippingLine('flat_rate', 'Flat rate', '5.00')
        ->couponLine('SAVE10')
);

$woo->orders()->setStatus($order['id'], OrderStatus::Completed);

// Notes and refunds hang off an order id:
$woo->orders()->notes($order['id'])->create('Picked & packed', customerNote: false);
$woo->orders()->refunds($order['id'])->refundAmount('12.50', 'Damaged item');
```

Listing &amp; pagination
------------------------

[](#listing--pagination)

Build list queries with `Query`; `list()` returns one page, `all()` walks every page for you.

WooCommerce reports totals in the `X-WP-Total` / `X-WP-TotalPages` **response headers** (not the body) and caps `per_page` at 100. `all()` reads those headers and paginates until the last page, so you never silently truncate a large result set:

```
use Baldie81\WooCommerceSDK\Support\Query;
use Baldie81\WooCommerceSDK\Enum\ProductStatus;

// One page:
$page = $woo->products()->list(
    Query::create()->search('shirt')->status(ProductStatus::Publish)->perPage(50)
);

// Every matching record, across all pages:
$everything = $woo->products()->all(
    Query::create()->after('2026-01-01T00:00:00')->orderBy('date', 'desc')
);

// Direct look-ups by natural key:
$bySku   = $woo->products()->bySku('SKU-123');     // ?array
$byEmail = $woo->customers()->byEmail('jane@example.com');
$byCode  = $woo->coupons()->byCode('SAVE10');
```

Batch API
---------

[](#batch-api)

Most collections expose a `/batch` endpoint that creates, updates and deletes in one round-trip. `BatchPayload` builds it; the SDK splits payloads larger than WooCommerce's 100-operation limit into several requests and merges the results:

```
use Baldie81\WooCommerceSDK\Support\BatchPayload;
use Baldie81\WooCommerceSDK\Support\ProductInput;

$result = $woo->products()->batch(
    BatchPayload::make()
        ->create(ProductInput::make()->name('A')->sku('A-1')->regularPrice('5'))
        ->update(ProductInput::make()->id(42)->regularPrice('9.99'))
        ->delete(43, 44)
);

// $result['create'], $result['update'], $result['delete']
```

Deleting
--------

[](#deleting)

`delete()` permanently deletes by default (`force: true`) — required for resources that can't be trashed (customers, webhooks) and usually what an integration wants. Pass `force: false` to move a product/order to the trash instead:

```
$woo->products()->delete(123);                // permanent
$woo->orders()->delete(456, force: false);    // trashed
```

Errors
------

[](#errors)

Every failure is a `WooCommerceException`. Two concrete types:

- **`ApiException`** — WooCommerce returned a 4xx/5xx. Carries the HTTP `statusCode`, the machine `errorCode` (e.g. `woocommerce_rest_product_invalid_id`), the parsed `data`, and the `rawBody`.
- **`TransportException`** — no usable HTTP response (DNS, connection, timeout, TLS).

```
use Baldie81\WooCommerceSDK\Exception\ApiException;
use Baldie81\WooCommerceSDK\Exception\TransportException;

try {
    $woo->products()->get(999999);
} catch (ApiException $e) {
    if ($e->statusCode === 404) {
        // not found — $e->errorCode is "woocommerce_rest_product_invalid_id"
    }
} catch (TransportException $e) {
    // network-level failure, safe to retry
}
```

Custom transport
----------------

[](#custom-transport)

Need retries, logging or your own middleware? Build a Guzzle client yourself and hand it over — its `base_uri` must point at the store root and the API prefix is prepended to every path:

```
use Baldie81\WooCommerceSDK\WooCommerceClient;

$woo = WooCommerceClient::fromGuzzle($myGuzzleClient, 'wp-json/wc/v3/');
```

Examples
--------

[](#examples)

Copy-pasteable usage lives in [`examples/`](examples) — **one class per area**, each method demonstrating a single operation against the real API. Build a client with `ExampleClient::create()` (edit its dummy placeholder credentials first — never commit real keys), then call a class, e.g. `(new ProductExamples($woo))->create()`.

- [ProductExamples](examples/ProductExamples.php) — create / update / status / delete / get / by-SKU / list / paginate
- [VariationExamples](examples/VariationExamples.php) — variable parent, add variations, bulk-create the matrix
- [CategoryExamples](examples/CategoryExamples.php) — categories (nesting, tree) and tags
- [AttributeExamples](examples/AttributeExamples.php) — global attributes and their terms (single &amp; batch)
- [OrderExamples](examples/OrderExamples.php) — create, set status, search, notes, refunds
- [CustomerExamples](examples/CustomerExamples.php) — CRUD, by-email, idempotent upsert
- [CouponExamples](examples/CouponExamples.php) — percentage &amp; fixed-cart coupons, by-code
- [TaxExamples](examples/TaxExamples.php) — tax classes and rates
- [ShippingExamples](examples/ShippingExamples.php) — zones, locations, flat-rate &amp; free-shipping methods
- [WebhookExamples](examples/WebhookExamples.php) — register / pause / list / delete webhooks
- [BatchExamples](examples/BatchExamples.php) — mixed create/update/delete, large auto-chunked imports
- [StoreConfigExamples](examples/StoreConfigExamples.php) — payment gateways, settings, system status &amp; tools

Testing
-------

[](#testing)

```
composer test
```

The suite drives the client against a Guzzle `MockHandler`, so it makes no real HTTP calls.

License
-------

[](#license)

MIT — see [LICENSE](LICENSE).

###  Health Score

39

—

LowBetter than 85% of packages

Maintenance100

Actively maintained with recent releases

Popularity0

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity42

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Unknown

Total

1

Last Release

0d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/78054659b8e58c2293418f19b04f0e01952282336ce9ed789955c42d01f1b233?d=identicon)[baldie81](/maintainers/baldie81)

---

Top Contributors

[![baldie81](https://avatars.githubusercontent.com/u/45520454?v=4)](https://github.com/baldie81 "baldie81 (4 commits)")

---

Tags

apiwordpresssdkrestGuzzleecommercewoocommerce

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/baldie81-woocommerce-sdk/health.svg)

```
[![Health](https://phpackages.com/badges/baldie81-woocommerce-sdk/health.svg)](https://phpackages.com/packages/baldie81-woocommerce-sdk)
```

###  Alternatives

[jlevers/selling-partner-api

PHP client for Amazon's Selling Partner API

4335.4M2](/packages/jlevers-selling-partner-api)[xeroapi/xero-php-oauth2

Xero official PHP SDK for oAuth2 generated with OpenAPI spec 3

1054.6M18](/packages/xeroapi-xero-php-oauth2)[pixelpeter/laravel5-woocommerce-api-client

Laravel 5 wrapper for the Woocommerce REST API

123104.8k](/packages/pixelpeter-laravel5-woocommerce-api-client)[zenditplatform/zendit-php-sdk

PHP client for Zendit API

1194.4k](/packages/zenditplatform-zendit-php-sdk)[highsidelabs/walmart-api

A PHP client for Walmart's Marketplace, 1P Supplier, and Content Provider APIs.

298.3k](/packages/highsidelabs-walmart-api)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
