Magento 2 RMA & Returns Management Extension

View Demo

Let customers request refunds, exchanges and store credit from their account, even as guests or for offline purchases. Your team handles every return in one admin grid, with workflow rules setting statuses, assigning managers and sending emails.

  • One admin grid for all returns, exchanges and credit memos
  • Workflow rules set status and manager automatically
  • One-click replacement orders
  • Guest returns and offline-order returns
  • Custom statuses, reasons and resolutions
  • REST and GraphQL API
Marketplace Approved
Hyvä
Magento Cloud
GraphQL
WCAG
Mage-OS
Compatible with:
Community:
2.3.* - 2.4.9
Enterprise:
2.3.* - 2.4.9
Problem

Magento Open Source has no returns management. Return requests arrive by email, someone checks each order by hand, and refunds, exchanges and return labels are handled one message at a time. Customers can't see where their return stands, so they write again.

Solution

Customers request a refund, exchange or store credit from their account, even as guests or for purchases made offline. Your team handles every request in one admin grid, while workflow rules set the status, assign a manager and send the emails.

Is it worth it for your store?

What you get

Customers handle returns from their account, workflow rules move statuses and send emails. Used by 1,000+ stores.

What it takes

Minutes. Statuses, emails and reasons come pre-filled; you add your return address. Installation is free.

What you risk

Nothing in your orders changes: returns live in their own tables, refunds use standard Magento credit memos. 30-day money-back guarantee.

RMA for Magento 2 main features

  • Refunds, exchanges, store credit and one-click replacement orders
  • Returns from guests and for offline orders that aren't in your database
  • Returns from several orders in one RMA
  • Workflow rules that set statuses, assign managers and send emails
  • Reports by reason, product and any product attribute, with CSV/Excel export
  • REST and GraphQL API, Hyvä support, Magento Open Source and Adobe Commerce 2.3–2.4.9

Returns, exchanges and refunds in one place

Customers choose how to settle a return: refund, exchange or store credit, for a whole order or part of it. Our guide on simplifying Magento returns shows the full process step by step. The extension works with multistore setups: statuses, messages and quick responses can differ per store view.

Refunds, Exchanges, Store Credit

Customers send a refund request or ask for an exchange. Store credit is a ready-made resolution: the manager opens a credit memo from the RMA and refunds the amount to the customer's balance. This needs a store credit feature, such as Mirasvit Store Credit & Refund or the one built into Adobe Commerce.

Partial Returns

For an order of several products, customers return only the items that don't suit them and set the quantity for each. There's no need to refund the entire order.

Product Returns for Offline Orders

Customers can open an RMA for goods bought by phone, in your physical store or on another site in your network, even when your store database has no record of the order. The option is off by default.

RMA for Guests

Customers who bought as guests open a return with their order number and email. No account is needed to return or exchange products.

One-click replacement orders

When an item needs replacing, the manager creates the replacement order from the RMA in one click: a zero-price order with free payment and free shipping, sent to the address from the original order and linked to the RMA.

Exchange orders and credit memos from the RMA

Exchange orders and credit memos open from the RMA in the standard Magento forms and stay linked to it, so their numbers show in the RMA grid and its export.

Set up the RMA workflow your way

Set up reasons, resolutions, statuses, fields and emails to match your own return policy.

Return reasons list in the RMA settings

Return reasons

Customers pick the return reason from a list you define. Reasons can be grouped into parent and child reasons.

RMA resolutions settings

RMA resolutions

Exchange, refund and store credit come ready, and you can add your own resolutions, such as repair. Each resolution decides which buttons the manager gets on the RMA: exchange order, replacement order or credit memo.

Custom RMA statuses with color coding

Custom RMA request statuses

Show customers which stage their RMA is at. Each status has its own color and its own emails to the customer and the admin, sent when the RMA reaches it. Color coding helps customers and store admins distinguish statuses at a glance.

Workflow rules

A rule runs on an event: a new RMA, a change to an RMA, a new reply from the customer or from staff, or an hourly check. It tests conditions such as status and status before the change, owner, who replied last, hours since the last reply, whether a return label is attached, the reason or resolution, custom fields, and product attributes or categories. Then it sets the status or owner, marks the RMA resolved and sends emails to the owner, the customer or any address.

For example, a rule can:

  • Approve a return automatically when the reason and item condition match your policy
  • Close an RMA and email the customer after 72 hours without a reply
  • Email the manager when an approved RMA still has no return label after 24 hours

See the workflow rules guide for all events, conditions and actions.

Store any RMA information in custom fields

Custom fields on an RMA

Store any additional information on an RMA in custom fields: text, date, checkbox or drop-down. Fields can be required, visible or editable for the customer, shown only at certain statuses, and set for each returned item, not only for the whole RMA.

For example, a field on the Confirm Shipping step lets the customer enter the carrier and tracking number of the parcel they sent back.

RMA email notification template

Custom email notifications

Emails go out automatically on the RMA events you choose, to customers and staff. Templates use Magento's standard variables plus the module's own, so each email can name the customer, the RMA and its status.

