WhatsApp Return & Refund Request Flow Template

A two-screen returns form that captures the order number, the items going back, the reason, their condition and whether the customer wants a refund, an exchange or store credit, then a description, a contact email and agreement to your returns policy.

2 screens 9 fields returned Flow JSON 7.2 Customer support Online stores, Retail shops, Fashion boutiques, Electronics sellers

Use Try it to fill the flow and see the exact response_json it returns.

return-refund-request.json Open in Flow Builder
{
  "version": "7.2",
  "screens": [
    {
      "id": "RETURN_REQUEST",
      "title": "Start a return",
      "data": {},
      "layout": {
        "type": "SingleColumnLayout",
        "children": [
          {
            "type": "Form",
            "name": "form_return_request",
            "children": [
              {
                "type": "TextHeading",
                "text": "What are you returning?"
              },
              {
                "type": "TextBody",
                "text": "Items can be returned within 30 days of delivery. Tell us about the order and how you would like it resolved."
              },
              {
                "type": "TextInput",
                "name": "order_number",
                "label": "Order number",
                "input-type": "text",
                "required": true,
                "helper-text": "Shown in your order confirmation, for example #10482"
              },
              {
                "type": "TextArea",
                "name": "returned_items",
                "label": "Items to return",
                "required": true,
                "helper-text": "Product name, colour, size and quantity",
                "max-length": 300
              },
              {
                "type": "RadioButtonsGroup",
                "name": "return_reason",
                "label": "Reason for return",
                "data-source": [
                  {
                    "id": "wrong_size",
                    "title": "Wrong size or fit"
                  },
                  {
                    "id": "damaged",
                    "title": "Arrived damaged or faulty"
                  },
                  {
                    "id": "wrong_item",
                    "title": "Received the wrong item"
                  },
                  {
                    "id": "not_as_described",
                    "title": "Not as described"
                  },
                  {
                    "id": "arrived_late",
                    "title": "Arrived too late"
                  },
                  {
                    "id": "changed_mind",
                    "title": "Changed my mind"
                  },
                  {
                    "id": "other_reason",
                    "title": "Other reason"
                  }
                ],
                "required": true
              },
              {
                "type": "RadioButtonsGroup",
                "name": "item_condition",
                "label": "Item condition",
                "data-source": [
                  {
                    "id": "unopened",
                    "title": "Unopened, original packaging"
                  },
                  {
                    "id": "opened_unused",
                    "title": "Opened but not used",
                    "description": "Tags or seals still attached"
                  },
                  {
                    "id": "used",
                    "title": "Used or worn"
                  },
                  {
                    "id": "damaged_on_arrival",
                    "title": "Damaged when it arrived"
                  }
                ],
                "required": true
              },
              {
                "type": "RadioButtonsGroup",
                "name": "preferred_resolution",
                "label": "How should we resolve it?",
                "data-source": [
                  {
                    "id": "refund",
                    "title": "Refund",
                    "description": "Back to your original payment method once the item is received"
                  },
                  {
                    "id": "exchange",
                    "title": "Exchange",
                    "description": "Different size, colour or a replacement for the same item"
                  },
                  {
                    "id": "store_credit",
                    "title": "Store credit",
                    "description": "Credit to spend on your next order"
                  }
                ],
                "required": true
              },
              {
                "type": "DatePicker",
                "name": "purchase_date",
                "label": "Purchase or delivery date",
                "required": true
              },
              {
                "type": "Footer",
                "label": "Continue",
                "on-click-action": {
                  "name": "navigate",
                  "next": {
                    "type": "screen",
                    "name": "RETURN_CONFIRM"
                  },
                  "payload": {}
                }
              }
            ]
          }
        ]
      }
    },
    {
      "id": "RETURN_CONFIRM",
      "title": "Return details",
      "terminal": true,
      "data": {},
      "layout": {
        "type": "SingleColumnLayout",
        "children": [
          {
            "type": "Form",
            "name": "form_return_confirm",
            "children": [
              {
                "type": "TextSubheading",
                "text": "A few more details"
              },
              {
                "type": "TextArea",
                "name": "issue_description",
                "label": "What happened?",
                "required": true,
                "helper-text": "Describe the problem so we can process your return faster",
                "max-length": 600
              },
              {
                "type": "TextInput",
                "name": "contact_email",
                "label": "Email",
                "input-type": "email",
                "required": true,
                "helper-text": "For your return label and refund receipt"
              },
              {
                "type": "EmbeddedLink",
                "text": "Read our returns policy",
                "on-click-action": {
                  "name": "open_url",
                  "url": "https://example.com/returns-policy"
                }
              },
              {
                "type": "OptIn",
                "name": "policy_agreement",
                "label": "I have read the returns policy and understand items must meet its conditions to be accepted.",
                "required": true
              },
              {
                "type": "TextCaption",
                "text": "After you submit, we may ask you to send a photo of the item in this chat. We will reply with next steps within 2 business days."
              },
              {
                "type": "Footer",
                "label": "Submit return request",
                "on-click-action": {
                  "name": "complete",
                  "payload": {
                    "order_number": "${screen.RETURN_REQUEST.form.order_number}",
                    "returned_items": "${screen.RETURN_REQUEST.form.returned_items}",
                    "return_reason": "${screen.RETURN_REQUEST.form.return_reason}",
                    "item_condition": "${screen.RETURN_REQUEST.form.item_condition}",
                    "preferred_resolution": "${screen.RETURN_REQUEST.form.preferred_resolution}",
                    "purchase_date": "${screen.RETURN_REQUEST.form.purchase_date}",
                    "issue_description": "${form.issue_description}",
                    "contact_email": "${form.contact_email}",
                    "policy_agreement": "${form.policy_agreement}"
                  }
                }
              }
            ]
          }
        ]
      }
    }
  ]
}

