Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

iTechGuides is reader-supported. When you buy through links on our site, we may earn an affiliate commission. As an Amazon Associate I earn from qualifying purchases. Learn more

Inside WordPress, get the order with wc_get_order() and call update_status() with the destination slug:

$order = wc_get_order( $order_id );

if ( $order ) {
    $order->update_status( 'completed', 'Updated by automation.' );
}

The method saves the order immediately and returns a boolean. For a remote system, use an authenticated PUT request to the WooCommerce REST API v3 order endpoint instead.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

The direct PHP method

WC_Order::update_status() is the normal choice when your code runs in the same WordPress installation as WooCommerce. It operates on an existing WC_Order object, changes the status, saves the order immediately, and reports whether the operation succeeded.

$order = wc_get_order( $order_id );

if ( $order ) {
    $updated = $order->update_status( 'completed', 'Updated by automation.' );

    if ( ! $updated ) {
        // Record or handle the failure for your application.
    }
}

Pass the status slug without WooCommerce’s internal wc- prefix. Use completed, not wc-completed. The optional second argument becomes an order note, which is useful when a human later needs to understand why an automation changed the order.

What update_status() does

The method signature is:

update_status( string $new_status, string $note = '', bool $manual = false ): bool
  • $new_status is the destination status slug, such as processing or completed.
  • $note is an optional note recorded with the transition. Supply an empty string when no note is needed.
  • $manual is a boolean indicating whether the change is manual. It defaults to false.

WooCommerce’s method documentation describes the operation as updating the order status immediately. Internally, the method sets the new status, saves the order, catches exceptions, logs an error when an exception occurs, and returns false if the update cannot be completed. Your code should therefore treat the return value as meaningful rather than assuming that a method call always succeeded.

Retrieve and validate the order first

update_status() acts on an order object; it does not replace the lookup step. Use wc_get_order() with the order ID and check the result before attempting the transition.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
$order_id = 727;
$order    = wc_get_order( $order_id );

if ( ! $order ) {
    // The ID did not resolve to an order. Stop before calling update_status().
    return;
}

if ( ! $order->update_status( 'processing', 'Payment verified by automation.' ) ) {
    // The transition failed; handle it according to your workflow.
}

This guard prevents code from dereferencing a missing order. It also gives you a separate failure path for an invalid or unavailable ID. For business-critical transitions, retain the failed result in your application’s own logging or retry workflow instead of silently continuing.

Common status changes in PHP

Mark an order completed

Use the completed slug when your workflow has reached its completed state:

$order = wc_get_order( $order_id );

if ( $order ) {
    $success = $order->update_status(
        'completed',
        'Fulfillment confirmed by the warehouse integration.'
    );

    if ( ! $success ) {
        // Escalate, log, or queue a retry.
    }
}

The note is optional, but a specific explanation is preferable to a blank audit trail when several systems can change orders.

Move an order to processing

$order = wc_get_order( $order_id );

if ( $order ) {
    $order->update_status( 'processing', 'Payment received.' );
}

Use the exact slug shown in the status table below. Do not add the wc- prefix.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Place an order on hold

$order = wc_get_order( $order_id );

if ( $order ) {
    $order->update_status( 'on-hold', 'Awaiting manual verification.' );
}

Status slugs can contain a hyphen, so quote on-hold as a normal PHP string.

Supply the manual flag explicitly

The third parameter is optional. If your integration needs to identify the transition as manual, pass true:

$order = wc_get_order( $order_id );

if ( $order ) {
    $order->update_status(
        'completed',
        'Approved by an operator.',
        true
    );
}

When the distinction is not needed, omit the third argument and let it use its default value of false.

WooCommerce status slugs

The official REST order schema lists these status values. Use the slug in the PHP call or REST payload exactly as shown.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Status slug Meaning in a transition Example call
pending The schema documents this as the default status. $order->update_status( 'pending' );
processing Move the order into processing. $order->update_status( 'processing' );
on-hold Place the order on hold. $order->update_status( 'on-hold' );
completed Mark the order completed. $order->update_status( 'completed' );
cancelled Set the order to cancelled. $order->update_status( 'cancelled' );
refunded Set the order to refunded. $order->update_status( 'refunded' );
failed Set the order to failed. $order->update_status( 'failed' );
trash The schema includes the trash status. $order->update_status( 'trash' );