Full RMA transparency for customers

Customers open an RMA and follow every status change from their account. A message thread on each RMA keeps the full communication history in one place.

Intuitive RMA workflow

RMA page in the customer account

Customers start a return from the RMA section of their account or with the return button in their order history. A progress bar shows where the request stands.

The RMA page shows all information relevant to the request: product name and SKU, quantity returned, return reason and the resolution the customer wants.

Message thread on an RMA

Convenient communication

Shoppers discuss any issue with store managers in the message thread on the RMA. For example, a customer may ask for a prepaid return label. With Mirasvit Help Desk installed, customers can also reply by email and their answers land in the same thread.

Customers can review the communication history at any time.

File attachments on an RMA message

Attach files to RMA requests

Customers add photos and documents to their RMA request, several files at once, and managers see the images right in the message history. Uploads are limited to the file types and size you allow, and each file is checked against its type.

Simplify RMA workload for store managers

Store managers get all the tools they need to handle returns fast, in a single section of the Magento admin panel.

RMA grid in the Magento admin

Magento 2 returns management in one grid

Store admins monitor all RMAs in one grid. Status color coding lets you tell statuses apart at a glance, and managers can filter the grid by status, company or customer email. Export the grid to CSV or Excel XML, with the linked exchange, replacement and credit memo numbers.

Full history of an RMA in the admin

Full communication history on each RMA

Store managers can quickly refresh their memory on any RMA by checking its full history of messages, status changes and files. Internal notes stay visible to the store team only.

Quick responses list

Quick responses

Predefine standard answers, for example, a link to print a return shipping label, and set them per store view. Store admins simply pick the answer from the list to send it in seconds.

Return label upload in the RMA admin

Return labels and packing slips

Store managers upload a prepaid return label from any carrier as an image or PDF. The customer prints it from their account and clicks Confirm Shipping, which moves the RMA to Package Sent. Each RMA also has a printable packing slip with your return address.

Help Desk integration support

Connect RMA with the Mirasvit Help Desk extension. Customer emails about a return land in the RMA thread, and managers can open an RMA from a ticket or a ticket from an RMA.

RMA policy settings

Craft your RMA Policy

Fit the RMA policy to your needs by configuring its main parameters:

  • Number of days after order completion during which an RMA can be requested
  • Allow RMA requests only for orders with specific statuses
  • Combine returns from several orders in one RMA
  • Request only shipped products
  • Exclude specific products from returns
  • Ask customers to confirm agreement with your return and exchange policy
  • Show customers a block with the RMA policy agreement

Built-in RMA reports

Analyze returns with reports:

  • by status
  • by reason
  • by product
  • by offline product
  • by any product attribute, such as brand
RMA reports by reason and status

Reports show the number of RMAs per status, period and customer, and the total number of products returned. Export them to CSV or Excel XML for further analysis or archive storage.

REST and GraphQL API

GraphQL API for RMA

Use the GraphQL API to build returns into a PWA or headless storefront: customers create RMAs, send messages with attachments, check the status and print the packing slip and label.

The REST API covers the back office: create, read, update and delete RMAs, items, messages, statuses, reasons, resolutions, custom fields, quick responses and workflow rules, change statuses in bulk, create replacement orders and confirm shipping. Customer and guest endpoints are included. See the REST API and GraphQL API guides.

Workflow rules, reports with export, both APIs and the Hyvä compatibility package are part of the extension, not separate tiers or add-ons. The extension works on Magento Open Source and Adobe Commerce 2.3–2.4.9 and Mage-OS, and meets WCAG 2.2 AA.

What the extension doesn't do

  • It doesn't generate carrier labels or track parcels. You upload a label you got from your carrier, and the customer confirms the shipment.
  • It doesn't refund money on its own. The manager confirms the amounts in the standard Magento credit memo.
  • Refunds to store credit need a store credit feature: Mirasvit Store Credit & Refund or the one in Adobe Commerce.
No hidden fees
Our developers install the extension on your store and configure it for your setup, free of charge.
Lifetime access to source code
Access to free support and updates for 1 year
Updates and support prolongation - $108

Pay today $179 for the first year.

Then $108 for updates and support services per year.

Cancel anytime.

30 days money back guarantee
See it in action!
Pick a quick tutorial to learn about various aspects of this extension
Customer Reviews 107
Earn points for your review about this extension modules. $1 = 10 points
Write Your Own Review

check-circle You submitted your review for moderation.

BBMC Verified Buyer
From Carol Stream, United States
Using the module for over 3 years
A complete return-management system rather than a basic RMA form
Any ecommerce business processing a meaningful number of returns needs a proper RMA system, and Mirasvit provides a very complete one.

It handles both online and offline returns and integrates directly with Magento orders, refunds and customer information. Statuses, communications, return terms and other parts of the process can be customized extensively. The included templates cover the normal stages of a return, while stores can also create their own.

Administration is straightforward and the extension has been reliable for us.