Raw JSON for scripts: curl -s https://whautomate.com/whatsapp-flow-templates/return-refund-request.json

Import in 60 seconds
  1. Copy the JSON above (or edit it first in the Flow Builder).
  2. In WhatsApp Manager, open Account tools > Flows, create a flow and choose Customer support as the category.
  3. Paste into the JSON editor, check the preview, then Publish.
  4. Send it with the Flow ID, as an interactive message or through a template's Flow button.

Not technical? Skip the JSON and send it from Whautomate with a drag-and-drop editor.

About this return & refund request flow

A return request that starts with "I want to send this back" usually takes a dozen messages before an agent can act: which order, which item, what is wrong with it, has it been worn, and does the customer want their money or a different size. This flow asks all of that in two screens, so the first thing your team sees is a complete return case rather than the start of an interview.

Screen one is the case itself: order number, the items, a reason list, the item condition and the preferred resolution, plus the purchase date so an agent can check the return window at a glance. Screen two collects the customer's own description, an email for the return label or refund receipt, and an explicit agreement to your returns policy, with a link to the full policy right above the checkbox.

Because this is a static flow, it cannot look the order up or decide eligibility on the spot. It records the request exactly as the customer describes it and your team approves, declines or asks for photos in the same chat. Photo upload needs the PhotoPicker component, which this builder does not cover, so the simplest pattern is to ask for pictures as a normal WhatsApp reply after the form is submitted.

Fields this flow returns

When the customer taps the final button, the complete action sends these keys back in response_json. Fields from earlier screens are pulled in with global references (${screen.SCREEN_ID.form.field}), so nothing is lost between screens.

KeyComponentScreenRequiredReturnsExample
order_number TextInput RETURN_REQUEST Yes string "#10482"
returned_items TextArea RETURN_REQUEST Yes string "Linen shirt, navy, size M (1 of 2 in the order)"
return_reason
wrong_size, damaged, wrong_item, not_as_described, arrived_late, changed_mind, other_reason
RadioButtonsGroup RETURN_REQUEST Yes item id "wrong_size"
item_condition
unopened, opened_unused, used, damaged_on_arrival
RadioButtonsGroup RETURN_REQUEST Yes item id "opened_unused"
preferred_resolution
refund, exchange, store_credit
RadioButtonsGroup RETURN_REQUEST Yes item id "exchange"
purchase_date DatePicker RETURN_REQUEST Yes YYYY-MM-DD "2026-10-03"
issue_description TextArea RETURN_CONFIRM Yes string "Fits tight across the shoulders. Tags still attached, I would like the same shirt in size L."
contact_email TextInput (email) RETURN_CONFIRM Yes string "[email protected]"
policy_agreement OptIn RETURN_CONFIRM Yes boolean true

Optional fields the customer leaves empty may be missing from response_json or arrive empty. Treat every optional key as nullable in your handler.

No developer needed

Send the Return & Refund Request flow without touching code

You do not need to be technical to use WhatsApp Flows. Connect your WhatsApp number, set the flow up in our drag-and-drop editor and send it to customers in a few clicks. No JSON, no API calls, no WhatsApp Manager.

1

Connect your number

Log in with Facebook and connect your WhatsApp number in a few minutes. No API keys or servers to set up.

2

Set up the flow

Start from a ready-made form or import this one, then drag fields in, change the wording and try it on a live phone preview. Click Publish when it looks right.

