# Android checkout

> Open Bolt Checkout from an Android app with an order token from your backend.

Source: https://help.boltapp.com/developers/sdks/android-kotlin/checkout

<span id="overview" />

## Before you begin [#before-you-begin]

Complete [steps 1 through 5 of the Custom Cart integration](/custom-cart/overview#1-requirements). Your app also needs:

* The [Android SDK installed and initialized](/developers/sdks/android-kotlin#installation) with the publishable key and environment for this integration.
* An application backend endpoint that returns a fresh order token for the current cart.

Never call `POST /v1/merchant/orders` or put a Bolt API key in the app. Follow [Create an order token](/custom-cart/create-order-token) for the server implementation.

<span id="generating-an-order-token-backend" />

<span id="request" />

<span id="request-body" />

<span id="response" />

<span id="end-to-end-flow" />

## 1. Get an order token [#1-get-an-order-token]

When the shopper selects checkout, send the current cart identifier to your backend. Wait for your backend to return the `token` from Bolt before opening checkout.

Create a new order token when the cart changes or the shopper starts another checkout attempt.

<span id="implementing-the-checkout-flow" />

<span id="complete-example-activity" />

## 2. Register the result launcher [#2-register-the-result-launcher]

Register an `ActivityResultLauncher` while the activity is being created. The delegate handles the three terminal results:

```kotlin title="Kotlin"
import android.content.Intent
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.result.ActivityResultLauncher
import com.bolt.checkout.BoltCheckout
import com.bolt.checkout.intl.BoltCheckoutDelegate
import com.bolt.checkout.intl.BoltCheckoutResult

class MainActivity : ComponentActivity() {
    private lateinit var checkoutLauncher: ActivityResultLauncher<Intent>

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        checkoutLauncher = BoltCheckout.get().getBoltCheckoutActivityResultLauncher(
            activity = this,
            boltCheckoutDelegate = object : BoltCheckoutDelegate {
                override fun onCheckoutSuccess(result: BoltCheckoutResult) {
                    println("Bolt transaction: ${result.transactionReference}")
                }

                override fun onCheckoutError(errorReason: String) {
                    println("Bolt Checkout failed: $errorReason")
                }

                override fun onCheckoutCancel() {
                    // Return the shopper to the cart.
                }
            },
        )
    }
}
```

The app callback controls client-side state only. Use verified Merchant Callbacks and transaction webhooks as the source of truth for order and payment state.

<span id="launching-from-a-fragment" />

### Register from a fragment [#register-from-a-fragment]

Use the fragment overload when a `Fragment` owns the checkout result:

```kotlin title="Kotlin"
checkoutLauncher = BoltCheckout.get().getBoltCheckoutActivityResultLauncher(
    fragment = this,
    boltCheckoutDelegate = checkoutDelegate,
)
```

## 3. Open checkout [#3-open-checkout]

After your backend returns the order token, configure checkout and pass the registered launcher:

```kotlin title="Kotlin"
import com.bolt.checkout.model.BoltCheckoutConfig

fun openBoltCheckout(orderToken: String) {
    val config = BoltCheckoutConfig(orderToken = orderToken)

    BoltCheckout.get().startCheckout(
        checkoutConfig = config,
        context = this,
        checkoutActivityResultLauncher = checkoutLauncher,
    )
}
```

<span id="pre-filling-customer-data" />

### Prefill shopper details [#prefill-shopper-details]

Pass optional hints when your app already has shopper information:

```kotlin title="Kotlin"
import com.bolt.checkout.model.BoltCheckoutConfig
import com.bolt.checkout.model.BoltMerchantHints

val hints = BoltMerchantHints(
    firstName = "Ada",
    lastName = "Lovelace",
    email = "ada@example.com",
    country = "US",
)

val config = BoltCheckoutConfig(orderToken = orderToken, hints = hints)
```

Do not send placeholder or stale values. The shopper can review the information in checkout.

<span id="ui-modes" />

## 4. Verify the Android client [#4-verify-the-android-client]

In sandbox:

1. Start checkout from a cart and confirm your backend returns a new order token.
2. Confirm Bolt Checkout opens and shows the same items and total as the cart.
3. Complete a purchase with a [sandbox test card](/getting-started/test-cards).
4. Confirm the app receives a success result and your backend receives the expected callback and webhook events.
5. Cancel another attempt and confirm the app returns the shopper to the cart without treating it as a completed order.

If checkout does not open or the cart does not match, continue to [Custom Cart troubleshooting](/custom-cart/troubleshooting).

<span id="next" />
