---
title: "Approval workflows"
description: "Set up merchant-side and buyer-side approval chains so quotes get internal sign-off before a proposal sends or a buyer accepts."
url: "https://www.quotway.com/docs/approvals/approval-workflows"
type: "documentation"
category: "approvals"
updated: "2026-10-14"
locale: "en"
source: "QuotWay - B2B Quote & Negotiation App for Shopify"
---

# Approval workflows

**Read time:** 7 minutes.
**Who it's for:** Merchants who need internal sign-off before a proposal goes to a buyer, or whose buyers' procurement teams need to sign off before they can accept.

> ⚠️ Approval workflows require the **Professional** plan or higher. Lite and Starter merchants see the policy editor but can't create policies. Professional includes linear multi-step chains; **parallel + conditional steps, timeout escalation, and delegation are Enterprise features.** See [Plans, trial, and billing](../billing/plans-trial-and-billing.md).

QuotWay supports **two sides** of approval:

- **Merchant-side** - sales rep proposes; sales manager approves before the proposal sends to the buyer.
- **Buyer-side** - buyer submits; purchasing manager approves; then finance approves; then the quote is officially accepted (B2B-capable stores).

Both sides share the same policy structure: steps + actors per step + optional parallel groups + optional conditional rules.

---

> Watch: create your first approval policy for B2B quotes.

## Anatomy of a policy

A policy has:

- **Domain** - `MERCHANT` or `BUYER`.
- **Trigger condition** - when does this policy apply? Examples:
  - Quote total > $50,000
  - Quote contains products in collection X
  - "Discount %" or "Deepest line discount %" above a threshold - each line is judged at what the buyer actually pays, so its share of any whole-quote (order) discount counts too
  - Buyer's customer tag contains `enterprise`
  - (No condition) - applies to every quote in the domain.
- **Steps** - ordered chain of approval steps. Each step has:
  - **Actors** - who can approve (one or more staff members, or one or more roles).
  - **Mode** - `ALL` (every actor must approve) or `ANY` (one approval clears the step).
  - Optional **conditional rule** - skip this step if X.

A policy is **active** when it has at least one step + the **Enabled** toggle is on.

## Worked example A - Single-step merchant approval

Scenario: every quote over $10K needs a sales manager to approve before the proposal goes out.

**Policy:**

- Domain: MERCHANT
- Trigger: `quote.totalEstimate > 10000`
- Steps:
  1. **Sales manager review** - actor: `staff:sales-manager-1` - mode: ANY.

That's it. When a sales rep clicks **Send proposal** on a $12K quote, the proposal status flips to `AWAITING_MERCHANT_APPROVAL`. The sales manager gets an email + an in-app notification. They review → approve → the proposal sends.

If they reject, the rep gets a notification with the rejection reason and can edit + re-submit.

## Worked example B - Buyer-side, multi-step, parallel

Scenario: your enterprise buyer's procurement team needs 3 sign-offs:

1. Purchasing manager
2. EITHER finance OR legal (parallel - whichever signs first)
3. CFO

**Policy:**

