Skip to content
Developers

Webhooks

WPReturns sends return events through WooCommerce’s own webhooks with two topics: Return request created (return_request.created) and Return request updated (return_request.updated). You add them in WooCommerce > Settings > Advanced > Webhooks like any other webhook. WooCommerce handles delivery, signing, retries and the delivery log.

Available in: Pro.

TopicName in WooCommerceFires when
return_request.createdReturn request createdA request is saved, from any source: My Account, the guest portal, the withdrawal form, the admin screen or the REST API
return_request.updatedReturn request updatedA request changes status, or a resolution is carried out

Resolving a request triggers the updated topic for the resolution and again for the move to Completed. Build the receiving app to handle the same request more than once. Read status and date_updated to decide what changed.

  1. Go to WooCommerce > Settings > Advanced > Webhooks and select Add webhook.
  2. Enter a Name such as “Returns to helpdesk”.
  3. Set Status to Active.
  4. Pick Return request created or Return request updated under Topic.
  5. Enter the Delivery URL of the receiving app.
  6. Enter a Secret or keep the generated one.
  7. Select Save webhook.

Add a second webhook for the other topic if you need both.

The body is the same request object the REST API returns.

{
"id": 1042,
"number": "RMA-01042",
"order_id": 1042,
"customer_id": 17,
"customer_email": "jane.cooper@example.com",
"customer_name": "Jane Cooper",
"type": "return",
"status": "approved",
"status_label": "Approved",
"resolution": "store_credit",
"customer_note": "The shirt is too small.",
"items_total": 49,
"restocking_fee": 0,
"shipping_fee": 0,
"credit_bonus": 4.9,
"resolution_total": 53.9,
"refunded_total": 0,
"coupon_code": "",
"exchange_order_id": 0,
"tracking_number": "",
"carrier": "",
"assigned_to": 0,
"risk_score": 15,
"risk_flags": ["quick_return"],
"source": "portal",
"returnless": false,
"date_created": "2026-11-02T10:15:00+00:00",
"date_updated": "2026-11-03T09:02:00+00:00",
"date_closed": null,
"items": [
{
"id": 2210,
"order_item_id": 3381,
"product_id": 512,
"variation_id": 515,
"name": "Linen shirt - M",
"qty": 1,
"line_total": 49,
"reason": "wrong-size",
"condition": "unopened",
"exchange_product_id": 0,
"restocked": 0
}
]
}

See REST API for what each field means.

WooCommerce signs each delivery. The X-WC-Webhook-Signature header holds a base64 HMAC-SHA256 of the raw body, keyed with the webhook secret. Other headers name the topic (X-WC-Webhook-Topic), the resource and the delivery ID.

<?php
$secret = 'your-webhook-secret';
$body = file_get_contents( 'php://input' );
$signature = isset( $_SERVER['HTTP_X_WC_WEBHOOK_SIGNATURE'] ) ? $_SERVER['HTTP_X_WC_WEBHOOK_SIGNATURE'] : '';
$expected = base64_encode( hash_hmac( 'sha256', $body, $secret, true ) );
if ( ! hash_equals( $expected, $signature ) ) {
http_response_code( 401 );
exit;
}
$request = json_decode( $body, true );
// Use $request['number'], $request['status'] and the rest here.

WooCommerce queues deliveries through Action Scheduler, and each webhook’s edit screen shows recent deliveries with the response code. WooCommerce turns a webhook off after too many failed deliveries in a row. Check its Status if deliveries stop.

To react inside WordPress instead of over HTTP, use the actions in the Hooks reference.