These are the values identified by the official order schema. A store’s workflow can still impose business rules around which transitions are appropriate, so choose a destination that matches the event your code has actually verified.

Build a reusable status-update function

When several jobs or callbacks need the same behavior, centralize lookup, notes, and failure handling in one function:

Rank #3
Sale
Handbook for Anglo-Chromatic Concertina
  • Pages: 24
  • Instrumentation: Concertina
function set_order_status_from_automation( $order_id, $status, $note = '' ) {
    $order = wc_get_order( $order_id );

    if ( ! $order ) {
        return false;
    }

    return (bool) $order->update_status( $status, $note );
}

$changed = set_order_status_from_automation(
    727,
    'completed',
    'Marked complete after fulfillment confirmation.'
);

if ( ! $changed ) {
    // The caller can log the ID and schedule its own recovery action.
}

This pattern keeps the boolean result visible to the caller. It does not hide a failed lookup or a failed save behind a successful-looking function call.

Handling failures and exceptions

There are two checks to make before considering a transition successful:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
  1. Confirm that wc_get_order() returned an order object.
  2. Inspect the boolean returned by update_status().

The implementation returns false when the order cannot be resolved for the requested operation. It also catches exceptions, logs an error, and returns false. A production integration should preserve enough context to diagnose the failed attempt: the order ID, requested status, and the automation event that initiated it.

$order = wc_get_order( $order_id );

if ( ! $order ) {
    error_log( 'Order lookup failed for ID ' . (int) $order_id );
    return;
}

$ok = $order->update_status( 'completed', 'Fulfillment callback received.' );

if ( ! $ok ) {
    error_log( 'Status update failed for order ' . (int) $order_id );
    // Notify the surrounding job, queue a retry, or stop dependent work.
}

Do not run downstream work that assumes completion until the method has returned a successful result. If the transition is not business-critical, you can choose a lighter response, but the decision should be deliberate.

Changing a status through the REST API

Use the REST route when the code that changes the order runs outside the WordPress installation or when another service needs a remote integration boundary. WooCommerce identifies REST API v3 as the current recommended version for new integrations.

To update order ID 727, send an authenticated request to:

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
PUT /wp-json/wc/v3/orders/727
Content-Type: application/json

{"status":"completed"}

The request uses the order ID in the URL and the destination slug in the JSON body. Replace completed with another supported slug when the receiving workflow calls for a different state.

What the remote client must provide

  • An authenticated request accepted by the store.
  • Permission to update orders.
  • A transport configuration appropriate for protecting credentials and order data.
  • A response-handling path that records an unsuccessful request rather than treating the HTTP exchange as automatically successful.

The exact authentication mechanism depends on the store and its integration setup. Keep credentials out of source control, use the store’s approved permissions, and send the request over a secured transport. The API endpoint alone does not bypass authorization.

Example request from a command-line client

The following illustrates the HTTP shape; supply authentication in the manner configured for your store:

curl -X PUT 
  'https://example.com/wp-json/wc/v3/orders/727' 
  -H 'Content-Type: application/json' 
  -H 'Authorization: Bearer YOUR_AUTH_TOKEN' 
  --data '{"status":"completed"}'

Replace the host and authentication header with values supported by the target installation. The important WooCommerce-specific parts are the /wp-json/wc/v3/orders/<id> route, the PUT method, and the status property in the JSON payload.

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Example request from external PHP

$payload = wp_json_encode( array( 'status' => 'completed' ) );

$response = wp_remote_request(
    'https://example.com/wp-json/wc/v3/orders/727',
    array(
        'method'  => 'PUT',
        'headers' => array(
            'Content-Type' => 'application/json',
            // Add the authentication headers required by the store.
        ),
        'body'    => $payload,
        'timeout' => 30,
    )
);

