This page explains how to enable and integrate the Kustom Upsell feature, which displays product recommendations on the order confirmation page after a purchase is completed.
Upsell must be enabled for your merchant account before use. Contact Kustom to activate it.
Upsell lets you present product recommendations to shoppers immediately after they complete a purchase. Because payment is already authorized, shoppers can add items to their existing order with a single tap — no re-entering payment details.
Kustom handles the UI widget, payment authorization increase, and order updates. You control what products are shown and when.
Set options.confirmation_page_upsell to true when creating a checkout order. This is the recommended approach for A/B testing or selective rollout.
{
"options": {
"confirmation_page_upsell": true
}
}The flag can be updated on the order until it reaches status checkout_complete.
Kustom can enable upsell at the merchant ID level so all eligible sessions show the widget without any per-order flag. You can still override per order using options.confirmation_page_upsell: false.
Contact Kustom to enable global activation.
When upsell is not applicable — for example if it is disabled or the payment method is unsupported — the confirmation push fires immediately with no delay to your existing flow.
Kustom supports two recommendation modes.
Provide a Google Shopping feed URL and Kustom handles enrichment, model training, and serving. No merchant_urls.upsell endpoint is needed.
| Parameter | Details |
|---|---|
| Feed format | Google Shopping XML or CSV — public URL |
| Sync frequency | Every 2–4 hours |
| One feed per | Market / currency pair (e.g. SE-SEK, DE-EUR) |
| Recommended filter | min_stock=50 to avoid out-of-stock recommendations |
The AI model works from day one without historical data and improves with every interaction.
Set merchant_urls.upsell to your recommendation endpoint. Kustom calls it before the confirmation page loads and you return the list of products to display.
{
"merchant_urls": {
"upsell": "https://www.example.com/api/upsell"
}
}Your endpoint must respond within 2–3 seconds. A slow or failed response results in no widget being shown and the push notification fires immediately.
The sections below on request/response structure apply only when using your own endpoint.
When merchant_urls.upsell is set, Kustom sends a POST request to that URL before the confirmation page loads.
| Field | Type | Description |
|---|---|---|
upsell_possible | boolean | false if the payment method does not support upsell. |
max_upsell_amount | integer | Maximum additional amount that can be authorized, in minor units. Pre-filter your recommendations by this value. |
order_lines | array | Current items in the order. |
selected_shipping_option | object | The shipping option selected by the customer. Use to filter out items that would break the selected shipping method. |
billing_address | object | Use for tax rate and locale-aware filtering. |
shipping_address | object | Use for tax rate and locale-aware filtering. |
purchase_currency | string | ISO 4217 (e.g. SEK, EUR, USD). |
locale | string | RFC 1766 (e.g. sv-SE, en-US). |
merchant_id | string | Your merchant ID. |
session_id | string | The order/session ID. Use to map the request to your internal order model. |
The callback is made even when upsell_possible is false. Return an empty upsell_lines[] array in that case to short-circuit.
These fields enable you to:
- Price products correctly based on
purchase_currencyandlocale - Apply correct tax rates based on
billing_address/shipping_address - Pre-filter candidates using the
max_upsell_amountauthorization headroom - Consider shipping compatibility via
selected_shipping_option
| Field | Type | Required | Description |
|---|---|---|---|
upsell_lines | array | Yes | List of products to display. Return an empty array to show no widget. |
last_upsell_time | string | No | ISO 8601 datetime when the upsell window expires. If omitted, Kustom uses the MID-level timeout. |
notification_uri | string | No | URL for push notifications when the order is updated with upsell items. Use as a trigger to re-read the order from the Order Management API (Method 1). |
empty | boolean | No | Signal no upsell without returning lines. |
Required fields:
| Field | Type | Description |
|---|---|---|
name | string | Product name (max 255 characters). |
quantity | integer | Default offered quantity. See note below. |
unit_price | integer | Minor units, includes tax. |
tax_rate | integer | Two implicit decimals. 2500 = 25%. |
total_amount | integer | Minor units, includes tax and discount. Must equal unit_price × quantity. |
total_tax_amount | integer | Minor units. |
max_allowed_quantity | integer | Maximum quantity the shopper can add. |
Strongly recommended fields:
| Field | Description |
|---|---|
reference | SKU or article number. |
image_url | Product card image URL (max 1024 characters). Required to render product cards. |
product_url | Link to the product page (max 1024 characters). |
description | Product description (max 1024 characters). |
product_identifiers | Product identifiers such as GTIN or ISBN. |
shipping_attributes | Weight, dimensions, and tags for shipping compatibility checks. |
feedback_url | Item-level signal URL called when a shopper adds the item. |
unit_price × quantity must equal total_amount. Kustom re-validates and recalculates when a shopper adds an item.
quantity is the default offer quantity you are proposing, not the shopper's final selection. If you are unsure, set quantity: 1 and control the upper bound via max_allowed_quantity. Kustom recalculates totals and re-validates authorization when the shopper adds items.
{
"name": "Matching Phone Case",
"quantity": 1,
"unit_price": 19900,
"max_allowed_quantity": 5,
"tax_rate": 2500,
"total_amount": 19900,
"total_tax_amount": 3980
}{
"upsell_lines": [
{
"name": "Baseball Cap",
"reference": "CAP-SAND-001",
"quantity": 1,
"unit_price": 40000,
"tax_rate": 2500,
"total_amount": 40000,
"total_tax_amount": 8000,
"max_allowed_quantity": 3,
"image_url": "https://www.example.com/images/cap-sand.jpg",
"product_url": "https://www.example.com/products/cap-sand"
}
],
"last_upsell_time": "2024-01-01T12:05:00Z"
}Set merchant_urls.upsell_validation to control whether a specific item add is allowed before Kustom processes it. This callback is not required — by default, items are added without a validation callback.
{
"merchant_urls": {
"upsell_validation": "https://www.example.com/api/upsell-validation"
}
}The request body is the same as the standard order API model, with one addition: upsell_order_lines, which contains the list of upsell lines being requested for addition. The model is the same as order_lines.
Return 2xx to allow the add. Any other status code blocks it.
Do not rely on this callback as the final confirmation. The payment authorization increase can still fail after this callback returns. Use the confirmation push to finalize the order state.
Because items can be added after the initial payment, you need to decide how your backend handles order creation. There are two approaches.

