Halloween DealsAmazon USHalloween week deals: useful picks before month-endAmazon US: current deals, useful picks and tech finds.Check DealsPC HealthRecommendedCrashes, freezes, slowdowns? Check your PC nowSpot repairable issues before they interrupt work.Check PCHalloween DealsAmazon USOctober picks are moving - compare before checkoutAmazon US: current deals, useful picks and tech finds.See Picks×
Skip to content
World desk9 min

How to Change a WooCommerce Order Status With update_status()

Use wc_get_order() and WC_Order::update_status() to change WooCommerce orders in PHP, or send an authenticated PUT request to the REST API v3 order endpoint from an external service.
Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

To change an order status in PHP running inside WordPress, load the order with wc_get_order() and call update_status() on the returned WC_Order object:

$order = wc_get_order( $order_id );

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

The method saves the transition immediately. Use a status slug such as completed or on-hold without WooCommerce’s internal wc- prefix, record a useful note when appropriate, and check the Boolean return value when a failed transition matters.

As an Amazon Associate I earn from qualifying purchases.

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.

What update_status() does

WC_Order::update_status() changes an existing WooCommerce order to a new status and persists that change immediately. It operates on a WC_Order object, not on an order ID by itself. The normal sequence is therefore: obtain the order, verify that an object was returned, call the method, and handle its result.

The documented method signature is:

update_status( string $new_status, string $note = '', bool $manual = false ): bool
  • $new_status is the destination status slug.
  • $note is optional text stored with the status transition. An empty string means that you do not want to add a note.
  • $manual is a Boolean that identifies whether the change should be treated as manual. It defaults to false.
  • The return value is true when the update succeeds and false when it does not.

The implementation sets the new status, saves the order, catches exceptions, logs an error, and returns false if the operation cannot be completed. That makes the return value the application-level signal to inspect after the call.

Change an order status in PHP

Minimal status update

Place this code in a context where WooCommerce is loaded, such as a plugin, a theme integration, or a callback that runs after WordPress has initialized its plugins:

$order_id = 727;
$order = wc_get_order( $order_id );

if ( $order ) {
    $order->update_status( 'processing' );
}

The example requests the processing status and supplies no note. WooCommerce performs the save during the method call; there is no separate status-save step in this sequence.

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

Add an audit note

An explanatory note is useful when an automated job, synchronization process, or support tool changes an order. Pass it as the second argument:

$order = wc_get_order( $order_id );

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

    if ( ! $updated ) {
        error_log( 'The order status update failed.' );
    }
}

Keep the note factual and specific. It should explain why the transition occurred without putting credentials, payment data, or other sensitive values into the order history.

Pass the manual flag explicitly when your workflow needs it

The third argument is optional:

$updated = $order->update_status(
    'on-hold',
    'Placed on hold pending verification.',
    true
);

Use true only when your application is intentionally identifying the transition as manual. Otherwise, omit the argument and use the documented default of false.

Retrieve and validate the order first

wc_get_order() can fail to return an order object. The ID may be wrong, the order may not exist in the current store, or the value supplied by an external system may not identify a valid WooCommerce order. Calling a method on a failed lookup is an avoidable fatal error, so guard the call:

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

if ( ! $order ) {
    error_log( 'No WooCommerce order was found for the supplied ID.' );
    return;
}

$updated = $order->update_status( 'completed', 'Marked complete by automation.' );

if ( ! $updated ) {
    error_log( 'WooCommerce could not change the order status.' );
}

In a function that cannot use return directly, replace that branch with the error-handling convention used by the surrounding application. The important points are to stop before calling update_status() when the lookup failed and to treat a false result as a real failure rather than assuming the transition happened.

Use the correct status slug

The official WooCommerce REST order schema lists these status values:

Status slug Use in code Schema note
pending $order->update_status( 'pending' ); Documented as the default status in the schema
processing $order->update_status( 'processing' ); Use the slug exactly as shown
on-hold $order->update_status( 'on-hold' ); Includes a hyphen
completed $order->update_status( 'completed' ); Use the slug without a prefix
cancelled $order->update_status( 'cancelled' ); Spelling follows the documented slug
refunded $order->update_status( 'refunded' ); Use the exact lowercase value
failed $order->update_status( 'failed' ); Use the exact lowercase value
trash $order->update_status( 'trash' ); Listed by the REST order schema