The biggest feature I would like added is a visual customer return-flow builder. It would be useful to define a step-by-step sequence—return reason, order selection, purchase date, additional information, eligibility checks, and then different available resolutions depending on the answers.
Also installed:
Help Desk MX,  Knowledge Base,  Full Page Cache Warmer,  Advanced Product Feeds,  Follow Up Email,  Reward Points,  Promo Banners and 28 more
Alex Verified Buyer
From United States
Using the module for over 1 month
Effective RMA solution with room for UI/UX improvement
This extension is a powerful and intuitive tool for managing authorized returns (RMA). It automates many key steps in the returns process, integrates smoothly with existing order management systems, offers customization options, and provides detailed analytics on return trends. The only downside is that the UI/UX design could be improved.
BB Verified Buyer
From Carol Stream, United States
Using the module for over 3 years
Best RMA extension for Magento
I have tried 3 RMA extensions for our store and this is by far the most comprehensive, yet easiest to manage.

I would like to see a possible way to integrate exchanges that can be preauthorized for a "ship first and return later" exchange method, but other than that, this is the one to get.
Also installed:
Help Desk MX,  Knowledge Base,  Full Page Cache Warmer,  Advanced Product Feeds,  Follow Up Email,  Reward Points,  Promo Banners and 28 more
Paolo Verified Buyer
From Gandino, Italy
Using the module for over 3 years
Great extension for managing returns.
The module for managing authorized returns (RMA) is an effective and intuitive solution that automates many critical phases of the returns process. It integrates easily with existing order management systems, offers customization options, and provides detailed analytics on return trends.
Also installed:
Product Kits ,  Automatic Related Products,  Help Desk MX,  Follow Up Email,  Reward Points,  Elastic Search Ultimate,  Advanced Product Feeds and 25 more
Pedro Verified Buyer
From Seixal, Portugal
Using the module for over 2 years
Very nice extension
The extension works very nicely. We had to do some tunning for our client needs, but now it's flying.
Also installed:
Reward Points,  Follow Up Email,  Customer Segmentation Suite,  Advanced Product Feeds,  Custom Form Builder ,  Help Desk MX,  Improved Sorting and 7 more
Manual & Support
Need more help?

Save time by starting your support request online and we'll connect you to an expert.

Frequently asked questions
chevron-down chevron-right

Does Magento 2 have a built-in RMA?

Magento Open Source has no returns module: return requests come by email and refunds are done by hand. Adobe Commerce includes a native Returns feature.

This extension works on both. On Adobe Commerce it runs alongside native Returns without changing it, and adds your own statuses with emails, workflow rules with timers, quick responses, returns for offline orders, several orders in one RMA, one-click replacement orders and RMA reports with export. Native Returns can generate carrier labels; this extension doesn't, you upload the label instead.

chevron-down chevron-right

How does a return work with this extension?

  • The customer opens an RMA from their account, the order history or the guest form, picks the items and quantities, and chooses a reason and resolution.
  • The manager approves it, by hand or with a workflow rule. The approval email carries the packing slip, the return label if you uploaded one, and your return address.
  • The customer ships the parcel and clicks Confirm Shipping.
  • The manager settles the RMA with a credit memo, an exchange order or a one-click replacement order.

The administrator can also create an RMA on behalf of a customer from the order page in the backend. See how to process an RMA.

chevron-down chevron-right

What do I need to set up after installation?

Very little, and it takes minutes. Customers can open returns right after installation: five statuses with colors and emails, return reasons, item conditions and three resolutions come pre-filled. You add your return address. Workflow rules, quick responses, offline returns and the Help Desk integration are optional. Installation is free.

chevron-down chevron-right

Does the extension include store credit?

Store credit is one of the ready-made resolutions. The manager opens a credit memo from the RMA and refunds the amount to the customer's balance. The balance itself needs a store credit feature: Mirasvit Store Credit & Refund or the one built into Adobe Commerce. The RMA extension takes into account credit already refunded with Mirasvit Store Credit.

chevron-down chevron-right

Can customers return only some items from an order?

Yes. Customers choose which items to return and the quantity of each. For example, a customer can return just one or two of the five items they bought. You can also let them combine items from several orders in one RMA, or allow returns only for shipped products.

chevron-down chevron-right

How do guests open a return?

Guests open a return with their order number and email, without an account, and then follow the RMA and reply to the store from its page. A guest form doesn't accept an online order that belongs to a registered customer: that customer returns it from their account. You can hide the guest return link in the store footer.

chevron-down chevron-right

Does the RMA extension support returns for offline orders?

Yes. Customers can open an RMA for products bought by phone, in your physical store or on another site connected to your store network, even when your store database has no record of the order. The customer enters the receipt number, and you can ask for a phone number.

Offline returns have their own custom fields and their own report. The option is off by default, so you decide whether to allow it.

chevron-down chevron-right

What can RMA workflow rules do?

