Resolution API
This feature is available only to approved apps and is subject to change.
This feature is available only to approved apps and is subject to change.
The Resolution API reads the cart or payment data for your resolution interface, and registers a save handler to finish pending work before Shopify Point of Sale (POS) revalidates. For an item-targeted authenticity check demo, follow Build a cart validation UI extension.
Anchor to Use casesUse cases
- Cart findings: Derive the cart line that needs attention from the intercepted cart.
- Payment findings: Show the attempted payment method and cash amount received.
- Pending changes: Run an asynchronous check and save its result before Shopify POS revalidates.
- Revalidation updates: Refresh the interface after Shopify POS revalidates.
Anchor to Supported targetsSupported targets
Each resolution target receives the following event data:
| Target | Event data |
|---|---|
pos.cart.validations.resolution.render | {cart} |
pos.payment.validations.resolution.render | {paymentMethod, amount} |
Payment resolution has read-only cart access through ReadonlyCartApi. Use shopify.cart.current to read the cart and subscribe to changes. You can't modify the cart from this target.
Anchor to PropertiesProperties
The shopify global object provides the intercepted event data and a save handler for the active resolution target. Access the following properties on shopify to read the cart or payment event and register work that Shopify POS must await before revalidation.
- Anchor to eventeventeventReadonlySignalLike<TEventData>ReadonlySignalLike<TEventData>requiredrequired
The data of the intercepted event this resolution target was opened for. The
valueproperty provides the current data, andsubscribereceives Shopify POS revalidation updates.- Anchor to onSaveon
Saveon Save (handler: ResolutionSaveHandler) => Promise<() => Promise<void>>(handler: ResolutionSaveHandler) => Promise<() => Promise<void>>requiredrequired Registers a handler that runs when staff advance the resolution flow (Save, Next, or Done). POS awaits the handler before it re-runs the intercepted validation, so use it to commit any pending work, for example cart updates or storage writes, and
awaitthose calls inside the handler. A rejected promise does not stop the flow; POS still re-runs validation and the interceptor result decides what happens next.Only the most recent handler is kept.
ReadonlySignalLike
Represents a reactive signal interface that provides both immediate value access and subscription-based updates. Enables real-time synchronization with changing data through the observer pattern.
- subscribe
Subscribes to value changes and calls the provided function whenever the value updates. Returns an unsubscribe function to clean up the subscription. Use to automatically react to changes in the signal's value.
(fn: (value: T) => void) => () => void - value
The current value of the signal. This property provides immediate access to the current value without requiring subscription setup. Use for one-time value checks or initial setup.
T
ResolutionSaveHandler
Runs when staff advance the resolution flow. Return a promise to have POS wait for pending work to finish before it re-runs validation.
void | Promise<void>jsx
Examples
Refresh after revalidation
Description
Keep the resolution interface current after Shopify POS revalidates. This example shows how to use `shopify.resolution.event.subscribe()` in the cart resolution target to update the number of cart lines after each revalidation.
jsx
import '@shopify/ui-extensions/preact'; import {render} from 'preact'; import {signal} from '@preact/signals'; const lineCount = signal(0); export default async () => { lineCount.value = shopify.resolution.event.value.cart.lineItems.length; shopify.resolution.event.subscribe(({cart}) => { lineCount.value = cart.lineItems.length; }); render(<Extension />, document.body); }; function Extension() { return <s-text>Items after revalidation: {lineCount.value}</s-text>; }Save a note before revalidation
Description
Save staff input before Shopify POS revalidates. This example shows how to use `shopify.resolution.onSave()` in the cart resolution target to save a note to the first cart line, so your interceptor can read it during revalidation.
jsx
import '@shopify/ui-extensions/preact'; import {render} from 'preact'; import {signal} from '@preact/signals'; const note = signal(''); export default async () => { await shopify.resolution.onSave(async () => { const [line] = shopify.resolution.event.value.cart.lineItems; if (!line) return; await shopify.cart.addLineItemProperties(line.uuid, {Note: note.value.trim()}); }); render(<Extension />, document.body); }; function Extension() { return ( <s-text-field label="Note" value={note.value} onInput={(event) => { note.value = event.currentTarget.value ?? ''; }} /> ); }
Anchor to RevalidationRevalidation
When staff tap the proceed control in the resolution interface to continue to checkout or complete the payment, Shopify POS runs validation again. The interceptor's findings, not the save handler's return value, decide whether staff can continue. This applies to both resolution targets. When staff proceed:
| Situation | What Shopify POS does |
|---|---|
| The save handler resolves | Runs validation again. The findings decide whether staff can continue. |
| The save handler rejects | Still runs validation again. The rejection doesn't stop the flow. |
| The save handler doesn't finish within 10 seconds | Stops waiting and runs validation again. |
| No save handler is registered | Runs validation again. |
In payment resolution, after staff finish the flow with no blocking findings remaining, Shopify POS resumes the payment. Dismissing the interface doesn't resume it.
Anchor to Best practicesBest practices
- Save the latest change before revalidation: Await your cart or storage writes inside
shopify.resolution.onSave, and keep your interceptor returning a finding until the new state is saved. Shopify POS revalidates even if the handler rejects or runs past 10 seconds, so validation can run before a slow save finishes.