Skip to content

CheckoutOptions

CheckoutOptions is the configuration object you pass when initiating a checkout. The shape is consistent across all platforms, with minor differences in typing and naming conventions.

Field Type (TS / Dart / Swift / Kotlin) Required Description
amount number / int / Int / Long Yes Amount in minor units (kobo, cents, paise). 500000 = ₦5,000. See amount handling.
currency string / String Yes ISO 4217 currency code (NGN, USD, INR, etc.)
customer CheckoutCustomer Yes Customer details. email is required.
reference string? / String? No Your unique transaction reference. Auto-generated as sanwo_<timestamp>_<random> if omitted.
metadata Record<string, unknown> / Map<String, dynamic> / [String: Any]? / Map<String, Any>? No Arbitrary key-value pairs passed through to the provider.
description string? / String? No Human-readable checkout description.
address CheckoutAddress? No Billing address. Web and React only.
onLoad () => void No Fires when the checkout UI loads. Web/React/React Native only.
onError (error) => void No Fires on error with { message, raw? }. Web/React/React Native only.
sanwoProviderOptions Record<string, unknown> No Provider-specific fields. Web/React/React Native only. On Flutter/iOS/Android, these are flattened as top-level fields.

Platform-specific top-level fields (Flutter / iOS / Android)

Section titled “Platform-specific top-level fields (Flutter / iOS / Android)”

On native SDKs, provider-specific options are passed as top-level fields on CheckoutOptions instead of being nested in sanwoProviderOptions:

Field Type Description
channels List<String> / [String]? Allowed payment channels (e.g. ["card", "bank_transfer"])
extra Map<String, Any>? Catch-all for any provider-specific field not explicitly typed
method String? Provider checkout method (e.g. "checkout", "newTransaction")

Sanwo always expects amounts in minor units (the smallest denomination of the currency):

Currency Minor unit Example
NGN kobo 500000 = ₦5,000.00
USD cents 1999 = $19.99
INR paise 100000 = ₹1,000.00

Providers that natively accept major units (Flutterwave, Monnify) have their amounts auto-converted by Sanwo. You always pass minor units regardless of provider.

Field Type Required Description
email string / String Yes Customer email address
firstName string? / String? No Customer first name
lastName string? / String? No Customer last name
name string? / String? No Full name (alternative to firstName + lastName)
phone string? / String? No Customer phone number
Field Type Required
line1 string Yes
line2 string? No
city string Yes
state string Yes
postalCode string Yes
country string Yes
interface CheckoutOptions {
amount: number;
currency: string;
customer: CheckoutCustomer;
reference?: string;
metadata?: Record<string, unknown>;
description?: string;
address?: CheckoutAddress;
onLoad?: () => void;
onError?: (error: { message: string; raw?: unknown }) => void;
sanwoProviderOptions?: Record<string, unknown>;
}
interface CheckoutCustomer {
email: string;
firstName?: string;
lastName?: string;
name?: string;
phone?: string;
}
interface CheckoutAddress {
line1: string;
line2?: string;
city: string;
state: string;
postalCode: string;
country: string;
}
class CheckoutOptions {
final int amount;
final String currency;
final CheckoutCustomer customer;
final String? reference;
final Map<String, dynamic>? metadata;
final String? description;
final List<String>? channels;
final Map<String, dynamic>? extra;
final String? method;
CheckoutOptions({
required this.amount,
required this.currency,
required this.customer,
this.reference,
this.metadata,
this.description,
this.channels,
this.extra,
this.method,
});
}
class CheckoutCustomer {
final String email;
final String? firstName;
final String? lastName;
final String? name;
final String? phone;
CheckoutCustomer({
required this.email,
this.firstName,
this.lastName,
this.name,
this.phone,
});
}
struct CheckoutOptions {
let amount: Int
let currency: String
let customer: CheckoutCustomer
var reference: String? = nil
var metadata: [String: Any]? = nil
var description: String? = nil
var channels: [String]? = nil
var extra: [String: Any]? = nil
var method: String? = nil
}
struct CheckoutCustomer {
let email: String
var firstName: String? = nil
var lastName: String? = nil
var name: String? = nil
var phone: String? = nil
}
data class CheckoutOptions(
val amount: Long,
val currency: String,
val customer: CheckoutCustomer,
val reference: String? = null,
val metadata: Map<String, Any>? = null,
val description: String? = null,
val channels: List<String>? = null,
val extra: Map<String, Any>? = null,
val method: String? = null,
)
data class CheckoutCustomer(
val email: String,
val firstName: String? = null,
val lastName: String? = null,
val name: String? = null,
val phone: String? = null,
)

The extra field (native SDKs) and sanwoProviderOptions (web/React/React Native) serve the same purpose: passing provider-specific fields that are not explicitly typed in CheckoutOptions.

Any key-value pair placed here is forwarded directly to the provider SDK. Refer to your provider’s documentation for available options.

// Flutter — pass Paystack split code via extra
CheckoutOptions(
amount: 500000,
currency: 'NGN',
customer: CheckoutCustomer(email: 'customer@example.com'),
extra: {'split_code': 'SPL_xxxxxxxx'},
)
// Web — same thing via sanwoProviderOptions
await sanwo({
amount: 500000,
currency: "NGN",
customer: { email: "customer@example.com" },
sanwoProviderOptions: {
split_code: "SPL_xxxxxxxx",
},
});