Refund reasons
Tree-structured taxonomy of refund reasons; required selection at refund time.
Refund reasons form a hierarchical taxonomy your team uses to categorize every refund. Selecting a reason is required when processing a refund; you must select a leaf node (a reason with no children).
Tree structure
Reasons are organized as an unlimited-depth tree using a parentId self-reference. You might structure it like:
Customer request
└── Changed mind
└── Found cheaper elsewhere
Product issue
└── Damaged on arrival
└── Wrong item shipped
└── Does not match description
Fraud
└── Unauthorized transaction
└── Stolen card
There is no fixed depth limit, but trees deeper than 3 levels tend to become difficult to navigate quickly during a refund workflow.
Managing reasons
Go to Settings → Refund Reasons. The tree is displayed with expand/collapse controls.
Add a root reason — click Add reason at the top level.
Add a child reason — click the + button next to any existing reason to add a node beneath it.
Edit — click the reason name to rename it or change its active state.
Deactivate — set Active to off. The reason disappears from the refund picker but remains visible on historical refund records that reference it.
Delete — only possible if the reason has never been used on a refund. If any Refund row references the reason, the delete is blocked. Use deactivate instead.
Selecting a reason at refund time
When you open the refund modal on an order, the Refund Reason field shows a cascading picker. Click a parent to expand its children. You can only select a leaf node — a reason that has no children. Intermediate nodes are not selectable.
The refund picker calls GET /api/refund-reasons, which returns only active nodes. It requires the orders feature permission. The tree is assembled client-side from the flat list.
APIs
| Endpoint | Methods | Permission | Purpose |
|---|---|---|---|
/api/settings/refund-reasons | GET, POST | settings.refund-reasons | List and create reasons |
/api/settings/refund-reasons/:id | PUT, DELETE | settings.refund-reasons | Edit or delete a reason |
/api/refund-reasons | GET | orders | Active tree for the refund picker |
Active vs inactive
Deactivating a reason has two effects:
- It is removed from the refund picker — no new refunds can use it.
- Existing refunds that reference it continue to show the reason name correctly in history.
Deactivating a parent node does not automatically deactivate its children. Each child remains independently active and selectable unless you deactivate it separately.
Caveats
- Deleting a referenced reason is blocked. If any refund already references it, the API returns a 409. Deactivate it instead.
- Deactivating a parent does not cascade. Children remain selectable until you deactivate them individually.
- You must select a leaf. The server validates that the submitted
reasonIdhas no active children. Submitting an intermediate node ID returns a 422. - Deep trees are cumbersome. Three levels is a practical maximum for fast selection during a refund.
Related
- Orders — Refunds — processing a refund and viewing refund history.