if ( is_wp_error( $response ) ) {
    // Handle the transport failure.
}

That example shows request construction and transport-error handling only. Your integration must add the store’s approved authentication and inspect the returned HTTP response before marking the remote operation complete.

PHP versus REST: choose by execution location

Consideration update_status() in WordPress REST API v3
Where code runs Inside the WordPress/WooCommerce installation. In an external service or another application communicating with the store.
How the order is addressed Retrieve it with wc_get_order( $order_id ). Put the order ID in /wp-json/wc/v3/orders/<id>.
How the status is supplied Pass the slug as the first method argument. Send a JSON status property.
Authentication model Uses the permissions and execution context already available inside WordPress. Requires request authentication and the store’s order-update permission.
Error signal A missing order or failed update produces a false result; exceptions are logged by the method. The client must handle transport, authorization, and unsuccessful API responses.
Best fit Local plugins, themes, scheduled jobs, and WordPress-side automation. Fulfillment platforms, back-office systems, and other remote integrations.

Use the local method when the transition is part of WordPress-side logic and the remote route when crossing an application boundary. Do not add a REST hop merely to change a status from code that already runs in the same installation.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Run follow-up work after a status transition

A status change often needs a second action, such as notifying another system or synchronizing fulfillment. WooCommerce documents action and webhook mechanisms for this purpose.

Actions and filters

Status-related hooks include woocommerce_order_status_changed and woocommerce_order_edit_status. Attach receiving code to the mechanism appropriate for your workflow, then keep the transition itself separate from the follow-up operation.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
add_action( 'woocommerce_order_status_changed', 'send_status_to_fulfillment', 10, 4 );

function send_status_to_fulfillment( $order_id, $old_status, $new_status, $order ) {
    // Send the order ID and new status to your receiving integration.
}

The receiving function shown above is intentionally a boundary for your own business logic. Supply only the data and side effects your integration requires, and make its failure handling explicit.

Webhooks

WooCommerce webhook documentation describes event topics and status-related hooks. Webhooks are useful when an external application should receive a notification after a transition without embedding that application inside WordPress. Configure the receiving endpoint and its authentication separately from the code that calls update_status().

Whether you use an action, filter, or webhook, decide which system owns the authoritative transition and ensure that follow-up processing can report failures. A notification mechanism should not be mistaken for proof that the original status save succeeded; check the method result or API response first.

Troubleshooting common problems

The status never changes

  • Check that wc_get_order() returned an object for the ID you supplied.
  • Verify that the slug is written without wc-; use on-hold, not wc-on-hold.
  • Inspect the boolean returned by update_status() and your application logs.
  • If the change is remote, confirm that the request used PUT, the v3 route, and a JSON status field.

The code reports success but another system did not react

Separate the order update from its follow-up work. A successful local method call confirms the status operation, not the completion of an external notification. Review the status-change hook or webhook receiver and its own error handling.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

The REST request is rejected

  • Confirm that the URL contains the correct order ID and the /wp-json/wc/v3/orders/ path.
  • Check that the credentials are valid for the store and authorized to update orders.
  • Send valid JSON with a supported status slug.
  • Review the response returned by the store before retrying.

An exception appears in logs

The method catches exceptions and returns false. Preserve the order ID, requested slug, and triggering event in your own diagnostic record, then correct the underlying data or integration condition before retrying.

Implementation checklist

  1. Decide whether the caller runs inside WordPress or outside it.
  2. For local code, call wc_get_order( $order_id ) and stop if no order is returned.
  3. Pass a documented status slug without the wc- prefix.
  4. Add a concise note when the reason for an automated change matters to future operators.
  5. Use the optional manual flag only when your workflow needs to identify the change as manual.
  6. Check the boolean result from update_status() before running dependent work.
  7. For remote systems, use an authenticated PUT request to the WooCommerce REST API v3 order route.
  8. Handle authorization, transport, and unsuccessful API responses separately.
  9. Use status hooks or webhooks for notifications and synchronization after the transition.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.