How to Get WooCommerce Order Details (Complete API Reference)

Complete reference for accessing WooCommerce order data programmatically - getter methods, get_data(), billing/shipping fields, iterating order items, and a practical custom admin column example. Updated for WooCommerce 7.1+ HPOS.

April 18, 2026 5 min read Tips

Accessing WooCommerce order data programmatically comes up constantly in custom development - whether you're building a custom order admin column, a webhook payload, a third-party integration, or a custom email notification. Since WooCommerce 3.0, the entire order data API changed: direct property access is gone, replaced by getter methods and the get_data() array. Here's the complete reference with practical examples.

Getting the WC_Order Object

Everything starts with wc_get_order(). Pass it an order ID and you get back a WC_Order object:

$order = wc_get_order( $order_id );

if ( ! $order ) {
    return; // always check - returns false if ID is invalid
}

Inside order hooks like woocommerce_order_status_changed, the order object is passed directly as a parameter, so you don't need to call wc_get_order() again.

Order Getter Methods

These are the getters you'll use most often on a WC_Order instance:

$order->get_id();                      // Order ID (integer)
$order->get_status();                  // e.g. 'pending', 'processing', 'completed'
$order->get_currency();                // e.g. 'CAD', 'USD'
$order->get_total();                   // Order total (string, formatted as decimal)
$order->get_subtotal();                // Subtotal before tax/shipping
$order->get_discount_total();          // Total discount applied
$order->get_shipping_total();          // Shipping total
$order->get_total_tax();               // Total tax

$order->get_payment_method();          // Payment method ID e.g. 'stripe'
$order->get_payment_method_title();    // Human-readable e.g. 'Credit Card (Stripe)'

$order->get_date_created();            // WC_DateTime object
$order->get_date_modified();           // WC_DateTime object
$order->get_date_completed();          // WC_DateTime object (null if not completed)

$order->get_customer_id();             // WordPress user ID (0 for guests)
$order->get_user();                    // WP_User object (false for guests)
$order->get_customer_ip_address();     // IP at time of order
$order->get_customer_note();           // Order note from customer

$order->get_transaction_id();          // Payment gateway transaction ID
$order->get_created_via();             // e.g. 'checkout', 'admin', 'rest-api'

Billing and Shipping Data

// Billing
$order->get_billing_first_name();
$order->get_billing_last_name();
$order->get_billing_company();
$order->get_billing_email();
$order->get_billing_phone();
$order->get_billing_address_1();
$order->get_billing_address_2();
$order->get_billing_city();
$order->get_billing_state();
$order->get_billing_postcode();
$order->get_billing_country();

// Shipping
$order->get_shipping_first_name();
$order->get_shipping_last_name();
$order->get_shipping_company();
$order->get_shipping_address_1();
$order->get_shipping_address_2();
$order->get_shipping_city();
$order->get_shipping_state();
$order->get_shipping_postcode();
$order->get_shipping_country();

Checking Order Status

Use has_status() rather than comparing get_status() directly - it handles the wc- prefix automatically:

if ( $order->has_status( 'completed' ) ) {
    // order is complete
}

// Check multiple statuses at once
if ( $order->has_status( array( 'processing', 'on-hold' ) ) ) {
    // order needs attention
}

Getting All Order Data as an Array

When you need to pass order data to a third-party integration or build a JSON payload, get_data() returns everything as a structured array - no need to call each getter individually:

$order_data = $order->get_data();

// Top-level keys available:
$order_data['id'];
$order_data['status'];
$order_data['currency'];
$order_data['total'];
$order_data['discount_total'];
$order_data['shipping_total'];
$order_data['total_tax'];
$order_data['customer_id'];
$order_data['payment_method'];
$order_data['payment_method_title'];

// Dates are WC_DateTime objects
$order_data['date_created']->date('Y-m-d H:i:s');
$order_data['date_created']->getTimestamp();

// Billing and shipping are nested arrays
$order_data['billing']['email'];
$order_data['billing']['phone'];
$order_data['shipping']['address_1'];

Iterating Through Order Items

Each item in get_items() is a WC_Order_Item_Product object. This is where you access what was actually purchased:

foreach ( $order->get_items() as $item_id => $item ) {

    $product      = $item->get_product();   // WC_Product object
    $product_id   = $item->get_product_id();
    $variation_id = $item->get_variation_id(); // 0 if not a variation
    $item_name    = $item->get_name();
    $quantity     = $item->get_quantity();
    $line_total   = $item->get_total();        // after discounts
    $line_subtotal = $item->get_subtotal();    // before discounts

    // From the product object
    if ( $product ) {
        $sku            = $product->get_sku();
        $product_price  = $product->get_price();
        $stock_qty      = $product->get_stock_quantity();
        $product_type   = $product->get_type(); // 'simple', 'variable', etc.
    }

    // Item meta (custom fields on the line item)
    $item_meta = $item->get_meta( 'your_meta_key' );
}

Other item types available via the $type parameter on get_items(): shipping, tax, coupon, fee.

// Get shipping items
foreach ( $order->get_items( 'shipping' ) as $shipping_item ) {
    $method_title = $shipping_item->get_name();
    $shipping_cost = $shipping_item->get_total();
}

// Get coupons applied
foreach ( $order->get_items( 'coupon' ) as $coupon_item ) {
    $coupon_code    = $coupon_item->get_name();
    $coupon_discount = $coupon_item->get_discount();
}

Order Meta (Custom Fields)

Custom order meta added by plugins or your own code is accessible via get_meta():

// Get a single meta value
$custom_value = $order->get_meta( '_custom_field_key' );

// Get all meta as an array of WC_Meta_Data objects
$all_meta = $order->get_meta_data();
foreach ( $all_meta as $meta ) {
    $meta_data = $meta->get_data();
    // $meta_data['key'], $meta_data['value']
}

Practical Example: Custom Admin Order Column

This is a common real-world use - adding a custom column to the WooCommerce orders list that shows data you frequently reference:

// Add the column header
add_filter( 'manage_woocommerce_page_wc-orders_columns', function( $columns ) {
    $columns['customer_phone'] = 'Phone';
    return $columns;
} );

// Populate the column
add_action( 'manage_woocommerce_page_wc-orders_custom_column', function( $column, $order ) {
    if ( 'customer_phone' === $column ) {
        echo esc_html( $order->get_billing_phone() );
    }
}, 10, 2 );

Note: WooCommerce 7.1+ uses the woocommerce_page_wc-orders screen for the orders list (HPOS). For sites still using the legacy shop_order post type, replace woocommerce_page_wc-orders with edit-shop_order in both hooks.

If you're building a deeper WooCommerce integration - custom order workflows, third-party sync, or a tailored admin experience - I do this kind of work for clients across Toronto and Canada.