Create the order immediately when the shopper is redirected to the confirmation page, then accept updates as items are added.
- Payment is authenticated — KCO marks the checkout order as
CHECKOUT_COMPLETE. - KCO redirects to your confirmation page URL.
- Your backend reads the order and creates it in your system, placed on hold.
- You load the KCO confirmation iframe.
- KCO calls
merchant_urls.upsellto fetch recommendations. - Shopper adds items — KCO triggers the upsell validation callback if configured, increases authorization, and updates the order.
- Upsell timeout expires — KCO sends the confirmation push.
- Your backend reads the final order state and releases the hold for fulfilment.
Best for merchants who need immediate order visibility in their systems or who handle high-value items where instant inventory reservation is critical.
The order must be updatable during the upsell timeout window. Do not send it to your warehouse or trigger confirmation emails until the confirmation push arrives.
Do not create the order in your system until the confirmation push arrives. This avoids mid-session order modifications entirely.
- Payment is authenticated — KCO marks the checkout order as
CHECKOUT_COMPLETE. - KCO redirects to your confirmation page URL.
- Your backend reads the order but does not create it yet.
- You load the KCO confirmation iframe.
- KCO calls
merchant_urls.upsellto fetch recommendations. - Shopper adds items — KCO handles authorization and updates the order.
- Upsell timeout expires — KCO sends the confirmation push with the final
order_lines. - Your backend creates the order once from the push payload.
Best for most integrations — simpler logic, no order modification needed, faster go-live.
The confirmation push is only delayed if upsell is enabled for the session and the payment method supports upsell. If either condition is false, the push fires immediately — you do not need to wait.
You can determine whether upsell is active by:
- Checking
options.confirmation_page_upsellon the order object - Observing the
upsell_possiblefield in the upsell callback request - Checking whether the upsell widget appears in the iframe
| Payment method | Upsell supported |
|---|---|
| Card | Yes |
| Klarna BNPL / Pay Later | Yes |
| Swish | No |
| Direct bank transfer | No |
When upsell_possible is false, the widget is not shown and the push fires immediately with no change to your existing flow.
Kustom can increase Klarna authorization limits on a per-merchant basis. Contact Kustom to discuss your limits. Use max_upsell_amount in your recommendations endpoint to pre-filter products to amounts that can be authorized.
The upsell window is configured at the merchant ID level by Kustom, with a maximum of 15 minutes. The timeout cannot be set via the API — contact Kustom to configure your preferred duration.
Upsell is compatible with the minimal_confirmation GUI option. The upsell widget overrides it automatically when upsell is enabled.
The upsell_request always includes selected_shipping_option when available. Use this to filter out recommendations that would break the selected shipping method.
Use shipping_attributes on your upsell lines to specify weight, dimensions, and tags. This is the recommended way to ensure suggestions are compatible with the selected shipping method.
{
"shipping_attributes": {
"weight": 500,
"dimensions": {
"width": 100,
"height": 150,
"length": 200
},
"tags": ["standard", "non-fragile"]
}
}Shipping information is only included in the upsell request if you use Kustom Shipping Assistant. Without it, selected_shipping_option will not be present.
If your shipping platform requires re-rating after cart changes (for example when using a third-party TMS), you have two options:
- Pre-filter (recommended): Perform a soft compatibility check in your upsell endpoint before returning candidates. Only propose items that keep the current shipping method valid.
- Post-upsell re-rate: After an upsell is accepted, re-rate and handle any method changes per your policy. You can optionally use the
shipping_option_updatecallback for this.
Compare order_lines in the original checkout order with order_lines in the final confirmation push to identify which items were added via upsell. Use feedback_url on each upsell_line for item-level add signals.
Recommendations are fetched once before the confirmation page loads and cannot be refreshed during the upsell window. Return your best candidates in the initial response.
What does the quantity field mean in upsell_line?
It is the default offer quantity you are proposing, not the shopper's final selection. Set quantity: 1 and use max_allowed_quantity to control the upper bound. Kustom recalculates totals and re-validates authorization when the shopper adds items.
When should we create the order — on redirect or after the push?
Both are supported. Method 2 (create on push) is simpler for most integrations. Method 1 (create on redirect) is better when immediate inventory reservation is required. See Integration methods above.
How do we know if we should wait for a delayed push?
The push is only delayed if upsell is enabled and the payment method supports it. Check options.confirmation_page_upsell on the order or the upsell_possible field in the upsell request.
What happens if our upsell endpoint is slow or times out?
The confirmation page loads normally, the upsell widget is not shown, and the push fires immediately. Optimize your endpoint to respond within 2–3 seconds.
Can we A/B test recommendation variants?
Yes. You can swap your merchant_urls.upsell endpoint at any time to test variants against each other or against the Kustom AI engine.
Can we show free shipping thresholds in the widget?
No. Real-time free shipping threshold tracking within the upsell widget is not currently supported. Handle threshold logic on your side when processing the final order after the push.
What happens if the upsell amount exceeds the authorization?
Kustom validates authorization when the shopper adds items and blocks additions that exceed the limit. Pre-filtering your recommendations by max_upsell_amount improves conversion by avoiding recommendations that will be blocked.
How do we track which items were upsold?
Compare the original order_lines with the final order_lines from the confirmation push. Use feedback_url on upsell lines for item-level add signals.