Pass completed, not wc-completed; pass on-hold, not wc-on-hold. The internal wc- prefix is not part of the value expected by update_status().

Choose the destination deliberately

A status change is a business decision, not merely a text edit. Before setting it, identify the event that authorizes the transition: payment confirmation, fulfillment confirmation, a fraud review, a customer-service correction, or an external system’s confirmed result. A job that runs repeatedly should also determine whether it should attempt the call only when the current status differs from the desired status.

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

if ( ! $order ) {
    return;
}

if ( 'completed' !== $order->get_status() ) {
    $order->update_status(
        'completed',
        'Completed after confirmed fulfillment.'
    );
}

This conditional avoids issuing the same transition when the order is already complete. Whether to skip an already-correct status or still write a note is a workflow choice; make it explicit in the calling code.

Handle failures instead of assuming success

There are two separate failure points. First, the order lookup may not produce a WC_Order object. Second, update_status() may return false. The method’s implementation catches exceptions and logs an error, so callers should still inspect the Boolean result and decide how to recover.

Rank #3
Sale
Handbook for Anglo-Chromatic Concertina
  • Pages: 24
  • Instrumentation: Concertina

For a critical workflow

If the status controls fulfillment, entitlement, invoicing, or another irreversible action, record the failure and keep the source event available for retry. A practical pattern is:

$order = wc_get_order( $order_id );

if ( ! $order ) {
    error_log( 'Order lookup failed; queue the source event for review.' );
    return;
}

$updated = $order->update_status(
    'completed',
    'Completed by the fulfillment integration.'
);

if ( ! $updated ) {
    error_log( 'Status transition failed; do not acknowledge the source event.' );
    return;
}

// Acknowledge the source event only after the update succeeds.

The final action in this example represents your integration’s acknowledgement mechanism; it is intentionally performed only after a successful return value.

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

For a non-critical administrative script

A one-off maintenance task can log the order ID and continue to the next item when one update fails. Do not hide failures by discarding the return value, especially in a batch where a successful exit code could otherwise suggest that every order changed.

Changing status through the REST API

Use the REST API when the code that initiates the change runs outside the WordPress installation, such as a separate fulfillment service or an integration server. WooCommerce identifies REST API v3 under /wp-json/wc/v3/ as the current recommended version for new integrations.

To change order 727 remotely, send an authenticated PUT request to the order resource:

PUT /wp-json/wc/v3/orders/727
Content-Type: application/json

{"status":"completed"}

The request body contains the status field and the same slug rules apply: use completed, processing, or on-hold, not a value with the wc- prefix. The request must be authenticated with credentials that have permission to edit orders, and it must be transported securely. How credentials are stored and supplied depends on the integration; never place them in client-side code or log them with request details.

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

Validate the remote result

A remote caller should treat the HTTP response as part of the operation’s result. Check that the request was accepted, inspect an error response when it was not, and retain enough context to retry safely. At minimum, log the order ID, requested status, time, and a correlation identifier while omitting secrets. If the integration can receive the same event twice, make its retry behavior idempotent so that a repeated request does not trigger duplicate downstream work.

PHP or REST: which path fits?

Decision point PHP with update_status() REST API v3
Where it runs Inside the WordPress and WooCommerce process In an external service that calls the store
How it identifies the order Loads a WC_Order with wc_get_order() Uses the order resource path, such as /wp-json/wc/v3/orders/727
Authentication model Uses the current WordPress execution context Requires authenticated API credentials and edit permission
Error signal Order lookup plus the method’s Boolean return value HTTP response plus the API error body
Local follow-up Can participate directly in local hooks and application code Requires a remote integration strategy for follow-up work
Best fit Plugins, scheduled WordPress jobs, and in-store automation External fulfillment, ERP, or synchronization services

Choose PHP when the decision already belongs inside the store and you need the local WooCommerce object. Choose REST when another system owns the event and should cross an explicit API boundary.

React to status changes with hooks and webhooks

Changing a status is often only the first step. WooCommerce documents status-related actions including woocommerce_order_status_changed and woocommerce_order_edit_status. These hooks let local code respond to a transition instead of putting every notification or synchronization task directly beside the update call.

Use a hook when the receiving action belongs to the same WordPress installation, such as sending an internal notification or updating a local record. Use a webhook when another service needs an event from the store. WooCommerce’s webhook system documents event topics for delivering those changes to external consumers.

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.