- Domain: BUYER
- Trigger: `quote.total > 100000`
- Steps:
  1. **Purchasing manager review** - actor: assigned per quote (defaults to buyer's company purchasing role) - mode: ANY.
  2. **Finance OR Legal review** - `parallelGroup: 1` - actors: finance + legal - mode: ANY (first one to approve clears).
  3. **CFO final** - actor: assigned per quote - mode: ANY.

When the buyer hits **Accept** on the proposal, the quote status flips to `AWAITING_BUYER_APPROVAL`. QuotWay surfaces the chain in the buyer portal: "Step 1 of 3 - Purchasing manager review".

## Worked example C - Conditional skip

Scenario: standard quotes go through one approval; quotes for a specific high-priority customer skip approval entirely.

**Policy:**

- Domain: MERCHANT
- Trigger: (no condition - applies to everything)
- Steps:
  1. **Sales manager review** - actor: sales manager - mode: ANY - **conditional**: skip if `customer.tags contains "auto-approve"`.

The auto-approve flag bypasses step 1 entirely for tagged customers. Useful for managing a small VIP roster without maintaining two parallel policies.

## Editing policies

1. **Admin → Approvals → New policy** (or open an existing one). New policies offer **templates** for the common cases - start from one and tweak, or build from scratch.
2. The editor is a top-to-bottom flow: **When** (who reviews + the trigger) → **Which quotes** (scope + conditions) → your **steps** → **Then** (what happens once the chain approves).
3. Add steps with the **+** buttons on the flow. For each step:
   - Pick the approvers (specific staff, a role, or buyer contacts for buyer-side policies).
   - To run a step in parallel with the one above it, tick **"Run at the same time as the previous step"**.
   - Conditional skips live under **"Add a condition to this step"**; time limits, escalation targets, delegation and rationale live under the step's **Advanced settings**.
4. **Save**.
5. **Enable** the policy when you're ready.

You can have multiple policies. They evaluate in priority order; the first matching policy wins.

Deleting a policy also deletes the completed approval chains and decisions recorded under it, and removing a step from a policy deletes the past decisions recorded on that step. To retire a policy and keep its history, turn **Enabled** off instead. A policy with a chain still in progress can't be deleted.

## Approval state in the inbox

The quote inbox shows the current state of each pending approval:

- `AWAITING_MERCHANT_APPROVAL` - merchant-side; sales manager owes a decision.
- `AWAITING_BUYER_APPROVAL` - buyer-side; buyer's chain in progress.

Open the quote detail → **Approvals** tab to see the full chain: each step's status, who owes the next action, and the elapsed time in the current step.

## Escalation

On Enterprise, a step can have a time limit under its **Advanced settings**. When a step waits past it, the hourly **approval-escalation-check** cron takes the action you chose: send a reminder, reassign the step to someone else, or approve or reject it automatically. An automatic approval or rejection is recorded as a decision by the system, with a rationale saying it timed out.

A chain still open 7 days after it started is logged as a `MerchantEvent('approval_chain_stuck_7d')` for analytics.

To move a step by hand, its approver can delegate it from the quote - see [Approval delegation](#approval-delegation).

## What approval looks like to the buyer

Buyers on B2B-capable stores see the approval chain in the Customer Account UI extension OR the hosted portal - depending on which path your store uses. Each step shows:

- Status badge (PENDING / ACTIVE / APPROVED / REJECTED).
- The actor's role label (PII like names are redacted from the buyer view unless the buyer is themselves a chain member).
- The action button if the current viewer is the active actor.

## Approval delegation

When a step allows it (**Allow the approver to delegate this step**, under the step's **Advanced settings** - Enterprise), an approver who can't act can delegate that step from the quote to another active staff member, with an optional note. Buyer-side approvers delegate to another contact by email. Delegation is per step, not for a period of time: the delegate takes over that step's decision, the original approver can no longer decide it, the hand-over is recorded with the step's decisions, and it doesn't route back on its own.

---

## Common gotchas

- **Policy editor blocked with "Upgrade required".** You're on Lite or Starter. Approval workflows need Professional+.
- **Step fires but the actor doesn't get an email.** Check that the actor's StaffMember record has an email address. Shopify sometimes hides staff emails from the API - see Troubleshooting.
- **Conditional skip never triggers.** The conditional uses the same rule format as Targeting (see [Targeting rules](../targeting/targeting-rules.md)). Verify the condition matches the quote's actual data.
- **Parallel group with both `mode: ALL` actors.** That works but reads as "everyone in the group must approve, in any order". Often you want `mode: ANY` instead.

---

## Related articles

- [Partial acceptance and split conversion](../converting-to-orders/partial-acceptance-and-split-conversion.md) - what happens after an approved proposal gets accepted.
- [Buyer portal vs customer account](../buyer-experience/portal-vs-customer-account.md) - where buyer-side approvals surface.