A rule runs on an event: a new RMA, a change to an RMA, a new reply from the customer or from staff, or an hourly check. It checks conditions such as status, owner, who replied last, hours since the last reply, whether a return label is attached, the reason or resolution, custom fields and product attributes. Then it sets the status or owner, marks the RMA resolved and sends emails to the owner, the customer or any address.

For example, a rule can approve a return automatically when the reason matches your policy, or close an RMA after 72 hours without a reply from the customer. See the workflow rules guide.

chevron-down chevron-right

How do return shipping labels work?

The manager uploads a prepaid return label from any carrier as an image or PDF. The customer prints it from their account and clicks Confirm Shipping, which moves the RMA to Package Sent; a custom field on that step can collect the tracking number. Every RMA also has a printable packing slip with your return address.

Uploads are limited to the file types you allow, and the content of each label file is checked. The extension doesn't generate labels through carriers or track parcels.

chevron-down chevron-right

Does the RMA extension keep the full communication history on each RMA?

Yes. Every message to the customer, every status change and every attached file stays on the RMA, and both the customer and the store team can see them. Staff can also add internal notes that only the store team sees. Managers can answer faster with quick responses, set per store view. With Mirasvit Help Desk, customers can also reply by email and their answers land in the RMA thread.

chevron-down chevron-right

Can I set my own reasons, conditions, statuses and resolutions?

Yes. Create your own return reasons (grouped into parent and child reasons if you like), item conditions, statuses with their own names, colors and emails, and resolutions. Each resolution decides which buttons the manager gets on the RMA: exchange order, replacement order or credit memo.

For example, offer a refund to store credit to encourage the customer to buy from you again.

chevron-down chevron-right

Is the Hyvä package included?

Yes. Hyvä support comes as a separate compatibility package, mirasvit/module-rma-hyva, included with the license. You install it with one Composer command, as described in the user guide.

chevron-down chevron-right

Does the RMA extension support REST API and GraphQL?

Yes, both. GraphQL serves the storefront: PWA and headless stores can create RMAs, send messages with attachments and show the status. The REST API serves the back office: it manages RMAs, items, messages, statuses, reasons, resolutions, custom fields, quick responses and workflow rules, and can create replacement orders and confirm shipping. Customer and guest endpoints are included.

Learn more in the REST API and GraphQL API guides.