Keep transition effects separate

A useful separation is:

  1. The command decides that the order should move to a destination status.
  2. update_status() performs and saves the transition.
  3. A hook or webhook consumer performs notification, fulfillment synchronization, or other follow-up work.

This arrangement makes it easier to retry a failed consumer without repeatedly inventing new status changes. The receiving code should still record failures and avoid assuming that delivery or processing occurred merely because the status update succeeded.

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

Common problems and fixes

The order object is empty

Check the value passed to wc_get_order() and confirm that the code is running after WooCommerce has loaded. Do not call update_status() until the lookup has returned an object. Log the identifier in a safe form so an administrator can correct the source data.

The status never changes

Confirm that the value is a documented slug, is lowercase, and uses the hyphen in on-hold. Remove the wc- prefix if it was copied from an internal label. Then inspect the Boolean return value and application logs rather than relying only on a screen refresh.

The method returns false

Treat this as an unsuccessful transition. Preserve the triggering event for retry, inspect the logged error, and verify that the order can be edited in the current execution context. Avoid acknowledging an external message or launching dependent fulfillment until the update succeeds.

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

The REST request is rejected

Verify the HTTP method, the /wp-json/wc/v3/orders/{id} resource shape, JSON content type, credentials, and permission to edit orders. Make sure the request reaches the intended store and that transport encryption is enabled. Read the response body for the specific API error instead of retrying blindly.

Follow-up automation runs more than once

Status changes can be retried by jobs or remote systems. Design notification and synchronization handlers to recognize duplicate events, and store a durable event or correlation identifier where your integration requires exactly-once business effects.

Implementation checklist

  • Confirm that the code runs in a WooCommerce-loaded WordPress context, or choose REST API v3 for an external caller.
  • Load the order with wc_get_order( $order_id ).
  • Stop safely when no order object is returned.
  • Pass a documented slug without the wc- prefix.
  • Use the second argument to explain an automated transition when an audit note is useful.
  • Pass the third Boolean argument only when the manual designation is intentional.
  • Inspect the true/false result from update_status().
  • For REST, send an authenticated PUT request to /wp-json/wc/v3/orders/<order-id> with a JSON status field.
  • Separate the status command from local hooks, webhook consumers, and retry logic.
  • Test missing IDs, invalid slugs, failed saves, permission errors, and duplicate events before enabling automation.

Complete reference example

The following function keeps lookup, status selection, note creation, and failure handling in one small unit. It returns a Boolean so its caller can decide whether to retry or report the result:

function mark_order_completed( $order_id ) {
    $order = wc_get_order( $order_id );

    if ( ! $order ) {
        error_log( 'Unable to load the WooCommerce order.' );
        return false;
    }

    if ( 'completed' === $order->get_status() ) {
        return true;
    }

    $updated = $order->update_status(
        'completed',
        'Marked complete by the fulfillment automation.'
    );

    if ( ! $updated ) {
        error_log( 'WooCommerce rejected the order status update.' );
        return false;
    }

    return true;
}

The function treats an already-completed order as successful without writing a second transition note. If your business process requires a fresh audit note on every invocation, remove that early return and make the duplicate-event policy explicit instead.

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

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.

Leave a Reply

Your email address will not be published. Required fields are marked *

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

More from the Wire

  1. World desk4 min
    How to Spot an AI Voice Scam Before Sending MoneyDon’t rely on how a caller sounds. Pause, call back through a known number, and verify the emergency with another trusted person before sending money.
  2. Mountain View desk4 min
    Google’s SynthID Detector: How to Check AI-Generated Images, Video and AudioGoogle’s SynthID Detector looks for an embedded watermark in supported images, video and audio. Here is what its results do—and do not—show.
  3. Redmond desk20 min
    How to create a link to File or Folder in Windows 11Windows 11 gives you several ways to point to a file or folder without moving or duplicating it. You can create a desktop shortcut,…
Recommended PC Tool
Recommended PC Tool
Windows Errors? Fix Them Before They SpreadFree repair scan
Outdated Drivers Are Slowing You DownFree scan - exact matches

Two free Windows tools

One Free Minute Could Fix That PC

Before you go - each of these free tools takes about a minute and tackles what quietly slows a Windows PC down.

Special offer. View Outbyte info, uninstall instructions, EULA, and Privacy Policy.