Skip to content

Raise a Return

About

The createCustomerReturn mutation raises a new return (RMA) request for one item of one of the customer's orders. The item must be return-eligible — check it with returnableItems first. The requested quantity (rmaQty) is capped server-side by the quantity the customer is actually allowed to return. The return starts in a Pending status.

Authentication

This mutation requires an authenticated customer — send the storefront key and a customer Bearer token. See the Authentication page.

Input Fields

FieldTypeRequiredDescription
orderIdInt!✅ YesId of the order the item belongs to.
orderItemIdInt!✅ YesId of the order item being returned — the orderItemId from returnableItems. This is the order line id, not the product id.
rmaQtyInt!✅ YesQuantity to return. Capped server-side by the returnable quantity.
resolutionTypeString!✅ Yesreturn or cancel_items.
rmaReasonIdInt!✅ YesId of the chosen return reason — from returnReasons.
informationString❌ NoFree-text note about the return.
packageConditionString❌ NoReported package condition — open or packed. Any other value is rejected.
customAttributesIterable⚠️ ConditionalAnswers to the return form's custom fields, keyed by field id — see List Return Custom Fields. Required when the store has custom fields marked isRequired.
agreementBoolean!✅ YesMust be true to confirm the return terms.

Custom Fields

The store can configure additional questions the shopper answers while raising a return. Query them with returnCustomFields and send the answers in customAttributes, keyed by the field _id:

  • every field with isRequired: true must be answered, otherwise the mutation is rejected
  • select and radio answers must be one of the field's option values
  • multiselect and checkbox answers take a list of option values
  • the stored answers come back on the return as customAttributes

Possible Returns

FieldTypeDescription
customerReturn._idInt!Numeric return ID.
customerReturn.orderIdInt!Id of the order the item belongs to.
customerReturn.orderIncrementIdString!Human-readable order number.
customerReturn.statusIdInt!Numeric status id — 1 (Pending) for a fresh return.
customerReturn.statusTitleString!Status label.
customerReturn.statusColorString!Hex color for the status badge.
customerReturn.packageConditionStringReported package condition.
customerReturn.informationStringThe note supplied when raising the return.
customerReturn.canCloseBooleanWhether the return can be closed.
customerReturn.canReopenBooleanWhether the return can be reopened.
customerReturn.isExpiredBooleanWhether the return is past its action window.
customerReturn.itemObjectThe returned item — id, order_item_id, sku, name, quantity, resolution, reason_id, reason, variant_id. Query bare (a JSON object).
customerReturn.imagesArrayAttached images (id, path, url). Always empty on a return raised through this mutation — see Attaching Evidence Photos. Query bare (a JSON array).
customerReturn.customAttributesArrayAnswers to the return's custom fields — field_id, code, label, type, value. Empty when the store has no custom fields. Query bare (a JSON array).
customerReturn.messagesCountInt!Number of conversation messages — 0 for a fresh return.
customerReturn.createdAtDateTime!Return creation timestamp.
customerReturn.updatedAtDateTime!Return last update timestamp.

Attaching Evidence Photos

A binary part cannot travel in a JSON GraphQL request, and photos can only go in while the return is being raised — there is no endpoint that adds them afterwards. So when the shopper attached files, raise the whole return over REST instead of through this mutation, sending the same fields as multipart/form-data:

bash
curl -X POST "https://your-store.com/api/shop/returns" \
  -H "X-STOREFRONT-KEY: pk_storefront_PvlE42nWGsKRVIf8bDlJngTPAdWAZbIy" \
  -H "Authorization: Bearer 438|aSV6JyFn299xuoR6wr5KKOodyIlMA26h0IgHiqLW" \
  -F "order_id=45" \
  -F "order_item_id=78" \
  -F "rma_qty=1" \
  -F "resolution_type=return" \
  -F "rma_reason_id=2" \
  -F "agreement=true" \
  -F "images[]=@/home/john/Pictures/damage-front.jpg" \
  -F "images[]=@/home/john/Pictures/damage-back.jpg"

Each file is checked against the mime types the store allows (Configuration → Sales → RMA → Allowed file extension). A return raised through this mutation always comes back with images empty, which is why the field reads as empty above rather than missing.

Files can still reach the store after the fact through the conversation — createCustomerReturnMessage documents the REST call that carries one file per message.

Released under the MIT License.