The real hooks, database schema, and meta keys available for integrating with return/exchange/cancel requests — e.g. a custom notification channel, a shipping-label generator triggered on approval, or a reporting dashboard.

1. Detecting the plugin is active

if ( defined( 'CR_WCREM_VERSION' ) ) {
    // Safe to register the hooks below.
}

2. Lifecycle action hooks

Every meaningful moment in the request lifecycle already fires a plain do_action() — hook these directly rather than polling the database.
wcrem_request_submittedaction
do_action( ‘wcrem_request_submitted’, int $order_id, string $req_type )
Fires immediately after a customer’s (or verified guest’s) return/exchange request is inserted. $req_type is 'return' or 'exchange'.
wcrem_new_request_emailaction
do_action( ‘wcrem_new_request_email’, int $order_id, string $req_type )
Fires alongside wcrem_request_submitted, specifically to trigger the admin notification email. Hook here for anything that should happen whenever you, the store owner, need to know about a new request — a Slack message, for instance.
wcrem_request_response_mailaction
do_action( ‘wcrem_request_response_mail’, int $order_id, string $req_type, string $response, string $coupon_code )
Fires after an admin accepts or declines a request. $response is 'accept' or the decline value; $coupon_code is set only when a return was accepted with a generated coupon.
add_action( 'wcrem_request_response_mail', function ( $order_id, $req_type, $response, $coupon_code ) {
    if ( 'accept' !== $response || 'return' !== $req_type ) {
        return;
    }
    // e.g. notify a fulfillment system that a returned item is expected back.
}, 10, 4 );
wcrem_before_guest_user_formaction
do_action( ‘wcrem_before_guest_user_form’ )
Fires immediately before the [wcrem_guest_user_form] shortcode renders its lookup form — useful for adding your own explanatory copy above it.

3. Customizing email content

Each of the plugin’s three emails exposes its own subject, heading, and body-message filters:
Email Subject filter Heading filter Message filter
New request (to admin) wcrem_new_request_email_subject wcrem_new_request_email_heading wcrem_new_request_message
Request received (to customer) wcrem_request_email_subject wcrem_request_email_heading wcrem_request_message
Request response (to customer) wcrem_request_email_subject wcrem_request_email_heading wcrem_request_response_message
Note: the “request received” and “request response” emails currently share the same default subject/heading filter names and default text (“Return/Exchange Request”) — if you want those two emails to look distinct in an inbox, filter both explicitly rather than relying on the defaults, or set an explicit Subject in each email’s own WooCommerce → Settings → Emails screen instead.
Attachment size is also filterable:
add_filter( 'wcrem_attachment_max_size', function () {
    return 10 * MB_IN_BYTES; // default is 5MB
} );

4. Reading request data

The tracking tables

Table Holds
{$wpdb->prefix}rem_requests One row per request: user, order, type (r/e), status, dates, payment/coupon info, attachments (JSON).
{$wpdb->prefix}rem_requested_product Line items of a request: which products, quantities, and per-item reason.
{$wpdb->prefix}rem_request_reason Admin-defined canned reasons shown in the request form’s dropdown.
global $wpdb;
$requests = $wpdb->get_results( $wpdb->prepare(
    "SELECT r.*, rp.product_id, rp.quantity
     FROM {$wpdb->prefix}rem_requests r
     JOIN {$wpdb->prefix}rem_requested_product rp ON r.id = rp.request_id
     WHERE r.order_id = %d",
    $order_id
) );

Order & product meta

Meta key On Meaning
_wcrem_return / _wcrem_exchange Order line item Set at checkout (woocommerce_thankyou) if that line item’s product is eligible.
_return_request_applied Order Guard flag preventing duplicate requests on the same order.
_exchange_request_order Order The ID of the child order created for an accepted exchange.
_wcrem_product_settings Product Serialized array with allow_return/allow_exchange — set via Product → Advanced.
// Always via the order object — never get_post_meta()/update_post_meta(),
// which silently break under HPOS (High-Performance Order Storage).
$order = wc_get_order( $order_id );
$exchange_order_id = $order->get_meta( '_exchange_request_order' );

5. Best practices

  • Never touch order data with get_post_meta()/update_post_meta(). Always go through $order->get_meta() / update_meta_data() / save().
  • Don’t edit any file inside the base plugin. A direct patch won’t survive an update — use the hooks above instead.
  • Check $req_type explicitly in any hook you attach to — several fire for both returns and exchanges with the same signature.
  • Sanitize and escape exactly as you would anywhere else in WordPress — none of these hooks do it for you.

6. Worked example

A minimal companion plugin that posts to a Slack webhook whenever a return is accepted:
<?php
/**
 * Plugin Name: RMA — Slack Notifications
 * Description: Posts to Slack when a return request is accepted.
 * Requires Plugins: woocommerce-return-management
 */

if ( ! defined( 'CR_WCREM_VERSION' ) ) {
    return;
}

add_action( 'wcrem_request_response_mail', function ( $order_id, $req_type, $response, $coupon_code ) {
    if ( 'accept' !== $response || 'return' !== $req_type ) {
        return;
    }

    $order = wc_get_order( $order_id );
    $message = sprintf(
        'Return accepted for order #%d (%s)%s',
        $order_id,
        $order->get_billing_email(),
        $coupon_code ? " — coupon issued: {$coupon_code}" : ''
    );

    wp_remote_post( 'https://hooks.slack.com/services/...', array(
        'body' => wp_json_encode( array( 'text' => $message ) ),
        'headers' => array( 'Content-Type' => 'application/json' ),
    ) );
}, 10, 4 );