Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
60 commits
Select commit Hold shift + click to select a range
c4c5f02
add button cursor-pointer
cshing-godaddy Jul 1, 2026
1785322
improve tip btn styling, fix custom tip input
cshing-godaddy Jul 1, 2026
949b03c
enable tips in nextjs example
cshing-godaddy Jul 1, 2026
cfed7a4
fix tipPercentage schema
cshing-godaddy Jul 1, 2026
0d559e5
pass tipAmount in confirmCheckout
cshing-godaddy Jul 1, 2026
ac650af
add tipAmount definition
cshing-godaddy Jul 1, 2026
813e2a3
formatting
cshing-godaddy Jul 1, 2026
3878b05
add tests
cshing-godaddy Jul 1, 2026
d1d3bb3
changeset
cshing-godaddy Jul 1, 2026
b229861
Merge remote-tracking branch 'upstream/main'
cshing-godaddy Jul 6, 2026
5f148d9
Merge branch 'main' into main
pbennett1-godaddy Jul 8, 2026
9f4fc31
calculate tips from subtotal instead of total
cshing-godaddy Jul 9, 2026
112c161
add tips definition
cshing-godaddy Jul 9, 2026
8197e34
handle tip amounts
cshing-godaddy Jul 9, 2026
2eb2f64
fix tip amount selection
cshing-godaddy Jul 9, 2026
0e5649f
lint
cshing-godaddy Jul 10, 2026
8962669
handle tip thresholds
cshing-godaddy Jul 10, 2026
6afe9d4
regenerate from schema
cshing-godaddy Jul 10, 2026
c74a86b
renegerate checkout-env for MutationAuthorizeCheckoutSessionInput.tip…
cshing-godaddy Jul 10, 2026
db41364
revert add tipAmount
cshing-godaddy Jul 10, 2026
6db8aff
add tipAmount to provider payment request total
cshing-godaddy Jul 10, 2026
773b1b8
lint
cshing-godaddy Jul 10, 2026
72ac855
check session.enableTips before adding tipAmount
cshing-godaddy Jul 10, 2026
daac42e
update tests
cshing-godaddy Jul 10, 2026
4261978
remove feeProgramId
cshing-godaddy Jul 13, 2026
af81b66
pr feedback
cshing-godaddy Jul 13, 2026
539443e
update express request to use total instead of subtotal
cshing-godaddy Jul 15, 2026
c14a32d
update tests
cshing-godaddy Jul 15, 2026
fefe8cc
Merge branch 'main' into main
cshing-godaddy Jul 24, 2026
026d2b4
claude feedback
cshing-godaddy Jul 27, 2026
dd11982
claude feedback
cshing-godaddy Jul 27, 2026
53e5be1
add fallback
cshing-godaddy Jul 27, 2026
3d597b2
include tip in useAuthorizeCheckout
cshing-godaddy Jul 30, 2026
e30bb0a
thread tip into useConfirmExpressCheckout
cshing-godaddy Jul 30, 2026
2c5913c
update README
cshing-godaddy Jul 30, 2026
8bb0b66
gate tips in checkout-form
cshing-godaddy Jul 30, 2026
f59c38b
remove dead code
cshing-godaddy Jul 30, 2026
0f13a58
handle tip for zero-total orders
cshing-godaddy Jul 30, 2026
752d60e
preserve ccavenue tip
cshing-godaddy Jul 30, 2026
d21e30d
rebuild mercado brick on amount change
cshing-godaddy Jul 30, 2026
e1e8292
fix stripe intent tip
cshing-godaddy Jul 30, 2026
02bfd2e
Merge remote-tracking branch 'upstream'
cshing-godaddy Aug 7, 2026
5485aa0
claude feedback
cshing-godaddy Aug 7, 2026
e700f60
claude feedback
cshing-godaddy Aug 7, 2026
60214ae
claude feedback
cshing-godaddy Aug 7, 2026
d437c21
claude feedback
cshing-godaddy Aug 10, 2026
573ccbb
claude feedback
cshing-godaddy Aug 10, 2026
8fe0996
claude feedback
cshing-godaddy Aug 10, 2026
a88195a
fix tip preset a11y, selection state, and threshold config warning
cshing-godaddy Aug 10, 2026
685f776
fix tip recalculation and express tip field errors
cshing-godaddy Aug 11, 2026
e9d3484
Merge remote-tracking branch 'upstream'
cshing-godaddy Aug 18, 2026
5babfb3
fix test
cshing-godaddy Aug 18, 2026
6a7d3fe
Merge branch 'main' into main
cshing-godaddy Aug 18, 2026
6985642
regenerate checkout-env
cshing-godaddy Aug 18, 2026
08dcac0
fix PayPal tip drift and CCAvenue confirmation when jwt arrives late
cshing-godaddy Aug 18, 2026
b0c552e
add missing tip apiErrors translations to every locale
cshing-godaddy Aug 18, 2026
62f8ab0
keep express checkout tip-free
cshing-godaddy Aug 19, 2026
02a736e
reset the payment method when a tip makes a free order payable
cshing-godaddy Aug 19, 2026
0f64700
hide percentage tip presets when the subtotal is zero
cshing-godaddy Aug 19, 2026
3876058
point a rejected tip-only charge at the tip field
cshing-godaddy Aug 19, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions .changeset/fruity-dots-jog.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
---
"@godaddy/react": patch
---

