> ## Documentation Index
> Fetch the complete documentation index at: https://docs.knotapi.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Cross-Merchant Savings

> Alert users when a product they bought is available for less at another merchant.

> This is a product use case page. When implementing, follow the linked quickstarts for canonical API setup steps rather than inferring them from this page.

## Problem

Users tend to shop at whichever merchant is most convenient without realizing the same product is available for less at another retailer. Neither large retailers nor delivery platforms are uniformly cheaper - price differences depend on the specific product, and the gap can be significant. Without SKU-level visibility into what was purchased and where, there is no practical way to surface these comparisons.

## Solution

Use SKU-level transaction data from Knot's [Sync Transactions](/api-reference/products/transaction-link/sync) endpoint to build a cross-merchant price index across your user base. After each purchase, check whether the same product is available at a lower price at another merchant. Surface the savings opportunity as a proactive tip.

<Frame>
  <img src="https://mintcdn.com/knot/LAFgTtGjggJatYpO/images/cross-merchant-savings.png?fit=max&auto=format&n=LAFgTtGjggJatYpO&q=85&s=771b6ae43a67de9e35c2367860adec82" alt="iPhone lock screen showing a push notification: Save $4.50 on Tide PODS - You paid $24.99 at Target. The same pack is $20.49 on Amazon." width="3840" height="1600" data-path="images/cross-merchant-savings.png" />
</Frame>

This turns passive spending data into actionable savings guidance, without requiring the user to comparison shop on their own.

## Flow

```mermaid placement="top-right" actions={false} theme={"system"}
%%{init: {'theme': 'base', 'themeVariables': {'primaryColor': '#f5f5f5', 'primaryTextColor': '#000', 'primaryBorderColor': '#000', 'lineColor': '#000', 'secondaryColor': '#f5f5f5', 'tertiaryColor': '#f5f5f5', 'edgeLabelBackground': '#fff', 'fontSize': '16px'}}}%%
flowchart LR
    A[User switches their card at a merchant through Knot or simply links their merchant account to begin syncing SKU-level purchase data] --> B[Sync each user's purchase data daily from Knot's API]
    B --> C[Your server adds each product to a cross-merchant price index]
    C --> D[On each new transaction, check for lower prices at other merchants]
    D --> E{Savings above threshold?}
    E -->|Yes| F[Surface price comparison to the user]
    E -->|No| G[No action needed]
```

## Implementation

