Create and Update Products with WooCommerce API
Recently, I was publishing and updating the tutorials about WordPress REST API, how to create a post, how to add a featured image and so on. But did you know that WooCommerce has its own API, which is built on the base of a regular WordPress REST API but allows you to do many more things and also simplifies the work with the other ones?
In this tutorial, we are going to dive into actual examples of working with WooCommerce API. I will show examples of creating and updating products, and also we will try to search them by SKU and delete them.
In this tutorial specifically, I am going to use two methods of interaction with the WooCommerce API – using WordPress HTTP functions like wp_remote_get() and wp_remote_request() and also using an official WooCommerce REST API PHP library.
Consumer Key and Consumer Secret
In order to authenticate with the WooCommerce API you need to provide:
- A username and application password – in case you’re about to use WordPress HTTP API functions, it could be useful in cases when your plugin works not only with WooCommerce products but also, for example, with regular WordPress posts, that’s exactly what my plugin, Simple WP Crossposting, does.
- A consumer key and secret – will work in both cases whether you’re using the WooCommerce REST API PHP Library or not.
In order to generate a consumer key and a consumer secret in WooCommerce settings, please go to the “Advanced” tab and then to the “REST API” tab.

Just click that big button.

The settings above are pretty straightforward:
- “Description” is the description of this specific pair of keys,
- “User” – is a store user under whose permissions all the changes are going to be made,
- “Permissions” – if you set just “Read” there, you will be able only to get the data using these API credentials but not allowed to update anything on the store. For example, you’d get a rest API error
woocommerce_rest_cannot_create, if you try to create a product with “Read” permissions. So let’s set it to “Read/Write”.
Finally, we got our keys:

One more thing to notion, please make sure that your REST API isn’t disabled on the WordPress level, for example, with this code. Also, there are plugins for that.
So for all the examples below, we assume that we have the following variables declared:
-
$keyand$secretin case we decide to use the consumer key and secret, $usernameand$pwd– in cases when we decided to use application passwords.
Now, let’s dive into the examples.
Create Product with WooCommerce API
Guys, a small disclaimer – it is just examples, not the complete API docs. So, obviously there are a lot of more arguments available, which you can find in the official docs.
Creating products is very similar to creating posts with WordPress REST API.
$product_data = array(
'name' => 'My test product', // product title
'status' => 'draft', // product status, default: publish
'categories' => array( // product categories
array(
'id' => 5 // each category in a separate array
),
array(
'id' => 10
)
),
'regular_price' => '9.99' // product price
);
$response = wp_remote_post(
"{$url}/wp-json/wc/v3/products",
array(
'headers' => array(
'Authorization' => 'Basic ' . base64_encode( "{$username}:{$pwd}" )
),
'body' => $product_data
)
);
if( 'Created' === wp_remote_retrieve_response_message( $response ) ) {
$body = json_decode( wp_remote_retrieve_body( $response ) );
echo "The product {$body->name} has been created.";
}You can always print_r( $body ) or print_r( $response ) to view what is returned.
If you’re going to create products with attributes using WooCommerce API, I recommend you check my other tutorial with the appropriate examples there.
Now, let’s try to do the same but using the WooCommerce REST API PHP library:
$woocommerce = new Client( $url, $key, $secret, array( 'version' => 'wc/v3' ) );
try {
$new_product = $woocommerce->post( 'products', $product_data );
echo "The product {$new_product->name} has been created.";
} catch( Exception $error ) {
$error = $error->getMessage();
}Update Product with WooCommerce API
In the piece of code below, you have to replace the $product_id variable with the actual product ID you would like to update.
$response = wp_remote_request(
"{$url}/wp-json/wc/v3/products/{$product_id}",
array(
'method' => 'PUT',
'headers' => array(
'Authorization' => 'Basic ' . base64_encode( "{$username}:{$pwd}" )
),
'body' => array(
'regular_price' => '100.30', // just update the product price
// but we can update several parameters at the same time, of course
)
)
);
if( 'OK' === wp_remote_retrieve_response_message( $response ) ) {
$body = json_decode( wp_remote_retrieve_body( $response ) );
echo "The product {$body->name} has been updated.";
}The same with the PHP library:
try {
$updated_product = $woocommerce->put(
"products/{$product_id}",
array(
'regular_price' => '100.30',
)
);
echo "The product {$updated_product->name} has been updated.";
} catch( Exception $error ) {
echo $error->getMessage();
}Search Products
Another cool thing is that WooCommerce REST API allows you to search products, let’s say, by their SKU or product categories.
Let me show you an example of how you can get products or even product variation by SKU.
$response = wp_remote_get(
add_query_arg(
array( 'sku' => $sku ),
'https://your-website/wp-json/wc/v3/products'
),
array(
'headers' => array(
'Authorization' => 'Basic ' . base64_encode( "{$username}:{$pwd}" )
)
)
);
if( 'OK' === wp_remote_retrieve_response_message( $response ) ) {
// now we have an array of products found
$products = json_decode( wp_remote_retrieve_body( $response ) );
// but probably it is the only product because we are searching by SKU
$product = reset( $products );
if( 'variation' === $product->type ) {
echo 'Variation found with ID: ' . $product->id;
} else {
echo 'Product found with ID: ' . $product->id;
}
}Delete a Product
Do not forget to replace $product_id with the actual product ID. ?force=true at the end of the endpoint URL means to remove a product completely without moving it to the trash.
$response = wp_remote_request(
'https://your-website/wp-json/wc/v3/products/{PRODUCT ID}', // ?force=true
array(
'method' => 'DELETE',
'headers' => array(
'Authorization' => 'Basic ' . base64_encode( "{$username}:{$pwd}" )
)
)
);
if( 'OK' === wp_remote_retrieve_response_message( $response ) ) {
$body = json_decode( wp_remote_retrieve_body( $response ) );
echo "The product {$body->name} has been removed.";
}
Misha Rudrastyh
Hey guys and welcome to my website. For more than 15 years I've been doing my best to share with you some superb WordPress guides and tips for free.
Need some developer help? Contact me
hi,
this not work for me.
but when I add this in functions.php, it works:
Hey Maro,
Are you sure that you use correct Consumer key and Consumer Secret with Read/Write permissions?
thanks, for reply..
i have used anthor library
Fantastic! You helped me fix something I’d been struggling with for hours! Thank you very much mate!
Hello
How I can add subscription product data ?
Good Afternoon,
I’m trying to play around with this and add products remotely.
Using the above, could I run it anywhere in order to add products? Or does it have to be within a WordPress installation?
Many thanks
This https://github.com/woocommerce/woocommerce/wiki/Getting-started-with-the-REST-API#server-does-not-support-postdeleteput do the trick for me.
Some times, Server does not support POST/DELETE/PUT
Ideally, your server should be configured to accept these types of API request, but if not you can use the _method property.
See https://developer.wordpress.org/rest-api/using-the-rest-api/global-parameters/#_method-or-x-http-method-override-header
Doing a POST request, and passing _method=PUT as a query parameter works for me.
Any available CRUD interfaces for supported actions of WooCommerce API?
Thanks for this example, pointed me in the right direction!
How would I go about moving product(s) to the Trash? ?force=false?
Products should by moved to trash by default.
It would be very nice to see options within the code on how to choose the product type, the owner (creator ID of the product, sale price (incuding start and end date), reservation price, incremental price (for those who use auction plugins), and a bunch of other things I guess other readers will ask for in regards of variable products, grouped products – and so forth.
BUT, more importantly – how to make this available as a page template:
So that we get something useful some a certain role / group os users without giving them access to the WP-ADMIN area.
Of course, which goes without saying: whatever “they” choose to submit will become a “draft” and not a published version.
I know there are plugins out there claming to the job, but they don’t really.
If you did one that actually works for ALL product types – I would be the first to buy it.
But until then, how about a taste with your, as always, amazing code comments along the way so that everyone can understand?
Thanks for everything you do and for an amazing blog / resource!
How to add ssl certificate to be sent with the request I’m getting
{“code”:”woocommerce_rest_cannot_create”,”message”:”Sorry, you are not allowed to create resources.”,”data”:{“status”:401}}
because the image link has it’s private ssl certificate (I have the ca-cert.pem) but how I can added to the api so it can download the images?