Importing Returns

The Returns import opens returns (RMAs) against your orders from a CSV/Excel file, a Google Sheet, or directly from another connected store — and can also close or cancel existing returns per row. Each create row resolves a real order in your store, finds its returnable items (Shopify's own math: only fulfilled, not-yet-returned/refunded quantities), and opens a return with the items and reasons you specify.

No money moves. A return records the buyer's intent to send items back — it opens in the Open state and creates a reverse fulfillment order. The eventual refund is the separate Refunds import. Approving or declining customer-requested returns is not part of this import — it creates returns that are already approved.

Because a return can cover several line items, the import uses one row per item — rows that share the same Order are merged into one return. A row with no SKU / Fulfillment Line Item ID returns everything still returnable on the order.

For the wizard itself — uploading, mapping, dry runs, schedules — see Importing into EcomSolo.

Columns

ColumnNotes
OrderRequired for create rows. The order to open the return on, by name (#1001) or ID. Must be a real order in the target store. Rows sharing an Order are grouped into one return.
Operationcreate (default), close, or cancel. Close/cancel rows act on an existing return named by the Return column.
ReturnFor close/cancel rows: the return's name (e.g. #1001-R1) or ID. Resolved against your synced Returns dashboard, with a live fallback via the row's Order.
Fulfillment Line Item IDThe fulfillment line-item GID/ID to return. Optional — usually you match by SKU instead.
SKUThe variant SKU to return on that order. Must be a fulfilled, still-returnable SKU on that order.
QuantityHow many of that item to return. Defaults to the returnable quantity; capped at what's still returnable.
Return ReasonOne of COLOR, DEFECTIVE, NOT_AS_DESCRIBED, OTHER, SIZE_TOO_LARGE, SIZE_TOO_SMALL, STYLE, UNKNOWN, UNWANTED, WRONG_ITEM. Unknown values never fail the row — they fall back to OTHER and the raw value is kept in the reason note.
Reason NoteFree-text detail about the reason (max 255 chars).

Common export headers map automatically: Order Name / Name / # → Order, Action / Command → Operation, Return Name / Return ID → Return, Variant SKU → SKU, Qty → Quantity, Reason → Return Reason, Note / Return Reason Note → Reason Note.

What's returnable — Shopify's own math

Before creating any return, the import asks Shopify for the order's returnable fulfillments — the exact items and quantities that are fulfilled and not already returned or refunded. The import then:

  • matches each row's SKU (or Fulfillment Line Item ID) against that list and caps the quantity at what's still returnable;
  • fails a row whose SKU isn't on the order at all (never guesses);
  • fails a row whose SKU is on the order but not returnable — items must be fulfilled (and not already returned or refunded) first;
  • skips an order with nothing returnable (a safe re-run no-op).

The dry run on the Review step shows the create / close / cancel / skip split before anything is written.

The lifecycle — create, close, cancel

  • Create (the default) opens the return in the Open state.
  • Close (Operation = close) marks an open return as done.
  • Cancel (Operation = cancel) voids a return — it stays in Shopify as Canceled (nothing is deleted).
  • The wizard's Delete operation cancels every matched return in the file — it's gated behind the delete via import permission, like other destructive runs.

Close/cancel rows identify the return with the Return column. A re-run is idempotent: a return that's already closed (or canceled) is skipped, and a name that doesn't resolve is a row error (returns are never deleted from Shopify, so an unresolvable name means a typo).

Idempotency — safe to re-run

Returns are create-only per row — there is no upsert key, and a merchant may legitimately open several returns on one order. The automatic guards: an order with nothing left to return is skipped, and close/cancel rows skip returns already in the target state. Re-running a create file against orders that still have returnable quantity will open new returns, so preview first.

Importing from another store

On the wizard's Source step, pick From another store to copy the source store's returns as import rows — one row per returned line item, grouped by Order, with the SKU, quantity and return reason. This creates NEW returns on the destination store — it does not move or link the source RMA. Each row is matched by Order name and SKU, so both stores must hold the same orders, and the target items must be fulfilled (import your Orders and Fulfillments first). Orders with nothing returnable are skipped.

Results and freshness

Returns you create take effect in Shopify immediately, and EcomSolo's Returns dashboard (Orders → Returns) refreshes within seconds of the run — status flips from close/cancel rows included.

Sample file

A ready-to-run sample lives under features/importing/examples/:

  • returns-create-sample.csv — covers every case in one file.
Order,Operation,Return,SKU,Fulfillment Line Item ID,Quantity,Return Reason,Reason Note
#1001,,,HAT-BLK-01,,1,DEFECTIVE,"Stitching came apart"
#1002,,,SCARF-RED-02,,2,SIZE_TOO_SMALL,
#1002,,,SOCKS-WHT-03,,1,changed my mind,"Falls back to OTHER"
#1003,,,,,,,
#1004,close,#1004-R1,,,,,
#1005,cancel,#1005-R1,,,,,

These cover a single-SKU return (#1001), a multi-line return of two SKUs on one order (#1002 — note the unknown reason on the second line safely falling back to OTHER), a whole-order return of everything still returnable (#1003), a close row (#1004), and a cancel row (#1005).

Swap in real values. Order, SKU and Return must resolve in your target store, so replace #1001#1005, the sample SKUs and the return names (#1004-R1, …) with values that actually exist — and remember create rows need the items fulfilled first. An order, SKU or return that can't be found produces a row-level error naming the unresolved value — the rest of the file still runs.

Troubleshooting

Error in the reportWhat it means / what to do
row requires an OrderEvery create row needs the order name or ID.
order '#1001' not foundNo order with that name/ID exists in the target store — check the value.
SKU 'HAT-BLK-01' not found on order '#1001'The order has no line item with that SKU — check for a typo or the wrong order.
SKU '…' has no returnable quantity — items must be fulfilled …The SKU is on the order but can't be returned: it's unfulfilled, or already returned/refunded. Fulfill first (see the Fulfillments import).
has nothing returnable … skippedEverything on the order is already returned/refunded or unfulfilled — the row is skipped, not an error.
return '#1001-R1' not foundNo return with that name/ID — check the Returns dashboard for the exact name.
return '…' is already closed/canceled — nothing to …An idempotent re-run — the row is skipped.

FAQ

Does creating a return refund the customer? No — no money moves. Pair this with the Refunds import to refund returned items.

Can I return items that aren't fulfilled? No — Shopify only allows returns on fulfilled, not-yet-refunded items. Fulfill first, then return.

Will re-importing create duplicate returns? Orders with nothing returnable are skipped, but an order that still has returnable quantity will get a new return — run each create file once and preview first.

What happens to a cancelled return? It stays in Shopify with the Canceled status — returns are never deleted.

Can I approve or decline customer-requested returns? Not with this import — it creates already-approved returns. Manage requests in the Shopify admin.