3

Send it anywhere

Send it from any chat in the Team Inbox, on web or mobile, send it automatically from an automation, or broadcast it to a list.

4

Get the answers

Every answer is saved on the customer's profile and chat, and your team can be notified the moment a form comes in.

7-day free trial, no credit card required.

Sample webhook payload (nfm_reply)

This is what your webhook receives when a customer submits the flow. response_json is a JSON string: parse it, then match flow_token to the record you created when you sent the message. The customer's WhatsApp number is in messages[0].from.

response_json (parsed)
{
  "flow_token": "bk_8f2c41",
  "order_number": "#10482",
  "returned_items": "Linen shirt, navy, size M (1 of 2 in the order)",
  "return_reason": "wrong_size",
  "item_condition": "opened_unused",
  "preferred_resolution": "exchange",
  "purchase_date": "2026-10-03",
  "issue_description": "Fits tight across the shoulders. Tags still attached, I would like the same shirt in size L.",
  "contact_email": "[email protected]",
  "policy_agreement": true
}
POST your-webhook (full event)
{
  "object": "whatsapp_business_account",
  "entry": [
    {
      "id": "WHATSAPP_BUSINESS_ACCOUNT_ID",
      "changes": [
        {
          "field": "messages",
          "value": {
            "messaging_product": "whatsapp",
            "metadata": {
              "display_phone_number": "15550001234",
              "phone_number_id": "PHONE_NUMBER_ID"
            },
            "contacts": [
              {
                "profile": {
                  "name": "Alex Morgan"
                },
                "wa_id": "14155550123"
              }
            ],
            "messages": [
              {
                "context": {
                  "from": "15550001234",
                  "id": "wamid.SENT_FLOW_MESSAGE_ID"
                },
                "from": "14155550123",
                "id": "wamid.INCOMING_MESSAGE_ID",
                "timestamp": "1760000000",
                "type": "interactive",
                "interactive": {
                  "type": "nfm_reply",
                  "nfm_reply": {
                    "name": "flow",
                    "body": "Sent",
                    "response_json": "{\"flow_token\":\"bk_8f2c41\",\"order_number\":\"#10482\",\"returned_items\":\"Linen shirt, navy, size M (1 of 2 in the order)\",\"return_reason\":\"wrong_size\",\"item_condition\":\"opened_unused\",\"preferred_resolution\":\"exchange\",\"purchase_date\":\"2026-10-03\",\"issue_description\":\"Fits tight across the shoulders. Tags still attached, I would like the same shirt in size L.\",\"contact_email\":\"[email protected]\",\"policy_agreement\":true}"
                  }
                }
              }
            ]
          }
        }
      ]
    }
  ]
}

Deploy with the WhatsApp Cloud API

Prefer code over WhatsApp Manager? Save the template as return-refund-request.json and run these calls with a system user token that has whatsapp_business_management and whatsapp_business_messaging permissions.

1. Create the flow

bash
curl -X POST 'https://graph.facebook.com/v23.0/{WABA_ID}/flows' \
  -H 'Authorization: Bearer {ACCESS_TOKEN}' \
  -H 'Content-Type: application/json' \
  -d '{"name": "return_refund_request", "categories": ["CUSTOMER_SUPPORT"]}'
# => {"id": "{FLOW_ID}"}

2. Upload the Flow JSON

bash
curl -X POST 'https://graph.facebook.com/v23.0/{FLOW_ID}/assets' \
  -H 'Authorization: Bearer {ACCESS_TOKEN}' \
  -F '[email protected];type=application/json' \
  -F 'name=flow.json' \
  -F 'asset_type=FLOW_JSON'
# => {"success": true, "validation_errors": []}

3. Publish it

bash
curl -X POST 'https://graph.facebook.com/v23.0/{FLOW_ID}/publish' \
  -H 'Authorization: Bearer {ACCESS_TOKEN}'

Publishing is permanent: a published flow cannot be edited. To change it later, create a new flow (or clone it with clone_flow_id) and publish the new version.

4. Send it to a customer

Inside the 24-hour customer service window, send an interactive flow message. Outside it, create a message template with a Flow button that points to this flow, and send the template instead.

