πŸ“ Bolt Help / Developer Resources / Bolt SDKs / iOS / Swift SDK / Checkout Flow
Checkout Flow
Generate order tokens and launch the Bolt managed checkout experience from your iOS app.

Overview

The Bolt iOS SDK provides a managed checkout flow that handles the entire payment experience β€” shipping, payment entry, and order completion. To launch checkout, your backend generates an order token and your app passes it to the SDK.

The SDK offers three levels of integration, from simplest to most explicit:

Approach Best For
Completion handler Simplest β€” works from anywhere, including SwiftUI.
Delegate pattern Callback-based, mirrors the Android SDK.
View controller Full control over presentation.

Generating an Order Token (Backend)

Before launching the checkout UI, your backend server must create an order token by calling the Bolt Merchant Orders API. This token represents the cart and is required by the SDK to start checkout.

WARNING

The API key used to authenticate this request is a secret. This call must be made from your server β€” never from the mobile app.

Request

POST https://api.bolt.com/v1/merchant/orders
Content-Type: application/json
X-Api-Key: <YOUR_MERCHANT_API_KEY>
Environment Endpoint
Sandbox https://api-sandbox.bolt.com/v1/merchant/orders
Production https://api.bolt.com/v1/merchant/orders

Request Body

All amounts are in cents (e.g. 1783 = $17.83).

{
  "cart": {
    "order_reference": "your-unique-order-id",
    "display_id": "ORDER-1234",
    "currency": "USD",
    "total_amount": 1783,
    "tax_amount": 0,
    "items": [
      {
        "name": "Cotton T-Shirt",
        "reference": "SKU-001",
        "description": "Comfortable cotton tee",
        "sku": "SKU-001",
        "total_amount": 1930,
        "unit_price": 965,
        "quantity": 2,
        "type": "unknown",
        "tax_amount": 0,
        "image_url": "https://example.com/tshirt.jpg"
      }
    ],
    "shipments": [
      {
        "cost": 103,
        "service": "Standard Shipping"
      }
    ],
    "discounts": [
      {
        "amount": 250,
        "type": "discount"
      }
    ]
  }
}

Response

{
  "token": "bolt-order-token-abc123"
}

Your backend returns this token to your mobile app, which then passes it to the SDK.

End-to-End Flow

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”        β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”        β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  Mobile App  │──(1)──▢│  Your Backend    │──(2)──▢│ Bolt API β”‚
β”‚              β”‚        β”‚                  β”‚        β”‚          β”‚
β”‚              │◀──(3)──│  (API key stays  │◀──(3)──│          β”‚
β”‚              β”‚        β”‚   server-side)   β”‚        β”‚          β”‚
β”‚              β”‚        β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜        β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
β”‚              β”‚
β”‚  (4) Pass token to BoltCheckout.shared.startCheckout(...)
β”‚              β”‚
β”‚  (5) SDK opens checkout UI β†’ user completes payment
β”‚              β”‚
β”‚  (6) Receive result via completion handler or delegate
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
  1. User taps “Checkout” β€” app sends cart details to your backend.
  2. Your backend calls POST /v1/merchant/orders with the cart and your API key.
  3. Bolt returns the order token; your backend forwards it to the app.
  4. App passes the token to the SDK.
  5. SDK presents the checkout experience.
  6. App receives the result (success, cancelled, or failed).

Option A: Completion Handler (Simplest)

The SDK automatically finds the topmost view controller and presents the checkout. No UIViewController reference needed β€” works from anywhere, including SwiftUI.

import BoltInternal

func onCheckoutButtonTapped() {
    let config = BoltCheckoutConfig(
        orderToken: "order-token-from-your-backend",
        hints: Bolt.Hints(
            firstName: "",
            lastName: "",
            email: "",
            phone: "",
            phoneCountryCode: nil,
            addressLine1: "",
            addressLine2: nil,
            city: "",
            state: "",
            zip: "",
            country: "",      // ISO 3166-1 alpha-2 code, e.g. "US"
            companyName: ""   // Optional
        )
    )

    BoltCheckout.shared.startCheckout(config: config) { outcome in
        switch outcome {
        case .success(let result):
            print("Order completed: \(result.orderReference)")
            print("Transaction: \(result.transactionReference)")
        case .canceled:
            print("User canceled")
        case .failed(let errorReason):
            print("Error: \(errorReason)")
        }
    }
}

Option B: Delegate Pattern

Implement BoltSimpleCheckoutDelegate for callback-based results. This approach mirrors the Android SDK’s delegate pattern.

import BoltInternal

class CheckoutManager: BoltSimpleCheckoutDelegate {

    func startCheckout(orderToken: String) {
        let config = BoltCheckoutConfig(orderToken: orderToken)
        BoltCheckout.shared.startCheckout(config: config, delegate: self)
    }

    // --- BoltSimpleCheckoutDelegate ---

    func onCheckoutSuccess(result: BoltCheckoutResult) {
        // result.reference            β€” transaction reference
        // result.status               β€” transaction status
        // result.amount               β€” BoltAmountView (minor units, currency, symbol)
        // result.cart?.orderReference  β€” Bolt order reference
        // result.merchantOrderNumber   β€” your merchant order number
    }

    func onCheckoutError(errorReason: String) {
        // Handle SDK, network, or validation errors
    }

    func onCheckoutCancel() {
        // User dismissed checkout β€” return to cart
    }
}

Option C: Present a View Controller Directly

For explicit control over presentation, use BoltCheckoutViewController:

let config = BoltCheckoutConfig(orderToken: "order-token-from-your-backend")
let checkoutVC = BoltCheckoutViewController(config: config, delegate: self)
present(checkoutVC, animated: true)

The view controller manages its own navigation and dismisses itself when checkout completes, cancels, or fails β€” your delegate receives the result.

Pre-Filling Customer Data

Use Bolt.Hints to pre-fill customer details and reduce friction during checkout:

Field Type Description
firstName String Customer’s first name.
lastName String Customer’s last name.
email String Customer’s email address.
phone String Customer’s phone number.
phoneCountryCode String? Phone country code (optional).
addressLine1 String Street address line 1.
addressLine2 String? Street address line 2 (optional).
city String City.
state String State or region.
zip String Postal code.
country String ISO 3166-1 alpha-2 country code (e.g. "US").
companyName String Optional company name.

UI Modes

Currently, the SDK supports WebView mode only. The checkout experience is rendered via a Bolt-hosted WebView. Native checkout mode is planned for a future release.

sdk ios swift checkout payments