<Steps>
  <Step title="Sync transaction data" titleSize="h3">
    When a user switches their card at a merchant or links their merchant account, Knot begins collecting transaction data. Listen for the [`NEW_TRANSACTIONS_AVAILABLE`](/transaction-link/webhook-events/new-transactions-available) webhook event, then call [Sync Transactions](/api-reference/products/transaction-link/sync) to pull the user's transactions.

    **Key fields**

    | Field                         | Purpose                                                          |
    | ----------------------------- | ---------------------------------------------------------------- |
    | `products[].name`             | Product display name, used as the cross-merchant matching key.   |
    | `products[].external_id`      | Merchant-specific product identifier.                            |
    | `products[].price.unit_price` | Price paid at this merchant.                                     |
    | `products[].category`         | Knot-provided category, used to validate matches are comparable. |
    | `products[].subcategory`      | Knot-provided subcategory for narrower match validation.         |
    | `products[].image_url`        | Product image for the comparison card.                           |
    | `merchant.id`                 | Identifies which merchant this price is from.                    |
    | `merchant.name`               | Retailer display name for the UI.                                |
    | `datetime`                    | Purchase timestamp.                                              |
    | `external_user_id`            | Identifies the user in your system.                              |
    | `order_status`                | Filter to completed orders only.                                 |

    Only include transactions with `order_status` of `COMPLETED`, `DELIVERED`, `PICKED_UP`, `SHIPPED`, `BILLED`, or `ORDERED`. Filter out `CANCELLED`, `REFUNDED`, and `FAILED`.
  </Step>

  <Step title="Build the cross-merchant price index" titleSize="h3">
    As products are synced, maintain a shared price index keyed by product name and merchant. Use `products[].name` combined with `products[].subcategory` (or `products[].category` as fallback) to identify the same product at different merchants.

    ```text theme={"system"}
    FOR each product in new_transaction.products:
        upsert into price_index:
            key: (normalized_name, subcategory, merchant_id)
            fields: (name, unit_price, image_url, merchant_name)
    ```

    This index is populated by data across all your users. A user who has only connected one merchant can still receive alerts about prices at other merchants, because other users' transactions contribute to the index.
  </Step>

  <Step title="Detect cross-merchant savings" titleSize="h3">
    On each incoming transaction, check whether any product in the order appears in the price index at a lower price at a different merchant.

    ```text theme={"system"}
    FOR each product in new_transaction.products:

        cheaper_options = query price_index WHERE
            normalized_name == normalize(product.name)
            AND subcategory == product.subcategory  // fall back to category if null
            AND merchant_id != new_transaction.merchant.id
            AND unit_price  <  product.price.unit_price

        IF cheaper_options is not empty:
            best = option with lowest unit_price
            savings = product.price.unit_price - best.unit_price
            savings_pct = savings / product.price.unit_price

            IF savings >= MIN_SAVINGS AND savings_pct >= MIN_SAVINGS_PCT:
                queue comparison for external_user_id
    ```

    **Configuration decisions for your team:**

    | Parameter                 | Suggested Default         | Considerations                                                                                                    |
    | ------------------------- | ------------------------- | ----------------------------------------------------------------------------------------------------------------- |
    | `MIN_SAVINGS`             | \$1.00                    | Cross-merchant switches have more friction than same-merchant swaps. A higher floor keeps alerts worth acting on. |
    | `MIN_SAVINGS_PCT`         | 10%                       | Avoids surfacing marginal differences on high-priced items.                                                       |
    | Max comparisons per order | 2                         | One or two clear wins is more actionable than a long list.                                                        |
    | Alert frequency           | Once per product per user | Re-evaluate when a meaningful price change is detected (e.g., gap widens by \$1+).                                |
    | Price freshness           | 30 days                   | Discard index entries older than 30 days. Prices shift and stale data leads to false alerts.                      |

    **Trigger timing options:**

    * **Real-time (preferred):** Run the check on each incoming transaction. Alerts surface while the purchase is fresh in the user's mind.
    * **Weekly digest:** Aggregate all cross-merchant savings opportunities from the past week and present a cumulative summary. Lower friction for users who prefer fewer notifications.
    * **Hybrid:** Real-time for savings above \$2 per item; weekly digest for smaller gaps.
  </Step>

  <Step title="Surface the comparison" titleSize="h3">
    When a cheaper price is found, notify the user with the product, what they paid, where it is cheaper, and the savings amount.

    <Frame>
      <img src="https://mintcdn.com/knot/LAFgTtGjggJatYpO/images/cross-merchant-savings.png?fit=max&auto=format&n=LAFgTtGjggJatYpO&q=85&s=771b6ae43a67de9e35c2367860adec82" alt="iPhone lock screen showing a push notification: Save $4.50 on Tide PODS - You paid $24.99 at Target. The same pack is $20.49 on Amazon." width="3840" height="1600" data-path="images/cross-merchant-savings.png" />
    </Frame>

    Deep-link the notification to a screen where the user can view the full comparison and navigate to the product at the cheaper merchant.
  </Step>
</Steps>

## Expansion Path

* **Merchant recommendations:** If a user consistently overpays at one merchant relative to another on a set of products they buy regularly, surface a merchant-level recommendation rather than per-product alerts. "Most of what you buy at Walmart is cheaper on Amazon" is a more compelling insight than individual item comparisons.
* **Weekly savings digest:** Aggregate all cross-merchant comparisons from the week into a single card showing total potential savings. This keeps the feature visible for users who prefer a lower notification volume.
