Buying Bitcoin
The Breez SDK allows users to purchase Bitcoin through external providers. Two providers are currently supported: MoonPay and CashApp. The user is directed to a provider URL in their browser (or the CashApp app) to complete the purchase, and the funds are deposited directly into their wallet.
MoonPay
MoonPay uses on-chain Bitcoin deposit addresses to receive purchased funds. It supports fiat-to-Bitcoin purchases via credit card, Apple Pay, Google Pay, and other payment methods.
To initiate a Bitcoin purchase via MoonPay:
// Optionally, lock the purchase to a specific amount
let optional_locked_amount_sat = Some(100_000);
// Optionally, set a redirect URL for after the purchase is completed
let optional_redirect_url = Some("https://example.com/purchase-complete".to_string());
let request = BuyBitcoinRequest::Moonpay {
locked_amount_sat: optional_locked_amount_sat,
redirect_url: optional_redirect_url,
};
let response = sdk.buy_bitcoin(request).await?;
info!("Open this URL in a browser to complete the purchase:");
info!("{}", response.url);
// Optionally, lock the purchase to a specific amount
let optionalLockedAmountSat: UInt64 = 100_000
// Optionally, set a redirect URL for after the purchase is completed
let optionalRedirectUrl = "https://example.com/purchase-complete"
let request = BuyBitcoinRequest.moonpay(
lockedAmountSat: optionalLockedAmountSat,
redirectUrl: optionalRedirectUrl
)
let response = try await sdk.buyBitcoin(request: request)
print("Open this URL in a browser to complete the purchase:")
print("\(response.url)")
// Optionally, lock the purchase to a specific amount
val optionalLockedAmountSat: ULong = 100_000u
// Optionally, set a redirect URL for after the purchase is completed
val optionalRedirectUrl = "https://example.com/purchase-complete"
val request = BuyBitcoinRequest.Moonpay(
lockedAmountSat = optionalLockedAmountSat,
redirectUrl = optionalRedirectUrl
)
val response = sdk.buyBitcoin(request)
// Log.v("Breez", "Open this URL in a browser to complete the purchase:")
// Log.v("Breez", "${response.url}")
// Optionally, lock the purchase to a specific amount
var optionalLockedAmountSat = (ulong)100000;
// Optionally, set a redirect URL for after the purchase is completed
var optionalRedirectUrl = "https://example.com/purchase-complete";
var request = new BuyBitcoinRequest.Moonpay(
lockedAmountSat: optionalLockedAmountSat,
redirectUrl: optionalRedirectUrl
);
var response = await sdk.BuyBitcoin(request: request);
Console.WriteLine("Open this URL in a browser to complete the purchase:");
Console.WriteLine($"{response.url}");
// Optionally, lock the purchase to a specific amount
const optionalLockedAmountSat = 100_000
// Optionally, set a redirect URL for after the purchase is completed
const optionalRedirectUrl = 'https://example.com/purchase-complete'
const response = await sdk.buyBitcoin({
type: 'moonpay',
lockedAmountSat: optionalLockedAmountSat,
redirectUrl: optionalRedirectUrl
})
console.log('Open this URL in a browser to complete the purchase:')
console.log(response.url)
// Optionally, lock the purchase to a specific amount
const optionalLockedAmountSat = BigInt(100_000)
// Optionally, set a redirect URL for after the purchase is completed
const optionalRedirectUrl = 'https://example.com/purchase-complete'
const request = new BuyBitcoinRequest.Moonpay({
lockedAmountSat: optionalLockedAmountSat,
redirectUrl: optionalRedirectUrl
})
const response = await sdk.buyBitcoin(request)
console.log('Open this URL in a browser to complete the purchase:')
console.log(response.url)
// Optionally, lock the purchase to a specific amount
final optionalLockedAmountSat = BigInt.from(100000);
// Optionally, set a redirect URL for after the purchase is completed
final optionalRedirectUrl = "https://example.com/purchase-complete";
final request = BuyBitcoinRequest_Moonpay(
lockedAmountSat: optionalLockedAmountSat,
redirectUrl: optionalRedirectUrl);
final response = await sdk.buyBitcoin(request: request);
print("Open this URL in a browser to complete the purchase:");
print(response.url);
# Optionally, lock the purchase to a specific amount
optional_locked_amount_sat = 100_000
# Optionally, set a redirect URL for after the purchase is completed
optional_redirect_url = "https://example.com/purchase-complete"
try:
request = BuyBitcoinRequest.MOONPAY(
locked_amount_sat=optional_locked_amount_sat,
redirect_url=optional_redirect_url,
)
response = await sdk.buy_bitcoin(request=request)
logging.debug("Open this URL in a browser to complete the purchase:")
logging.debug(response.url)
except Exception as error:
logging.error(error)
raise
optionalLockedAmountSat := uint64(100_000)
optionalRedirectUrl := "https://example.com/purchase-complete"
request := breez_sdk_spark.BuyBitcoinRequestMoonpay{
LockedAmountSat: &optionalLockedAmountSat,
RedirectUrl: &optionalRedirectUrl,
}
response, err := sdk.BuyBitcoin(request)
if err != nil {
return err
}
log.Printf("Open this URL in a browser to complete the purchase:")
log.Printf("%v", response.Url)
The returned URL should be opened in a browser for the user to complete the purchase.
Developer note
MoonPay supports Apple Pay and Google Pay, but these payment methods will not work inside an iframe or standard web view. To ensure compatibility:- iOS: Open the URL using
SFSafariViewController. - Android: Open the URL using Chrome Custom Tabs.
- Desktop: Apple Pay requires Safari; Google Pay requires Chrome.
CashApp
CashApp uses Lightning (bolt11 invoices) to receive purchased funds. The SDK generates a Lightning invoice and returns a CashApp deep link (cash.app/launch/lightning/...) that opens the CashApp for the user to complete payment.
Developer note
CashApp is only available on mainnet. Attempting to use CashApp on testnet or regtest will return an error.To initiate a Bitcoin purchase via CashApp:
let request = BuyBitcoinRequest::CashApp {
amount_sats: None,
};
let response = sdk.buy_bitcoin(request).await?;
info!("Open this URL in Cash App to complete the purchase:");
info!("{}", response.url);
let request = BuyBitcoinRequest.cashApp(amountSats: nil)
let response = try await sdk.buyBitcoin(request: request)
print("Open this URL in Cash App to complete the purchase:")
print("\(response.url)")
val request = BuyBitcoinRequest.CashApp(amountSats = null)
val response = sdk.buyBitcoin(request)
// Log.v("Breez", "Open this URL in Cash App to complete the purchase:")
// Log.v("Breez", "${response.url}")
var request = new BuyBitcoinRequest.CashApp(
amountSats: null
);
var response = await sdk.BuyBitcoin(request: request);
Console.WriteLine("Open this URL in Cash App to complete the purchase:");
Console.WriteLine($"{response.url}");
const response = await sdk.buyBitcoin({
type: 'cashApp',
amountSats: undefined
})
console.log('Open this URL in Cash App to complete the purchase:')
console.log(response.url)
const request = new BuyBitcoinRequest.CashApp({
amountSats: undefined
})
const response = await sdk.buyBitcoin(request)
console.log('Open this URL in Cash App to complete the purchase:')
console.log(response.url)
final request = BuyBitcoinRequest_CashApp(
amountSats: null);
final response = await sdk.buyBitcoin(request: request);
print("Open this URL in Cash App to complete the purchase:");
print(response.url);
try:
request = BuyBitcoinRequest.CASH_APP(
amount_sats=None,
)
response = await sdk.buy_bitcoin(request=request)
logging.debug("Open this URL in Cash App to complete the purchase:")
logging.debug(response.url)
except Exception as error:
logging.error(error)
raise
request := breez_sdk_spark.BuyBitcoinRequestCashApp{
AmountSats: nil,
}
response, err := sdk.BuyBitcoin(request)
if err != nil {
return err
}
log.Printf("Open this URL in Cash App to complete the purchase:")
log.Printf("%v", response.Url)
The returned URL is a CashApp universal link (https://cash.app/launch/lightning/<bolt11>). On devices with CashApp installed it opens the app directly; otherwise it falls back to the CashApp website.
Developer note
The URL is obtained after an async SDK call, which means window.open() will be blocked by popup blockers on most mobile browsers and PWAs.
Recommended approach: pre-open a blank tab before the async call:
// 1. Open blank tab synchronously during the user gesture (click handler)
const newTab = window.open('', '_blank');
// 2. Async SDK call
const response = await sdk.buyBitcoin({ provider: 'cashApp' });
// 3. Navigate the pre-opened tab (or fall back to same-tab)
if (newTab) {
newTab.location.href = response.url;
} else {
// Mobile/PWA: popup was blocked, navigate in same tab
window.location.href = response.url;
}
Platform-specific guidance:
| Platform | Behavior | Recommendation |
|---|---|---|
| Desktop browsers | Pre-opened tab works reliably | Use the pattern above |
| Mobile browsers | window.open may be blocked after async | Falls back to location.href automatically |
| PWA (standalone) | window.open is almost always blocked | Same-tab redirect via location.href; opens system browser |
| iOS (native) | Use SFSafariViewController or UIApplication.open() | Universal link triggers CashApp if installed |
| Android (native) | Use Chrome Custom Tabs or Intent | Universal link triggers CashApp if installed |
CashApp availability: US and UK only (excluding New York State for Bitcoin/Lightning features). CashApp handles region restrictions on their end, so no client-side gating is needed.