Changelog
Version 2.5.0Oct 20, 2026
Hyvä and GraphQl support now ship with the extension - The two companion packages, mirasvit/module-rma-hyva and mirasvit/module-rma-graph-ql, are retired: everything they contained is part of RMA itself. That is the Hyvä storefront for the whole returns flow - the request form, the guest and offline forms, the RMA list, the RMA view with its messages and attachments, the returns column in order history and the My Returns link in the account menu - and the customerRmas, guestCustomerRmas, rmaDictionary and orderRmas queries with the createRma and addRmaMessage mutations used by headless and PWA storefronts. Each storefront page now has one template and one plain-JavaScript script for both themes, so Luma and Hyvä behave the same way. There is no longer a second package to find and keep in step, and on a Luma store the Hyvä part simply stays dormant. Composer removes the companion packages by itself when you upgrade.
A new attachment control on the RMA forms - The request forms, the message form and the admin reply form now list the chosen files, with a thumbnail for images, accept drag and drop, and let a file be taken off the list before sending. A file of a type you do not allow, or over your size limit, is refused while the customer is still on the form instead of after a failed submit, and the refusal says why: "that file type is not allowed" or "it is larger than 2.0 MB". Choosing files again adds to the list instead of replacing it. The file picker's own filter now honours Allow attachment upload with extensions (it never did before), and a store with no size limit set falls back to PHP's upload ceiling. The admin reply form takes its limits from the RMA's own store view. Without JavaScript the plain file input still works.
Attachment previews open in a gallery on Hyvä - A click on an image attachment in the RMA view opens it in place, as Luma has always done, instead of leaving the page. The gallery walks every previewable attachment on the page with on-screen arrows or the left and right keys, shows the position (2/6), preloads the neighbours, and closes on the backdrop, the close button or Escape. A click on the picture zooms it. Files without a preview are listed as framed rows with the file name in bold, as on Luma.
⚠️ The mstRma GraphQl queries now answer on every store - Previously the schema arrived with an optional package, so customerRmas, rmaDictionary, orderRmas, guestCustomerRmas, createRma and addRmaMessage existed only where that package had been installed. They now ship with the extension and apply everywhere. That is the intended change, but it is a change in behaviour on upgrade for anyone querying /graphql: those fields appear in your schema whether or not you asked for them, and any tooling that introspects the schema will see them.
⚠️ The Hyvä module is gone, not renamed - Hyva_MirasvitRma no longer exists in any form. Everything it did now happens inside Mirasvit_Rma: each storefront page has one template for both themes, and hyva_-prefixed layout files set what only Hyvä needs. setup:upgrade removes the old name from app/etc/config.php for you. You only need to act if you referenced it yourself - in a custom di.xml, a layout file, or a deployment script that enables modules by name.
⚠️ Hyvä stores: run bin/magento hyva:config:generate and rebuild your theme after upgrading - Retiring the companion package took RMA off the list of modules Hyvä's Tailwind build scans, and the extension now registers itself there. Until you regenerate that list and run npm run build in your theme, utility classes the RMA templates use are purged from the built stylesheet. The extension's own styling - status badges, the progress bar, the unread marker, the box treatment, the dialogs and the layout of every RMA page - ships as a plain stylesheet that needs no build and loads only on the RMA pages, so the pages are usable either way and the rest of your store is not affected, but the rebuild is what makes them complete.
⚠️ Re-check your theme's overrides of RMA storefront templates - The Luma and Hyvä copies are merged into one template per page, driven by plain JavaScript (js/rma-new-form.js, js/rma-attachments.js) instead of Knockout on Luma and Alpine on Hyvä. A Hyvä override under Hyva_MirasvitRma/templates/… no longer applies; move it to Mirasvit_Rma/templates/… under the shared name. A Luma override of rma/new.phtml or the message form copied from an earlier version still asks for the removed Mirasvit_Rma/js/create-rma component or the removed jQuery MultiFile (jqueryMultiFile, js/multifile/); rebuild it from the new template.
⚠️ GraphQl attachments now obey your attachment settings - An attachment sent through the createRma or addRmaMessage mutation is now checked against Allow attachment upload with extensions and Limit of attachments size, Mb (RMA configuration, File Upload Settings), exactly as a file uploaded through the storefront form. Until now GraphQl stored any file. The extension list has a default (images, PDF, office documents, text/CSV and archives), so even if you never changed it, a mutation sending another type, such as .exe, now fails with "Uploaded file does not match requirements" instead of saving. The size limit has no default and applies only if you set one. Every attachment, including that it is valid base64, is checked before anything is saved, so a refused file leaves no return or message behind.
The RMA GraphQl resolvers no longer need magento/module-customer-graph-ql. They identify the signed-in customer themselves (token, account not locked or awaiting confirmation, account of the current website), so a store that strips Magento's GraphQl modules with a composer replace still compiles.
The message history reads as a conversation on both themes. Messages from the store sit on the left and the customer's on the right, each bubble capped at 78% of the column, with the author line and the tail following its bubble. An automatic status notice sits centred and full width, in its own neutral colour on Hyvä too, so a line the system wrote no longer looks like one somebody typed. The history box no longer scrolls inside the page.
Status chips are readable on both themes. Each chip keeps the hue the administrator picked but shows it as a tint behind a darker label of the same hue, so every label meets the 4.5:1 contrast body text needs. Twelve of the sixteen palette colours failed it before, and a black status printed its label in black on black.
The RMA pages on Hyvä follow your theme's palette. The greys, the link blue and the reply green come from the theme's own colour tokens, with the previous values as the fallback, so a Hyvä store that retunes its theme colours retunes the RMA pages with it.
More storefront text is translatable. The RMA column heading in the order history on Luma, the "Order or Receipt #" tooltip and the "Item Name" tooltip on the offline form were printed in English whatever the store locale; the order picker on the request form now has a label for screen readers; and the Remove control on a selected order can be reached from the keyboard on Hyvä.
⚠️ createRma can no longer take over another customer's return. A custom field code in the input was written into the RMA as is, so rma_id, customer_id or status_id sent as custom fields loaded and reassigned an existing RMA. Only active fields a customer may fill in on the storefront form are accepted now; any other code is refused.
⚠️ createRma only accepts orders the caller owns. A signed-in customer can return only their own orders, a guest only a guest order placed with the e-mail they gave, and the order must belong to the current website.
⚠️ createRma now applies the return period and the RMA policy. An order last updated longer ago than Return Period is refused, as the storefront form refuses it, and when the RMA policy is active the request must send agree_box: true. Until now GraphQl accepted any order in an allowed status and ignored agree_box.
⚠️ guestCustomerRmas now checks the e-mail it asks for. The query declared customer_email as required but never read it, so an order id alone listed another guest's returns. The order and e-mail pair is now checked the way the guest storefront form checks it. A store with guest access off answers with an authorization error instead of a bare internal server error, an unknown order id answers "not found", and each return in the list now carries its rma_id, which was always null.
createRma works for a return of offline orders only. It answered "Please select an order for the RMA." and left the offline order it had created behind, one more with every retry. If the return cannot be saved, the offline orders created for it are now removed. Offline items take their name from the new optional name field of RmaItemInput, or from product_sku when it is not sent.
Each order in the orders of customerRmas, guestCustomerRmas and createRma lists only its own items. An RMA of two orders listed the items of both under each, and an offline order listed the store order's items.
Hyvä: the request form requires the policy box. With Ask to agree with RMA policy text on, only Luma's validation enforced the "I agree" box, so on Hyvä a return could be created without accepting the policy.
createRma with attachments and no reply creates the return. It failed with "Please, enter a message". A GraphQl attachment can also carry its MIME type in the new optional type field of RmaMessageAttachmentInput; without it the file is stored as application/octet-stream, as before.
The request form no longer fails to render its policy when no policy block is chosen. With Ask to agree with RMA policy text on and no CMS block selected, the form logged Argument 'value' must be type of string, NULL given; it now shows the "I agree" box with no policy text.
The policy's "I agree" box shows the required-field asterisk on both themes. It was always required but carried no asterisk.
orderRmas now requires the signed-in customer who placed the order. It used to list the returns of any order id for anyone.
The createRma and addRmaMessage GraphQl mutations no longer fail for a signed-in customer. Both answered Internal server error for every logged-in customer: the resolver passed Magento's customer data object into a service that requires the customer model, so the request died before it reached the returns logic. Guest requests were unaffected. Both mutations now create the return, and the message is recorded against the right customer name.
A message can be an attachment alone again. Since 2.4.0 a reply with a file and no text was refused with "text" is required, although the form allows it. A message that fails now also returns the customer to the return with the reason, instead of adding "RMA does not exist" and leaving for the list.
Luma: a second order can be added to a return opened from an order. When a customer started a return from an order's page and then picked another order and pressed Apply, the form read the first order again, said "Order already exists in current RMA" and never added the second one. It now adds the order that was picked.
Hyvä: the request form no longer submits a return with no items selected. It now asks the customer to select an order and the items to return, as Luma always has.
Luma: a date custom field no longer logs "Script error for calendar". The storefront input is the browser's native date picker; the admin-only calendar widget init is no longer rendered with it.
The rmaDictionary query no longer breaks on a store with an empty vocabulary. If a store view had no return conditions, no reasons or no resolutions configured, the query answered with an undefined value in that part of the response instead of an empty list.
A guest offline return no longer records an undefined customer. When an offline return was created through createRma by a guest, the customer id written to the request came from a variable that was only ever set for signed-in customers.
guestCustomerRmas now reports a missing order id properly. A query without order_id produced a PHP warning rather than the input error every other RMA query returns for the same mistake.
Every value the Hyvä storefront prints is now escaped. The Hyvä templates were carrying 183 unescaped outputs, inherited from the companion package, which had no static checks of its own. Pages render exactly as before; the values simply cannot be read as page markup any more.
A status message left blank at a store view again means "do not send" there. Clearing the customer, administrator or history message of a status for one store view now stores that blank as the store view's own setting, as the field's "Leave blank to not send" hint promises, instead of falling back to the All Store Views text. Clearing it at All Store Views clears only the default text. A message that cannot be saved now raises an error instead of being silently wiped.
Saving a name at a store view no longer overwrites All Store Views. Editing the store-view text of a status, reason, condition, resolution, custom field or workflow rule copied that text into the All Store Views value whenever the default was empty, and clearing a store-view text left an empty override instead of falling back to the default. Each store view now keeps its own text, and a cleared one shows the All Store Views text again.
A long word or link in a message no longer runs out of its bubble. An unbroken run of characters - a long URL, a tracking number - pushed the message past the column in the customer's RMA view and in the admin RMA conversation. It now wraps inside the bubble.
The Hyvä RMA pages are laid out properly, on a desktop and on a phone. In Hyvä's narrower account column the RMA view now stacks the message form and history full width, keeps the status bar on one line, keeps product thumbnails visible at a sensible size, and shows order numbers and links in a link colour instead of plain grey text. On a phone, the RMA view and the request form no longer scroll sideways, and long order or reason options no longer widen their dropdowns past the screen. The "Show N per page" control in the order's Returns tab no longer breaks onto two lines, and the message box keeps its border while you type. The Confirm Shipping dialog opens centred on the screen, and the instructions inside it wrap.
Version 2.4.21Oct 16, 2026
⚠️ RMA Free Shipping has a new carrier code, rmafree - The old code rma_free_shipping contained the underscore Magento uses to join the carrier and the method into the rate code it stores, so a replacement order shipped with it read back as carrier rma, which does not exist. Anything that looks the carrier up from an order - Order::getShippingMethod(true), a shipping or ERP integration, a payment provider's callback - found none. setup:upgrade moves your saved settings from carriers/rma_free_shipping/* to carriers/rmafree/* in every scope and rewrites the rate code on existing orders and quotes from rma_free_shipping_rma_free_shipping to rmafree_rmafree. You only need to act if you refer to the old code or path yourself: in custom code, in settings locked in app/etc/config.php or env.php, or in reports that filter on the shipping method.
A replacement order that cannot be created is now reported as an error. When Replacement Order on an RMA was refused - because the RMA Free Shipping method is disabled, or no item has the resolution "Replacement" - the reason was shown as a green success message. It is now a red error message.
Exchange orders created from an RMA are linked to it again. Since 2.4.18, an order placed with the Exchange Order button on an RMA was saved but not attached to the return, so it did not appear among the RMA's exchange orders. The return is now remembered through the whole order-create page - including its background requests, such as the admin notification bar refreshing - until the order is submitted, and forgotten only once you leave order creation.
Version 2.4.20Oct 7, 2026
Let admin employees create offline RMAs regardless of customer toggle
Version 2.4.19Oct 5, 2026
Added item-level custom fields.
Selecting an offline order added two RMA items at once.
Check a field's reserved code on every target table and on rename
Reject guest return for a registered customer's order
Let a merchant-facing refusal out of Condition and Rule delete()
Update an offline order that already has a row instead of inserting a duplicate
Drop ReasonRepository::getByCode(), which filtered on a column mst_rma_reason has not
Resolve an RMA's store before the write instead of reporting oneand storing another
Retype accessory to the int it stores, retire the dead order_id key
Stop normalising a return code into a column that does not exist
Copy helpdesk email attachments onto item_type/item_id
Api\Data id constants that name the wrong column
Saving an RMA warned on items missing reason/resolution/condition
Version 2.4.18Sep 30, 2026
Customer column in RMA reports — RMA reports can now be grouped and filtered by the customer recorded on the return itself, instead of only reaching the customer through the order.
Works with Mirasvit Core 2.0 — the module no longer relies on the core helpers that Core 2.0 removes. Template variables, text utilities, product images and data serialization now use the module's own code or native Magento. Email templates and their [variable] / {variable} syntax work exactly as before.
⚠️ Stored values converted to JSON — a new data patch converts old PHP-serialized values to JSON. This covers the localized names and messages of statuses, reasons, conditions, resolutions and custom fields, rule names and email texts, the return status history, and item product options. Run bin/magento setup:upgrade after updating, and back up the database first.
Safer message attachments — message attachments are now checked against an allow-list of file types (by default: images, PDF, office documents, text/CSV and archives). A file whose content doesn't match its extension is refused. Downloads now take their file type from the file itself, not from what the uploader claimed.
Accurate "last reply" date — a return's last-reply date now changes only when a reply is posted, not on every save.
Clearer messages on the new-return form — the form used to reload silently when a customer picked items from more than one order, or left a required reason, condition or resolution empty. It now tells the customer what to change.
Re-running setup is safe — re-applying the module's install patches no longer stops setup:upgrade with a duplicate-key error, and never resets statuses you edited. It also no longer adds duplicate order status history, which inflated "time in status" report figures.
⚠️ Removed features that never worked — the RMA tab block for the admin order view and its layout (the tab was never shown), the "Update the Product" rule action and the "PHP" rule condition are gone. A rule saved with the PHP condition now just doesn't match. Customizations that reference the removed block need updating.
RMA pages load faster — the return workflow now loads in a single query instead of one query per status (a twenty-status workflow previously cost twenty queries per page view), and a return's order is resolved once per page instead of on every read.
Fewer queries on the new-return form — the reason, condition and resolution lists are now read once per page instead of twice. The Hyvä theme reads the same lists and gets the same saving.
Deleting an order or an order line no longer leaves broken links on returns — the return and its lines are kept, as a merchant has to keep the record: returned lines fall back to the product name and SKU stored on the return, and the order's return status history is removed with it.
Deleting a customer account no longer breaks their walk-in returns — offline (walk-in) returns stay and are still found by receipt number; only the link to the deleted account is dropped.
⚠️ Return report relations corrected — three relations between returns, return items and order items were declared the wrong way round, so a report combining a return with its items could show an arbitrary item row instead of an aggregated total. Saved reports built on those combinations are worth re-checking.
⚠️ Unused code removed — the duplicate uiform admin route, three admin actions that never worked (Exchange, Export CSV, Export XML), 17 unreferenced PHP classes and six templates nothing rendered have been deleted. Grid export from the RMA list is unaffected and still works. Customizations that extend or reference the removed classes and route need updating.
The return form offered items that were already returned — the new-return form showed each order line's full shipped quantity, ignoring earlier returns, and then rejected the request because a return already existed. It now offers only the quantity that can still be returned.
Guests couldn't open returns for some offline orders — the guest return login failed with an error for offline orders with no linked customer. It also didn't find offline orders whose email or last name had capital letters.
Rule conditions on the last message and on item reasons didn't work — "Last message contains / does not contain" always gave the same answer, and rules using it crashed on new returns that had no messages yet. "Items have reason / condition / resolution is not …" never matched.
Condition rows in the rule editor shared one field ID — each condition row now gets its own ID, so rows no longer interfere with each other.
Creating a replacement order showed an error even though it worked — the admin saw an error page after the order was placed, and retrying created a second replacement order.
Exchange orders were added to the wrong return — after an admin created an exchange order from one return, every later order they placed in the same admin session was also added to that return.
Saving a new return with no items showed an error page — the admin now goes back to the New RMA form and sees the "Items are required" message.
A custom field couldn't be saved with no customer statuses selected — it now saves with an empty selection.
Resolution mass delete reported the wrong count — skipped reserved resolutions were counted as deleted in the success message.
Admin notification emails crashed when variable parsing was on — they now send, with their attachments.
Some messages failed to save with a database error — a message with no admin author is now stored correctly.
Return items marked "not offline" were saved as offline items on an online order.
Saving several returns in one run (API, import, cron) failed — the second save in the same process stopped with an error.
Records could show outdated values after an edit — statuses, reasons, conditions, resolutions and other records looked up by code or name could return their old values, or a deleted record, for the rest of the same request.
Attachments updated through the API were stored encoded — they're now stored as the actual file and download correctly.
Attachment downloads failed on PHP 8.5 — they now work.
The admin RMA page logged image errors for products with no image — the admin placeholder image is shown instead.
The admin RMA grid didn't load on older Mirasvit Core versions — the QuickDataBar tiles crashed with a constructor error.
Selecting an offline order added two return items at once — on the new-return page opened for a specific order, the create-RMA script was initialised a second time, so every "Add Item" click fired twice and added two rows. It now initialises once.
Customers could not submit returns on the Luma theme — the new-return form, the message reply form, the return action buttons and the guest offline-return form did not include a form key, so Magento rejected the submission with "Invalid Form Key. Please refresh the page." and bounced the shopper back to the form they had just filled in. Guest returns were hit hardest, with no account page to retry from.
⚠️ Return creation now accepts POST only — the return-save URL also answered GET, so a crafted link or image on any page could create a return against a signed-in customer's order. The shipping-confirmation link sent in email still works exactly as before.
⚠️ A registered customer's order could be opened through the guest return form — the guest gate accepted any online order whose number matched, so anyone who knew a registered customer's order increment id and their email or surname (both routinely visible) could open that order and file a return against it. An online order placed from an account must now be requested while signed in; on the public guest form it is refused exactly as a wrong order number or email is. Guest orders are unaffected.
Wrong orders could end up on an admin return — in the admin "Create RMA" flow, a missing or non-numeric order id was silently skipped, so the next id quietly became the first order of the return, and an invalid ticket id was stored as given. The selection is now checked before any order is loaded, and an invalid one sends the admin back to the order selector with an error instead.
The admin "Add RMA" page for an offline order failed when no customer was selected — it errored with "An ID is needed. Set the ID and try again." instead of rendering the offline return form.
Required Reason / Condition / Resolution dropdowns with nothing to choose from — deactivating or deleting the last active reason, condition or resolution while its toggle stayed on left customers with a required dropdown offering only "-- Select a Reason --" and a return they could not submit, with nothing on the page explaining why. Each control is now shown only when its list actually has active entries.
"Customers are required to select:" can now be saved empty — the setting previously refused to save with nothing selected.
An empty "Customers are required to select:" setting now means nothing is required — an empty value was read as one blank requirement rather than as no requirements at all.
CSV shipping labels were refused on upload — the file-type check expected one specific answer for CSV files, while current Linux systems report them as plain text. Both answers are now accepted.
Return pages and emails came out blank on Magento 2.3.7 — seven storefront and email templates used an escaping helper that does not exist before Magento 2.4.0, so the return list, the guest forms and the return confirmation emails silently failed to render on a page that still returned 200.
Removed orders no longer take down the pages that mention them — the admin return grid, the admin return form, the return list and the order lookup treated a deleted or zero order id as an outright error rather than "no order", which could break the whole page.
Opening or printing a return no longer fails when its messages cannot be flagged as read — the storefront return page, the printable return and the admin return page now render normally and log the problem instead of showing an error page.
Failed shipping confirmations now explain themselves — a confirmation that could not be saved reached Magento's generic error page; it now comes back as a "Can't confirm shipping" message on the page.
Version checks no longer misread the platform version — the mail transport and one setup patch compared a raw version string, so Mage-OS and pre-release versions could take the wrong compatibility branch.
Malformed markup in the admin return history — every message row emitted a stray empty HTML attribute. The rows look the same; the broken attribute is gone.
"Quick Responce" spelling corrected — the quick-response delete confirmation in the admin is now spelled correctly, in every language pack.
Reasons to choose Mirasvit
Client focusing and satisfaction

These are our primary. A major portion of our new clients come from referrals from our existing clients. Our professional team of developers, marketers and support staff have invested the best knowledge and experience in the field into our work, so you know you can come back to us again and again.

Remarkable support

One year free and high quality support. We go to great lengths to provide maximum satisfaction with every module you have purchased in our store. By helping you with installation, configuration, answering your every question, we do all our best to eliminate any possible problems.

Risk-free Investment

30-days money back guarantee. If you are not satisfied with our extension performance for any reason, we provide a full refund.

Constant improvements and upgrades

We constantly add new features to all our modules, and are always interested in hearing your opinion and implementing your suggested features in our future developments.

Comprehensive Documentation

We provide an expanded user guide for every aspect of our extension, so you can find answers for all your burning questions.

Unencrypted source code of our products

You can customize extension according to your needs and requirements.

Usability and Performance

The Module is easy to install and upgrade, just follow our step-by-step user guide. Additionally, the extension is ready to use with the Hyvä theme.

Ready for Magento Cloud

No core modifications. The extension has been tested in a Magento Cloud environment and is fully compatible with it.

Loading...