> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.coinflow.cash/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.coinflow.cash/_mcp/server.

# Swift SDK

## Overview

`CoinflowCardForm` is a SwiftUI SDK that embeds Coinflow's card tokenization form directly into iOS apps. The user enters their card inside your app, the SDK returns a payment token, and your backend charges the card via the standard Coinflow checkout API.

* **Package:** [`coinflow-swift`](https://github.com/coinflow-labs-us/coinflow-swift)
* **Distribution:** Swift Package Manager
* **Current version:** `0.2.0`

## Requirements

* iOS 15+
* Swift 5.9+
* Xcode 15+

## Installation

#### Xcode UI

In Xcode: **File → Add Package Dependencies…** and enter:

```
https://github.com/coinflow-labs-us/coinflow-swift
```

Select version **0.2.0** (or "Up to Next Major"), then add the `CoinflowCardForm` library product to your app target.

#### Package.swift

```swift
dependencies: [
    .package(
        url: "https://github.com/coinflow-labs-us/coinflow-swift",
        from: "0.2.0"
    )
],
targets: [
    .target(
        name: "YourApp",
        dependencies: [
            .product(name: "CoinflowCardForm", package: "coinflow-swift")
        ]
    )
]
```

## Integration

#### Add the card form view

Drop `CoinflowCardFormView` into your SwiftUI layout and pass a `CardFormCoordinator` you'll use to trigger tokenization.

```swift
import SwiftUI
import CoinflowCardForm

struct PaymentView: View {
    @StateObject private var coordinator = CardFormCoordinator()

    var body: some View {
        VStack {
            CoinflowCardFormView(
                variant: .cardForm,
                merchantId: "your-merchant-id",
                env: .sandbox,
                coordinator: coordinator
            )
            .frame(height: 52)

            Button("Pay") {
                Task { await tokenize() }
            }
        }
    }

    private func tokenize() async {
        do {
            let response = try await coordinator.tokenize()
            print("Token: \(response.token)")
        } catch {
            // surface error to user
        }
    }
}
```

> **Info**
>
> `your-merchant-id` is an **example placeholder**. Use your actual merchant ID from the merchant dashboard, or contact the Coinflow integrations team. Typically you'd inject it via a build setting or environment variable rather than hard-coding it.

#### Configure the environment

Switch `env` based on build configuration:

```swift
#if DEBUG
let env: CoinflowEnv = .sandbox
#else
let env: CoinflowEnv = .prod
#endif
```

* `.sandbox` — test cards, no real money
* `.prod` — live cards, real money

#### Charge the token server-side

`coordinator.tokenize()` returns a `TokenizeResponse`:

* `token: String` — payment token to send to your backend
* `expMonth: String?`, `expYear: String?` — populated only for variants that collect expiry

Send the token to your server and call Coinflow's checkout API to charge it. See the [Checkout API reference](/api-reference/api-reference/checkout/card-checkout) for the full request shape.

## Variants

```swift
CoinflowCardFormView(variant: .cardForm, ...)         // full card entry
CoinflowCardFormView(variant: .cardNumberForm, ...)   // number + expiry only
CoinflowCardFormView(variant: .cvvForm, token: "...", ...) // CVV only for saved card
```

| Variant           | Captures            | Use case                                   |
| ----------------- | ------------------- | ------------------------------------------ |
| `.cardForm`       | Number, expiry, CVV | Standard one-shot capture                  |
| `.cardNumberForm` | Number + expiry     | First step of a two-step flow              |
| `.cvvForm`        | CVV only            | Re-collecting CVV for a card-on-file token |

## Theming

`MerchantTheme` styles the rendered form. All fields optional.

```swift
let theme = MerchantTheme(
    primary: "#165DFB",
    background: "#ffffff",
    textColor: "#05092E",
    ctaColor: "#165DFB",
    font: "Red Hat Display",
    style: .rounded
)

CoinflowCardFormView(theme: theme, /* ... */)
```

#### All theme fields

| Field                                                              | Purpose                                             |
| ------------------------------------------------------------------ | --------------------------------------------------- |
| `primary`, `ctaColor`                                              | Accent / action colors (hex strings)                |
| `background`, `backgroundAccent`, `backgroundAccent2`              | Form background tones                               |
| `textColor`, `textColorAccent`, `textColorAction`                  | Input and label text colors                         |
| `font`, `fontSize`, `fontWeight`                                   | Typography. `font` must be available on the device. |
| `style`                                                            | Input shape: `.rounded`, `.sharp`, `.pill`          |
| `cardNumberPlaceholder`, `cvvPlaceholder`, `expirationPlaceholder` | Override input placeholder text                     |
| `showCardIcon`                                                     | Toggle the card brand icon (Visa/Mastercard/Amex)   |

## Dynamic height

The hosted form reflows responsively — at narrow widths the inputs wrap to multiple rows. To keep your SwiftUI container fitted, observe `coordinator.contentHeight` and bind it to your frame:

```swift
CoinflowCardFormView(
    merchantId: "your-merchant-id",
    coordinator: coordinator
)
.frame(height: coordinator.contentHeight ?? 52)
```

`contentHeight` is `@Published` on `CardFormCoordinator` and updates whenever the form reflows. Without this wiring the form may be clipped if it wraps.

## Resources

* **Source:** [github.com/coinflow-labs-us/coinflow-swift](https://github.com/coinflow-labs-us/coinflow-swift)
* **License:** Apache 2.0
* **Checkout API:** [Card Checkout endpoint](/api-reference/api-reference/checkout/card-checkout)