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:
ApproachBest For
Completion handlerSimplest: works from anywhere, including SwiftUI.
Delegate patternCallback-based, mirrors the Android SDK.
View controllerFull 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.
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>
EnvironmentEndpoint
Sandboxhttps://api-sandbox.bolt.com/v1/merchant/orders
Productionhttps://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:
FieldTypeDescription
firstNameStringCustomer’s first name.
lastNameStringCustomer’s last name.
emailStringCustomer’s email address.
phoneStringCustomer’s phone number.
phoneCountryCodeString?Phone country code (optional).
addressLine1StringStreet address line 1.
addressLine2String?Street address line 2 (optional).
cityStringCity.
stateStringState or region.
zipStringPostal code.
countryStringISO 3166-1 alpha-2 country code (e.g. "US").
companyNameStringOptional 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.