send-return-refund-request.json
{
  "messaging_product": "whatsapp",
  "recipient_type": "individual",
  "to": "14155550123",
  "type": "interactive",
  "interactive": {
    "type": "flow",
    "header": {
      "type": "text",
      "text": "Returns and refunds"
    },
    "body": {
      "text": "Sorry the order was not right. Tell us what you are sending back and how you would like it resolved, and we will reply with the next steps."
    },
    "footer": {
      "text": "Returns are reviewed within 2 business days"
    },
    "action": {
      "name": "flow",
      "parameters": {
        "flow_message_version": "3",
        "flow_token": "bk_8f2c41",
        "flow_id": "YOUR_FLOW_ID",
        "flow_cta": "Start a return",
        "flow_action": "navigate",
        "flow_action_payload": {
          "screen": "RETURN_REQUEST"
        }
      }
    }
  }
}
bash
curl -X POST 'https://graph.facebook.com/v23.0/{PHONE_NUMBER_ID}/messages' \
  -H 'Authorization: Bearer {ACCESS_TOKEN}' \
  -H 'Content-Type: application/json' \
  -d @send-return-refund-request.json

When to send it

Customer says "return" or "refund"

Trigger the flow from a keyword so a customer typing "return", "refund", "exchange" or "wrong size" gets the form immediately instead of a queue.

After delivery confirmation

A few days after an order is marked fulfilled, a delivery follow-up template can carry a "Start a return" Flow button for customers who need it, alongside the usual "enjoy your order" message.

Damaged or wrong item reports

When a customer sends a photo of a broken or incorrect item, reply with the flow so the order number and resolution choice are captured in a format your warehouse can process.

Seasonal return peaks

After holiday sales, route every returns conversation through the flow so agents spend their time approving cases rather than collecting details.

How to customise this template

  • Rewrite the return reasons to match what your returns data actually shows. A clothing store needs "Too small" and "Too big" as separate ids; an electronics store needs "Stopped working" and "Missing parts".
  • If you do not offer store credit, remove that option rather than leaving it in: customers who pick an option you cannot honour will be disappointed twice.
  • Point the EmbeddedLink at your live returns policy page and keep the OptIn wording in step with it. If your window is 30 days, say so in the TextBody on screen one as well.
  • Pass your order id as the flow_token when you send the flow from an order notification. The submission then maps to the order without relying on what the customer typed in the order number field.
  • For marketplaces or multi-brand shops, add a Dropdown for the seller or brand on screen one so the case can be routed before anyone opens it.

Open this template in the Flow Builder to make these changes visually. The builder keeps field names unique and regenerates the completion payload for you.

Common mistakes to avoid

  • Do not phrase the final button or caption as "Refund approved". Submitting the form is a request; approval happens after your team checks the order, the window and the item condition.
  • The order number is free text, so expect "#1042", "1042" and "order 1042". Normalise it in your webhook handler before matching, or send the order id in the flow_token instead.
  • Keep item condition options honest and neutral. A list that only offers "Unused" pushes customers to pick it, and you lose the information you need to grade the return.
  • Ask for photos after the flow, not before. Customers who are asked to take photos first often drop off, while a quick "please send a photo of the item" reply after submission gets a much better response.

Take real orders inside WhatsApp

Whautomate includes a built-in store checkout flow: products, customer details, address and shipping, coupon codes and the order itself, with an optional payment request sent right after. It is created and published for you and runs on an endpoint Whautomate hosts.

  • Live products and coupon checks
  • Order created on submit
  • Optional payment request after checkout

7-day free trial, no credit card required.

Frequently asked questions

Not as a static flow. Checking the order and its date needs a data_exchange endpoint that looks the order up and returns eligibility. This template captures the purchase date and order number so your team, or your own webhook logic, can make that check after submission.
Photo upload uses the PhotoPicker component, which is outside what this template and builder support. Ask for photos as a regular WhatsApp message once the form is submitted; they arrive on the same chat, right below the flow response.
An interactive nfm_reply message whose response_json contains the flow_token and each field: order_number, returned_items, return_reason, item_condition, preferred_resolution, purchase_date, issue_description, contact_email and policy_agreement. Radio fields return item ids such as store_credit, the date is YYYY-MM-DD and the OptIn is a boolean.
Yes, but only inside an approved message template that carries a Flow button, for example a post-delivery message. A free-form interactive flow message can only be sent within 24 hours of the customer's last message.

The Complete Omnichannel Customer Engagement Platform

Go beyond free tools. Automate conversations, build AI chatbots, send broadcast campaigns, book appointments, sell products, and manage every messaging channel from one powerful platform. Trusted by thousands of businesses worldwide.

  • WhatsApp, Instagram, Messenger, Telegram & Live Chat
  • AI chatbots & no-code automation
  • Broadcast campaigns & analytics
  • Appointment & class booking
  • E-commerce, Shopify & WooCommerce integration
  • CRM, invoicing & payment collection

No credit card required. Free 7-day trial. Visit our pricing page for plans.