Create or Update WooCommerce Orders via REST API
In this guide, we’re going to dive into different examples of both creating and updating WooCommerce orders using the REST API. By the way, if you’re looking for a way how to delete orders using REST API, check my other tutorial out.
Before we begin, let’s decide how we’re going to send REST API requests in WooCommerce, because there are different ways to do it actually.
Let’s say, we are going to send them from another WordPress website, then we have the following possible ways:
- We can use cURL or WordPress HTTP API,
- We can use an official PHP library for WooCommerce REST API; this method, for example, I’m using in my Order Sync plugin.
- We can use an official JavaScript library.
I am going to use the first two ways in the examples below. But you can use whatever way you want.
Create an Order Using REST API
You can create a WooCommerce order just by sending a POST request to this endpoint /wp-json/wc/v3/orders. By the way, there are no required parameters you need to pass in order to create an order, so something like this will be enough:
$order_data = array();
$response = wp_remote_post(
"{$url}/wp-json/wc/v3/orders",
array(
'headers' => array(
'Authorization' => 'Basic ' . base64_encode( "$username:$pwd" )
),
'body' => $order_data
)
);
if( 'Created' === wp_remote_retrieve_response_message( $response ) ) {
echo 'Your order has been created';
}Of course, do not forget to replace $url with the actual WooCommerce store where you’re about to create orders using the REST API, also, replace $username and $pwd with a username and an application password.
If you decide to use a WooCommerce PHP library for that, your code is going to look a little bit different:
$order_data = array();
$woocommerce = new Client( $url, $consumer_key, $consumer_secret, array( 'version' => 'wc/v3' ) );
try {
$woocommerce->post( 'orders', $order_data );
} catch( Exception $error ) {
$error = $error->getMessage();
}What is interesting here is that you don’t need a username and application password, but you have to provide a consumer key and consumer secret; read more about where to get them.
And that’s what we get if we run the code above:

Of course, it is better to pass some parameters to an order, at least a customer ID, maybe the order total or a payment method, you can find the full list of parameters in an official WooCommerce REST API documentation, but for now – just check the example below:
/*
* @snippet: WooCommerce API Create Order
* @author: Misha Rudrastyh
* @url: https://rudrastyh.com/woocommerce/rest-api-create-or-update-orders.html#create-order
*/
$order_data = array(
'status' => 'processing',
'customer_id' => 1,
'billing' => array(
'first_name' => 'Misha',
'last_name' => 'Rudrastyh',
'company' => 'Misha Rudrastyh Digital',
'address_1' => 'Boulevard Point',
'address_2' => '2301',
'city' => 'Dubai',
'state' => 'Dubai',
'postcode' => '0000',
'country' => 'AE', // in in ISO 3166-1 alpha-2 format
'email' => 'no-reply@rudrastyh.com',
'phone' => '+971 000 00 00',
),
'shipping' => array(), // the same as for 'billing'
'payment_method' => 'cod',
'payment_method_title' => 'By cash', // you can set a custom title
'transaction_id' => 'tx1234567890',
'meta_data' => array(
array(
'key' => 'my_custom_key',
'value' => 'the value of this key',
),
),
// products added to an order
'line_items' => array(
// when a product exists on this store
array(
'product_id' => 123, // or 'variation_id' => 123,
'quantity' => 2,
),
// when a product doesn't exist
array(
'name' => 'Surf board',
'quantity' => 2,
'subtotal' => 50,
'total' => 100,
'product_id' => 9999, // you can use non-existing ID
),
),
'shipping_lines' => array(
array(
'method_title' => 'My shipping method',
'method_id' => 'flat_rate',
'total' => 5,
),
),
'fee_lines' => array(
array(
'name' => 'Some special handling fee',
'total' => 500,
),
),
'coupon_lines' => array(
array(
'code' => 'blckfrd',
),
),
// if you set this parameter to true it will reduce stock items quantity and set the order status to processing
//'set_paid' => true,
);
$response = wp_remote_post(
"{$url}/wp-json/wc/v3/orders",
array(
'headers' => array(
'Authorization' => 'Basic ' . base64_encode( "$username:$pwd" )
),
'body' => $order_data,
)
);If you decide to use the PHP library, then just replace the following lines:
try {
$woocommerce->post( 'orders', $order_data );
} catch( Exception $error ) {
$error = $error->getMessage();
}Update an Existing Order Using REST API
Updating an order is as easy as sending a PUT REST API request to the /wp-json/wc/v3/orders/{ORDER ID} endpoint.
Change an order status
Let’s begin with something super simple. For example we can change an order status.
$response = wp_remote_request(
"{$url}/wp-json/wc/v3/orders/{$order_id}",
array(
'method' => 'PUT',
'headers' => array(
'Authorization' => 'Basic ' . base64_encode( "$username:$pwd" )
),
'body' => array(
'status' => 'completed', // pending, processing, on-hold, cancelled, refunded, failed
)
)
);
if( 'OK' === wp_remote_retrieve_response_message( $response ) ) {
echo 'Order status has been changed.';
}Also, let’s do the same using WooCommerce REST API PHP library for a change:
try {
$woocommerce->put(
"orders/{$order_id}",
array(
'status' => 'completed'
)
);
echo 'Order status has been changed.';
} catch( Exception $error ) {
echo $error->getMessage();
}Update a custom field of an order
Updating custom fields of an order is also not a very big deal:
$response = wp_remote_request(
"{$url}/wp-json/wc/v3/orders/{$order_id}",
array(
'method' => 'PUT',
'headers' => array(
'Authorization' => 'Basic ' . base64_encode( "$username:$pwd" )
),
'body' => array(
'meta_data' => array(
array(
'key' => 'my_custom_key',
'value' => 'a new custom field value',
),
),
)
)
);The new value of a custom field should be reflected on the edit order page, in case you don’t have your field added to the order meta box, it will be displayed just like that:

Add new line items
You can easily add an order item to an order without removing the existing ones. You just need to pass them into line_items, shipping_lines or fee_lines array.
For example, we would like to add a product variation to an order as an order item:
$response = wp_remote_request(
"{$url}/wp-json/wc/v3/orders/{$order_id}",
array(
'method' => 'PUT',
'headers' => array(
'Authorization' => 'Basic ' . base64_encode( "$username:$pwd" )
),
'body' => array(
'line_items' => array(
array(
'variation_id' => 12345,
),
),
)
)
);That’s great, but if we need to remove existing order items from an order as well? The good news – all you need to do is pass a quantity of an order item equal to 0, the bad news – you need to know an order item ID, for example:
'line_items' => array(
array(
'id' => 1234, // yes, we need to provide an order item ID
'quantity' => 0,
),
),The same goes if you’re just about to change an order item quantity without removing it – you have to know an order item ID.
Ok, but how to do it?
You need to send one more REST API request to get this specific order, the response will contain all order items with IDs.
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
Perfect, i reached this using Vue app, but I’m stuck at payment method, should i create another api request to confirm the payment then update the state of order?