Support tips in unified checkout

Adds the `tips` session config surface (`default` and threshold-based `amounts`/`percentages` presets) alongside `enableTips`, and includes the selected tip in wallet sheet totals and the authorized/confirmed amount.

For redirect gateways (CCAvenue), the authorized tip is persisted across the redirect so the confirmation on the return leg records the tip the customer was actually charged. Checkout refuses to redirect when a non-zero tip cannot be persisted, rather than sending the customer to pay a tip the order would not include.

Express checkout stays tip-free: its wallet sheets open on the item subtotal and add the shipping and taxes they calculate in their own event flows, and its confirmation records no tip.

Also gives every `Button` a `cursor-pointer`, so buttons rendered as `<button>` show a pointer cursor on hover instead of the browser default.
5 changes: 5 additions & 0 deletions .changeset/tip-api-error-translations.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@godaddy/localizations": patch
---

Add the missing tip `apiErrors` translations to every locale
13 changes: 13 additions & 0 deletions examples/nextjs/app/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,19 @@ export default async function Home() {
enableTaxCollection: true,
enableNotesCollection: true,
enablePromotionCodes: true,
enableTips: true,
tips: {
default: {
percentages: [ 20, 40, 60 ]
},
thresholds: [
{
minSubtotal: 0,
maxSubtotal: 1000,
amounts: [ 300, 500, 700 ]
}
]
},
shipping: {
fulfillmentLocationId: 'default-location',
originAddress: {
Expand Down
5 changes: 5 additions & 0 deletions packages/localizations/src/deDe.ts
Original file line number Diff line number Diff line change
Expand Up @@ -369,6 +369,11 @@ export const deDe = {
DEPENDENCY_ERROR:
'Wir können Ihre Bestellung derzeit nicht bearbeiten. Bitte warten Sie einen Moment und versuchen Sie es erneut',
AUTHORIZATION_FAILED: 'Zahlungsautorisierung fehlgeschlagen',
TIP_EXCEEDS_LIMIT: 'Das Trinkgeld ist für diese Bestellung zu hoch',
INVALID_TIP_AMOUNT: 'Gültigen Trinkgeldbetrag eingeben',
TIPS_NOT_ENABLED: 'Für diese Bestellung wird kein Trinkgeld akzeptiert',
TIP_CHARGE_FAILED:
'Anderen Trinkgeldbetrag versuchen oder Kein Trinkgeld auswählen',
},
storefront: {
product: 'Produkt',
Expand Down
4 changes: 4 additions & 0 deletions packages/localizations/src/enAu.ts
Original file line number Diff line number Diff line change
Expand Up @@ -345,6 +345,10 @@ export const enAu = {
DEPENDENCY_ERROR:
"We're unable to process your order right now. Please wait a moment and try again",
AUTHORIZATION_FAILED: 'Failed to authorise payment',
TIP_EXCEEDS_LIMIT: 'Tip is too large for this order',
INVALID_TIP_AMOUNT: 'Enter a valid tip amount',
TIPS_NOT_ENABLED: 'Tips are not accepted for this order',
TIP_CHARGE_FAILED: 'Try a different tip amount, or choose No Tip',
},
storefront: {
product: 'Product',
Expand Down
4 changes: 4 additions & 0 deletions packages/localizations/src/enIe.ts
Original file line number Diff line number Diff line change
Expand Up @@ -345,6 +345,10 @@ export const enIe = {
DEPENDENCY_ERROR:
"We're unable to process your order right now. Please wait a moment and try again",
AUTHORIZATION_FAILED: 'Failed to authorise payment',
TIP_EXCEEDS_LIMIT: 'Tip is too large for this order',
INVALID_TIP_AMOUNT: 'Enter a valid tip amount',
TIPS_NOT_ENABLED: 'Tips are not accepted for this order',
TIP_CHARGE_FAILED: 'Try a different tip amount, or choose No Tip',
},
storefront: {
product: 'Product',
Expand Down
4 changes: 4 additions & 0 deletions packages/localizations/src/enUs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -345,6 +345,10 @@ export const enUs = {
DEPENDENCY_ERROR:
"We're unable to process your order right now. Please wait a moment and try again",
AUTHORIZATION_FAILED: 'Failed to authorize payment',
TIP_EXCEEDS_LIMIT: 'Tip is too large for this order',
INVALID_TIP_AMOUNT: 'Enter a valid tip amount',
TIPS_NOT_ENABLED: 'Tips are not accepted for this order',
TIP_CHARGE_FAILED: 'Try a different tip amount, or choose No Tip',
},
storefront: {
product: 'Product',
Expand Down
4 changes: 4 additions & 0 deletions packages/localizations/src/esAr.ts
Original file line number Diff line number Diff line change
Expand Up @@ -352,6 +352,10 @@ export const esAr = {
DEPENDENCY_ERROR:
'No podemos procesar su pedido en este momento. Espere un momento e inténtelo de nuevo',
AUTHORIZATION_FAILED: 'Error al autorizar el pago',
TIP_EXCEEDS_LIMIT: 'La propina es demasiado alta para este pedido',
INVALID_TIP_AMOUNT: 'Ingresá un monto de propina válido',
TIPS_NOT_ENABLED: 'No se aceptan propinas para este pedido',
TIP_CHARGE_FAILED: 'Probá otro monto de propina o elegí Sin Propina',
},
storefront: {
product: 'Producto',
Expand Down
4 changes: 4 additions & 0 deletions packages/localizations/src/esCl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -354,6 +354,10 @@ export const esCl = {
DEPENDENCY_ERROR:
'No podemos procesar su pedido en este momento. Espere un momento e inténtelo de nuevo',
AUTHORIZATION_FAILED: 'Error al autorizar el pago',
TIP_EXCEEDS_LIMIT: 'La propina es demasiado alta para este pedido',
INVALID_TIP_AMOUNT: 'Ingresa un monto de propina válido',
TIPS_NOT_ENABLED: 'No se aceptan propinas para este pedido',
TIP_CHARGE_FAILED: 'Prueba otro monto de propina o elige Sin Propina',
},
storefront: {
product: 'Producto',
Expand Down
4 changes: 4 additions & 0 deletions packages/localizations/src/esCo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -352,6 +352,10 @@ export const esCo = {
DEPENDENCY_ERROR:
'No podemos procesar su pedido en este momento. Espere un momento e inténtelo de nuevo',
AUTHORIZATION_FAILED: 'Error al autorizar el pago',
TIP_EXCEEDS_LIMIT: 'La propina es demasiado alta para este pedido',
INVALID_TIP_AMOUNT: 'Ingresa un monto de propina válido',
TIPS_NOT_ENABLED: 'No se aceptan propinas para este pedido',
TIP_CHARGE_FAILED: 'Prueba otro monto de propina o elige Sin propina',
},
storefront: {
product: 'Producto',
Expand Down
4 changes: 4 additions & 0 deletions packages/localizations/src/esEs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -357,6 +357,10 @@ export const esEs = {
DEPENDENCY_ERROR:
'No podemos procesar su pedido en este momento. Espere un momento e inténtelo de nuevo',
AUTHORIZATION_FAILED: 'Error al autorizar el pago',
TIP_EXCEEDS_LIMIT: 'La propina es demasiado alta para este pedido',
INVALID_TIP_AMOUNT: 'Introduce una cantidad de propina válida',
TIPS_NOT_ENABLED: 'No se aceptan propinas para este pedido',
TIP_CHARGE_FAILED: 'Prueba otra cantidad de propina o elige Sin propina',
},
storefront: {
product: 'Producto',
Expand Down
4 changes: 4 additions & 0 deletions packages/localizations/src/esMx.ts
Original file line number Diff line number Diff line change
Expand Up @@ -353,6 +353,10 @@ export const esMx = {
DEPENDENCY_ERROR:
'No podemos procesar su pedido en este momento. Espere un momento e inténtelo de nuevo',
AUTHORIZATION_FAILED: 'Error al autorizar el pago',
TIP_EXCEEDS_LIMIT: 'La propina es demasiado alta para este pedido',
INVALID_TIP_AMOUNT: 'Ingrese una cantidad de propina válida',
TIPS_NOT_ENABLED: 'No se aceptan propinas para este pedido',
TIP_CHARGE_FAILED: 'Pruebe otra cantidad de propina o elija Sin Propina',
},
storefront: {
product: 'Producto',
Expand Down
4 changes: 4 additions & 0 deletions packages/localizations/src/esPe.ts
Original file line number Diff line number Diff line change
Expand Up @@ -352,6 +352,10 @@ export const esPe = {
DEPENDENCY_ERROR:
'No podemos procesar su pedido en este momento. Espere un momento e inténtelo de nuevo',
AUTHORIZATION_FAILED: 'Error al autorizar el pago',
TIP_EXCEEDS_LIMIT: 'La propina es demasiado alta para este pedido',
INVALID_TIP_AMOUNT: 'Ingrese un monto de propina válido',
TIPS_NOT_ENABLED: 'No se aceptan propinas para este pedido',
TIP_CHARGE_FAILED: 'Pruebe otro monto de propina o elija Sin Propina',
},
storefront: {
product: 'Producto',
Expand Down
4 changes: 4 additions & 0 deletions packages/localizations/src/esUs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -352,6 +352,10 @@ export const esUs = {
DEPENDENCY_ERROR:
'No podemos procesar su pedido en este momento. Espere un momento e inténtelo de nuevo',
AUTHORIZATION_FAILED: 'Error al autorizar el pago',
TIP_EXCEEDS_LIMIT: 'La propina es demasiado alta para este pedido',
INVALID_TIP_AMOUNT: 'Ingrese una cantidad de propina válida',
TIPS_NOT_ENABLED: 'No se aceptan propinas para este pedido',
TIP_CHARGE_FAILED: 'Pruebe otra cantidad de propina o elija Sin Propina',
},
storefront: {
product: 'Producto',
Expand Down
5 changes: 5 additions & 0 deletions packages/localizations/src/frCa.ts
Original file line number Diff line number Diff line change
Expand Up @@ -369,6 +369,11 @@ export const frCa = {
DEPENDENCY_ERROR:
'Nous ne pouvons pas traiter votre commande actuellement. Veuillez patienter un moment et réessayer',
AUTHORIZATION_FAILED: "Échec de l'autorisation du paiement",
TIP_EXCEEDS_LIMIT: 'Le pourboire est trop élevé pour cette commande',
INVALID_TIP_AMOUNT: 'Entrez un montant de pourboire valide',
TIPS_NOT_ENABLED: 'Les pourboires ne sont pas acceptés pour cette commande',
TIP_CHARGE_FAILED:
'Essayez un autre montant de pourboire ou choisissez Aucun pourboire',
},
storefront: {
product: 'Produit',
Expand Down
5 changes: 5 additions & 0 deletions packages/localizations/src/frFr.ts
Original file line number Diff line number Diff line change
Expand Up @@ -370,6 +370,11 @@ export const frFr = {
DEPENDENCY_ERROR:
'Nous ne pouvons pas traiter votre commande actuellement. Veuillez patienter un moment et réessayer',
AUTHORIZATION_FAILED: "Échec de l'autorisation du paiement",
TIP_EXCEEDS_LIMIT: 'Le pourboire est trop élevé pour cette commande',
INVALID_TIP_AMOUNT: 'Entrez un montant de pourboire valide',
TIPS_NOT_ENABLED: 'Les pourboires ne sont pas acceptés pour cette commande',
TIP_CHARGE_FAILED:
'Essayez un autre montant de pourboire ou choisissez Aucun pourboire',
},
storefront: {
product: 'Produit',
Expand Down
4 changes: 4 additions & 0 deletions packages/localizations/src/idId.ts
Original file line number Diff line number Diff line change
Expand Up @@ -344,6 +344,10 @@ export const idId = {
DEPENDENCY_ERROR:
'Kami tidak dapat memproses pesanan Anda saat ini. Silakan tunggu sebentar dan coba lagi',
AUTHORIZATION_FAILED: 'Gagal mengotorisasi pembayaran',
TIP_EXCEEDS_LIMIT: 'Tip terlalu besar untuk pesanan ini',
INVALID_TIP_AMOUNT: 'Masukkan jumlah tip yang valid',
TIPS_NOT_ENABLED: 'Tip tidak diterima untuk pesanan ini',
TIP_CHARGE_FAILED: 'Coba jumlah tip lain atau pilih Tanpa Tip',
},
storefront: {
product: 'Produk',
Expand Down
5 changes: 5 additions & 0 deletions packages/localizations/src/itIt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -368,6 +368,11 @@ export const itIt = {
DEPENDENCY_ERROR:
'Non riusciamo a elaborare il tuo ordine in questo momento. Aspetta un momento e riprova',
AUTHORIZATION_FAILED: "Errore nell'autorizzazione del pagamento",
TIP_EXCEEDS_LIMIT: 'La mancia è troppo alta per questo ordine',
INVALID_TIP_AMOUNT: 'Inserisci un importo della mancia valido',
TIPS_NOT_ENABLED: 'Le mance non sono accettate per questo ordine',
TIP_CHARGE_FAILED:
'Prova un altro importo della mancia o scegli Nessuna Mancia',
},
storefront: {
product: 'Prodotto',
Expand Down
4 changes: 4 additions & 0 deletions packages/localizations/src/ptBr.ts
Original file line number Diff line number Diff line change
Expand Up @@ -350,6 +350,10 @@ export const ptBr = {
DEPENDENCY_ERROR:
'Não conseguimos processar seu pedido no momento. Aguarde um momento e tente novamente',
AUTHORIZATION_FAILED: 'Falha ao autorizar pagamento',
TIP_EXCEEDS_LIMIT: 'A gorjeta é muito alta para este pedido',
INVALID_TIP_AMOUNT: 'Digite um valor de gorjeta válido',
TIPS_NOT_ENABLED: 'Gorjetas não são aceitas para este pedido',
TIP_CHARGE_FAILED: 'Tente outro valor de gorjeta ou escolha Sem Gorjeta',
},
storefront: {
product: 'Produto',
Expand Down
4 changes: 4 additions & 0 deletions packages/localizations/src/qaPs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -354,6 +354,10 @@ export const qaPs = {
DEPENDENCY_ERROR:
'موږ اوس ستاسو امر پروسس نشو کولی. مهرباني وکړئ یو شېبه انتظار وکړئ او بیا هڅه وکړئ',
AUTHORIZATION_FAILED: '[Fâîlëd ţö âüţhörîžë þâÿmëñţ]',
TIP_EXCEEDS_LIMIT: '[Ţîþ îš ţöö lârgë för ţhîš örðër]',
INVALID_TIP_AMOUNT: '[Ëñţër â vâlîd ţîþ âmöüñţ]',
TIPS_NOT_ENABLED: '[Ţîþš ârë ñöţ âççëþţëd för ţhîš örðër]',
TIP_CHARGE_FAILED: '[Ţrÿ â dîffërëñţ ţîþ âmöüñţ, ör çhööšë Ñö Ţîþ]',
},
storefront: {
product: '[Product]',
Expand Down
4 changes: 4 additions & 0 deletions packages/localizations/src/trTr.ts
Original file line number Diff line number Diff line change
Expand Up @@ -345,6 +345,10 @@ export const trTr = {
DEPENDENCY_ERROR:
'Şu anda siparişinizi işleme alamıyoruz. Lütfen bir dakika bekleyin ve tekrar deneyin',
AUTHORIZATION_FAILED: 'Ödeme yetkilendirmesi başarısız',
TIP_EXCEEDS_LIMIT: 'Bahşiş bu sipariş için çok yüksek',
INVALID_TIP_AMOUNT: 'Geçerli bir bahşiş tutarı girin',
TIPS_NOT_ENABLED: 'Bu sipariş için bahşiş kabul edilmiyor',
TIP_CHARGE_FAILED: 'Farklı bir bahşiş tutarı deneyin veya Bahşiş Yok seçin',
},
storefront: {
product: 'Ürün',
Expand Down
4 changes: 4 additions & 0 deletions packages/localizations/src/viVn.ts
Original file line number Diff line number Diff line change
Expand Up @@ -345,6 +345,10 @@ export const viVn = {
DEPENDENCY_ERROR:
'Chúng tôi không thể xử lý đơn hàng của bạn ngay bây giờ. Vui lòng đợi một chút và thử lại',
AUTHORIZATION_FAILED: 'Không thể ủy quyền thanh toán',
TIP_EXCEEDS_LIMIT: 'Tiền tip quá lớn cho đơn hàng này',
INVALID_TIP_AMOUNT: 'Nhập số tiền tip hợp lệ',
TIPS_NOT_ENABLED: 'Đơn hàng này không nhận tiền tip',
TIP_CHARGE_FAILED: 'Hãy thử số tiền tip khác hoặc chọn Không tip',
},
storefront: {
product: 'Sản phẩm',
Expand Down
4 changes: 4 additions & 0 deletions packages/localizations/src/zhCn.ts
Original file line number Diff line number Diff line change
Expand Up @@ -332,6 +332,10 @@ export const zhCn = {
MISSING_SHIPPING_INFO: '配送地址或方式应用失败',
DEPENDENCY_ERROR: '我们目前无法处理您的订单。请稍等片刻再试',
AUTHORIZATION_FAILED: '付款授权失败',
TIP_EXCEEDS_LIMIT: '小费金额超出此订单的上限',
INVALID_TIP_AMOUNT: '请输入有效的小费金额',
TIPS_NOT_ENABLED: '此订单不接受小费',
TIP_CHARGE_FAILED: '请尝试其他小费金额或选择无小费',
},
storefront: {
product: '产品',
Expand Down
4 changes: 4 additions & 0 deletions packages/localizations/src/zhSg.ts
Original file line number Diff line number Diff line change
Expand Up @@ -332,6 +332,10 @@ export const zhSg = {
MISSING_SHIPPING_INFO: '配送地址或方式应用失败',
DEPENDENCY_ERROR: '我們目前無法處理您的訂單。請稍等片刻再試',
AUTHORIZATION_FAILED: '付款授权失败',
TIP_EXCEEDS_LIMIT: '小费金额超出此订单的上限',
INVALID_TIP_AMOUNT: '输入有效的小费金额',
TIPS_NOT_ENABLED: '此订单不接受小费',
TIP_CHARGE_FAILED: '请尝试其他小费金额或选择无小费',
},
storefront: {
product: '产品',
Expand Down
59 changes: 59 additions & 0 deletions packages/react/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ The first parameter accepts all checkout session configuration options from the
- **`enableSurcharge`** (boolean): Enable surcharge fees
- **`enableTaxCollection`** (boolean): Enable tax collection
- **`enableTips`** (boolean): Enable tip/gratuity options
- **`tips`** (CheckoutSessionTipsInput): Tip option configuration (see [Tips](#tips))
- **`enabledLocales`** ([String!]): List of enabled locales
- **`enabledPaymentProviders`** ([String!]): List of enabled payment providers
- **`environment`** (enum): Environment - `ote`, `prod`
Expand Down Expand Up @@ -135,6 +136,64 @@ operatingHours: {
- **Timezone handling** — All date/time logic uses the store's `timeZone`, not the customer's browser timezone. A store in Phoenix shows Phoenix hours regardless of where the customer is browsing from.
- **No available slots** — In `dateAndTime` mode, when leadTime exceeds the entire pickup window, no days are enabled, or no selectable slots exist, a "No available time slots" banner is shown.

### Tips

The `tips` field configures preset tip options shown to the customer when `enableTips` is `true`. Tips supports a `default` preset and optional `thresholds` that activate based on the order subtotal.

Throughout this section, "subtotal" means the order's **item subtotal** (`totals.subTotal`) — the sum of item prices **before** discounts, shipping, fees and tax. It is not the order total the customer pays. See [Subtotal basis](#behavior-notes) below.

Every option list — `default` and each threshold — must supply **exactly one** of `amounts` or `percentages`, with **exactly three** values. The API rejects sessions that provide both, neither, or a different number of values. Three values is also what the tip selector is laid out for.

```typescript
tips: {
default: {
percentages: [15, 18, 20],
},
thresholds: [
{
minSubtotal: 0,
maxSubtotal: 999,
amounts: [100, 200, 500],
},
{
minSubtotal: 1000,
maxSubtotal: 4999,
amounts: [200, 400, 700],
},
],
}
```

#### `tips.default`

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `amounts` | number[] | Conditional | Fixed tip amounts in the smallest currency unit (e.g. cents). Exactly three values. Mutually exclusive with `percentages`. |
| `percentages` | number[] | Conditional | Tip percentage options (integers between 0 and 100). Exactly three values. Mutually exclusive with `amounts`. |

#### `tips.thresholds`

An array of threshold objects that override the default tips when the order's item subtotal falls within the specified range.

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `minSubtotal` | number | Yes | Minimum item subtotal (inclusive) in the smallest currency unit for this threshold to apply. Required by the API — omitting it fails with `INVALID_TIP_THRESHOLD`. |
| `maxSubtotal` | number | Yes | Maximum item subtotal (inclusive) in the smallest currency unit for this threshold to apply. Required by the API — omitting it fails with `INVALID_TIP_THRESHOLD`. Must be greater than `minSubtotal`. |
| `amounts` | number[] | Conditional | Fixed tip amounts in the smallest currency unit (e.g. cents). Exactly three values. Mutually exclusive with `percentages`. |
| `percentages` | number[] | Conditional | Tip percentage options (integers between 0 and 100). Exactly three values. Mutually exclusive with `amounts`. |

#### Behavior Notes

- **Subtotal basis** — `minSubtotal`, `maxSubtotal` and every `percentages` calculation use the order's item subtotal (`totals.subTotal`), which is the sum of item prices **before discounts, shipping, fees and tax**. A $50 cart with a $20 discount, $6 shipping and $2 tax has a subtotal of `5000`, not the `3800` the customer pays, so it matches a `0–5000` threshold and `20%` offers `1000`. Configure ranges against the pre-discount cart value, not the amount charged.
- **Threshold matching is client-side** — Checkout selects the preset list. The API stores `tips` and validates its shape, but never re-derives which threshold applied.
- **Tip ceiling is measured against the order total** — Independent of the presets, the API rejects a `tipAmount` above 100% of the **order total** (post-discount, tax and shipping included) or `2000` minor units, whichever is greater, with `TIP_EXCEEDS_LIMIT`. Note the asymmetry: thresholds bucket on the subtotal, this bound uses the total. Large fixed `amounts` can therefore be rejected on a heavily discounted order — e.g. `amounts: [2500, 5000, 10000]` on an order totalling `1000` allows at most `2000`.
- **Threshold matching** — Checkout uses the **first** threshold whose range contains the item subtotal. Both bounds are inclusive, so a subtotal equal to `minSubtotal` or `maxSubtotal` matches.
- **Overlaps are not validated** — The API checks neither overlap nor full coverage of the subtotal range. Adjacent thresholds that share a boundary (e.g. `0–1000` and `1000–2000`) are accepted and resolve silently to whichever comes first in the array. Make ranges contiguous but non-overlapping (e.g. `0–999` then `1000–1999`) so the applied threshold is unambiguous.
- **Gaps fall back to `default`** — A subtotal outside every threshold range uses `tips.default`.
- **No `tips` configured** — When `enableTips` is `true` but `tips` is omitted, checkout shows `15%`, `18%`, and `20%`.
- **Both lists on one threshold** — Should a threshold reach checkout with both `amounts` and `percentages` (the API rejects this), `amounts` wins and the percentages are ignored.
- **Customer overrides** — The presets are suggestions. The tip selector also offers "No tip" and "Custom amount", and the API does not check `tipAmount` against the configured options, so the confirmed tip need not match any preset.

### Appearance

The `appearance` field customizes the checkout's look and feel.
Expand Down
Loading
Loading