---
title: Gratuity
slug: gratuity
docTags: 
createdAt: 2025-05-12T12:36:05.961Z
---

### Tipping modes

The SDK supports three gratuity modes, configured via `GratuityConfig.mode`:

| Mode                      | Description                                                                                                 |
| ------------------------- | ----------------------------------------------------------------------------------------------------------- |
| `GratuityMode.NONE`       | No tipping prompt is shown. This is the default.                                                            |
| `GratuityMode.STANDARD`   | The SDK shows a built-in tipping menu with 10%, 15%, and 20% options. No additional configuration required. |
| `GratuityMode.CONFIGURED` | The SDK builds a tipping menu from the fixed amounts or percentages you supply.                             |

In `STANDARD` and `CONFIGURED` modes, the SDK handles the full on-device flow automatically, including the initial "Add Gratuity?" yes/no prompt, the selection menu, a built-in "Other Amount" option for free-form tip entry.

### Global configuration

Set `gratuityConfig` in `ToroConfig` to apply the same tipping behaviour to every transaction:

:::CodeblockTabs
```kotlin
val config = ToroConfig(
    gratuityConfig = GratuityConfig(mode = GratuityMode.STANDARD),
    // ...
)
```

```java
ToroConfig config = new ToroConfig(
    // ...
    new GratuityConfig(GratuityMode.DEFAULT),
    // ...
);
```
:::

### Per-transaction configuration

Pass a `GratuityConfig` in `TransactionMetadata` to override the global config for a specific transaction. This is the recommended approach when tipping behaviour varies per transaction - for example, when switching between amounts and percentages based on business logic.

:::CodeblockTabs
```kotlin
val metadata = TransactionMetadata(
    gratuityConfig = GratuityConfig(
        mode = GratuityMode.CONFIGURED,
        percentages = listOf(20, 10, 5),
        header = "Select a Tip / Gratuity:"
    )
)

toro.startTransaction(
    amount = 1000,
    type = TransactionType.Purchase,
    currencyCode = CurrencyCode.GBP,
    metadata = metadata,
    // ...
)
```

```java
GratuityConfig gratuityConfig = new GratuityConfig(
    GratuityMode.CONFIGURED,
    Collections.emptyList(),
    Arrays.asList(20, 10, 5),
    "Add Gratuity?",
    "Select a Tip / Gratuity:"
);

TransactionMetadata metadata = new TransactionMetadata(
    null,
    0,
    null,
    gratuityConfig,
    Collections.emptyMap()
);

toro.startTransaction(
    1000,
    TransactionType.Purchase,
    CurrencyCode.GBP,
    metadata,
    // ...
);
```
:::

### STANDARD mode

`GratuityMode.STANDARD` presents a built-in tipping menu with 10%, 15%, and 20% options. No amounts or percentages need to be supplied.

:::CodeblockTabs
```kotlin
GratuityConfig(mode = GratuityMode.STANDARD)
```

```java
new GratuityConfig(GratuityMode.DEFAULT)
```
:::

:::hint{type="warning"}
Supplying `amounts` or `percentages` in `STANDARD` mode will throw an `IllegalArgumentException`. Use `CONFIGURED` mode instead.
:::

### CONFIGURED mode

`GratuityMode.CONFIGURED` lets you define exactly which amounts or percentages to offer. Supply either `amounts` (in pence) or `percentages` - not both. A maximum of 3 options may be provided. The SDK automatically appends an "Other Amount" option for free-form entry.

**Fixed amounts:**

:::CodeblockTabs
```kotlin
GratuityConfig(
    mode = GratuityMode.CONFIGURED,
    amounts = listOf(300, 200, 100), // rendered as £3.00, £2.00, £1.00
    header = "Select a Tip / Gratuity:"
)
```

```java
new GratuityConfig(
    GratuityMode.CONFIGURED,
    Arrays.asList(300, 200, 100),  // rendered as £3.00, £2.00, £1.00
    Collections.emptyList(),
    "Add Gratuity?",
    "Select a Tip / Gratuity:"
)
```
:::

**Percentage-based:**

:::CodeblockTabs
```kotlin
GratuityConfig(
    mode = GratuityMode.CONFIGURED,
    percentages = listOf(20, 10, 5), // rendered as 20%, 10%, 5%
    header = "Select a Tip / Gratuity:"
)
```

```java
new GratuityConfig(
    GratuityMode.CONFIGURED,
    Collections.emptyList(),
    Arrays.asList(20, 10, 5),  // rendered as 20%, 10%, 5%
    "Add Gratuity?",
    "Select a Tip / Gratuity:"
)
```
:::

:::hint{type="warning"}
Mixing `amounts` and `percentages` in the same config will throw an `IllegalArgumentException`.
:::

### Customising prompt text

Two text fields control what is shown on-device before and during the tip selection:

- `addGratuityPrompt`: text shown on the initial yes/no screen asking the cardholder whether they want to add a tip (default: `"Add Gratuity?"`)
- `header`: title shown at the top of the tip selection menu (default: `"Add Gratuity?"`, max 30 characters)

```kotlin
GratuityConfig(
    mode = GratuityMode.CONFIGURED,
    percentages = listOf(20, 10, 5),
    addGratuityPrompt = "Add a tip?",
    header = "Select a Tip / Gratuity:"
)
```

### Responding to the customer's selection

When the customer confirms a tip, the `onGratuityConfirmed` callback is triggered:

```kotlin
onGratuityConfirmed = { gratuityAmount, gratuityPercentage ->
    // gratuityAmount: tip in the smallest currency unit (e.g. pence)
    // gratuityPercentage: whole number percentage (e.g. 15), or 0 for a fixed-amount or free-form tip
}
```

If the customer declines the tip, `onGratuityConfirmed` is still called with `gratuityAmount = 0`.

### Custom pre-transaction flow

If you prefer to collect the tip before calling `startTransaction()`, for example in your own application UI, pass it directly via `TransactionMetadata.gratuityAmount`. In this case leave `gratuityConfig` unset (or set `mode` to `NONE`) and include the tip in the total `amount`.

:::CodeblockTabs
```kotlin
val metadata = TransactionMetadata(
    gratuityAmount = 100 // £1.00
)

toro.startTransaction(
    amount = 1100, // £11.00 total (£10.00 + £1.00 tip)
    type = TransactionType.Purchase,
    currencyCode = CurrencyCode.GBP,
    metadata = metadata,
    // ...
)
```

```java
TransactionMetadata metadata = new TransactionMetadata(
    null,
    100, // £1.00
    null,
    null,
    Collections.emptyMap()
);

toro.startTransaction(
    1100, // £11.00 total (£10.00 + £1.00 tip)
    TransactionType.Purchase,
    CurrencyCode.GBP,
    metadata,
    // ...
);
```
:::

:::hint{type="warning"}
`TransactionMetadata.gratuityAmount` and a non-`NONE` `gratuityConfig` cannot both be set on the same transaction - this will throw an `IllegalArgumentException`.
:::

:::hint{type="warning"}
The `amount` parameter in `startTransaction()` must be the total transaction amount, including any gratuity.
:::

:::hint{type="info"}
The `onGratuityConfirmed` callback is not triggered when using the custom pre-transaction flow.
:::

