Receiving Payments

With the Breez SDK you aren't required to open a channel and set up your inbound liquidity.

Once the SDK is initialized, you can directly begin receiving payments. The receive process takes two steps:

  1. Preparing the Payment
  2. Receiving the Payment

Developer note

Consider implementing the Notification Plugin when using the Breez SDK in a mobile application. By registering a webhook the application can receive notifications to process the payment in the background.

Preparing Payments

During the prepare step, the SDK ensures that the inputs are valid with respect to the specified payment method, and also returns the relative fees related to the payment so they can be confirmed.

The SDK currently supports three methods of receiving: Lightning, Bitcoin and Liquid:

Lightning

When receiving via Lightning, we generate an invoice to be paid. Note that the payment may fallback to a direct Liquid payment (if the payer's client supports this).

Note: The amount field is currently mandatory when paying via Lightning.

Rust
// Fetch the Receive lightning limits
let current_limits = sdk.fetch_lightning_limits().await?;
info!("Minimum amount: {} sats", current_limits.receive.min_sat);
info!("Maximum amount: {} sats", current_limits.receive.max_sat);

// Set the invoice amount you wish the payer to send, which should be within the above limits
let prepare_response = sdk
    .prepare_receive_payment(&PrepareReceiveRequest {
        payer_amount_sat: Some(5_000),
        payment_method: PaymentMethod::Lightning,
    })
    .await?;

// If the fees are acceptable, continue to create the Receive Payment
let receive_fees_sat = prepare_response.fees_sat;
info!("Fees: {} sats", receive_fees_sat);
Swift
// Fetch the Receive lightning limits
let currentLimits = try? sdk.fetchLightningLimits()
print("Minimum amount: {} sats", currentLimits?.receive.minSat ?? 0);
print("Maximum amount: {} sats", currentLimits?.receive.maxSat ?? 0);

// Set the invoice amount you wish the payer to send, which should be within the above limits
let prepareResponse = try? sdk
    .prepareReceivePayment(req: PrepareReceiveRequest(
        payerAmountSat: 5_000,
        paymentMethod: PaymentMethod.lightning
    ));

// If the fees are acceptable, continue to create the Receive Payment
let receiveFeesSat = prepareResponse!.feesSat;
print("Fees: {} sats", receiveFeesSat);
Kotlin
try {
    // Fetch the lightning Receive limits
    val currentLimits = sdk.fetchLightningLimits()
    // Log.v("Breez", "Minimum amount allowed to deposit in sats: ${currentLimits.receive.minSat}")
    // Log.v("Breez", "Maximum amount allowed to deposit in sats: ${currentLimits.receive.maxSat}")

    // Set the invoice amount you wish the payer to send, which should be within the above limits
    val prepareRequest = PrepareReceiveRequest(5_000.toULong(), PaymentMethod.LIGHTNING)
    val prepareResponse = sdk.prepareReceivePayment(prepareRequest)

    // If the fees are acceptable, continue to create the Receive Payment
    val receiveFeesSat = prepareResponse.feesSat;
    // Log.v("Breez", "Fees: ${receiveFeesSat} sats")
} catch (e: Exception) {
    // handle error
}
React Native
// Fetch the Receive lightning limits
const currentLimits = await fetchLightningLimits()
console.log(`Minimum amount, in sats: ${currentLimits.receive.minSat}`)
console.log(`Maximum amount, in sats: ${currentLimits.receive.maxSat}`)

// Set the amount you wish the payer to send via lightning, which should be within the above limits
const prepareResponse = await prepareReceivePayment({
  payerAmountSat: 5_000,
  paymentMethod: PaymentMethod.LIGHTNING
})

// If the fees are acceptable, continue to create the Receive Payment
const receiveFeesSat = prepareResponse.feesSat
console.log(`Fees: ${receiveFeesSat} sats`)
Dart
// Fetch the Receive lightning limits
LightningPaymentLimitsResponse currentLightningLimits =
    await breezSDKLiquid.instance!.fetchLightningLimits();
print("Minimum amount: ${currentLightningLimits.receive.minSat} sats");
print("Maximum amount: ${currentLightningLimits.receive.maxSat} sats");

// Create an invoice and set the amount you wish the payer to send
PrepareReceiveResponse prepareResponse =
    await breezSDKLiquid.instance!.prepareReceivePayment(
  req: PrepareReceiveRequest(
    payerAmountSat: 5000 as BigInt,
    paymentMethod: PaymentMethod.lightning,
  ),
);

// If the fees are acceptable, continue to create the Receive Payment
BigInt receiveFeesSat = prepareResponse.feesSat;
print("Fees: ${receiveFeesSat} sats");
Python
try:
    # Fetch the lightning Receive limits
    current_limits = sdk.fetch_lightning_limits()
    logging.debug("Minimum amount allowed to deposit in sats ", current_limits.receive.min_sat)
    logging.debug("Maximum amount allowed to deposit in sats ", current_limits.receive.max_sat)

    # Set the invoice amount you wish the payer to send, which should be within the above limits
    prepare_request = PrepareReceiveRequest(5_000, PaymentMethod.LIGHTNING)
    prepare_response = sdk.prepare_receive_payment(prepare_request)

    # If the fees are acceptable, continue to create the Receive Payment
    receive_fees_sat = prepare_response.fees_sat
    logging.debug("Fees: ", receive_fees_sat, " sats")
    return prepare_response
except Exception as error:
    logging.error(error)
    raise
Go
// Fetch the lightning Receive limits
if currentLimits, err := sdk.FetchLightningLimits(); err == nil {
    log.Printf("Minimum amount, in sats: %v", currentLimits.Receive.MinSat)
    log.Printf("Maximum amount, in sats: %v", currentLimits.Receive.MaxSat)
}

// Set the invoice amount you wish the payer to send, which should be within the above limits
optionalPayerAmountSat := uint64(5_000)
prepareRequest := breez_sdk_liquid.PrepareReceiveRequest{
    PayerAmountSat: &optionalPayerAmountSat,
    PaymentMethod:  breez_sdk_liquid.PaymentMethodLightning,
}
if prepareResponse, err := sdk.PrepareReceivePayment(prepareRequest); err == nil {
    // If the fees are acceptable, continue to create the Receive Payment
    receiveFeesSat := prepareResponse.FeesSat
    log.Printf("Fees: %v sats", receiveFeesSat)
}
C#
try
{
    // Fetch the lightning Receive limits
    var currentLimits = sdk.FetchLightningLimits();
    Console.WriteLine($"Minimum amount allowed to deposit in sats: {currentLimits.receive.minSat}");
    Console.WriteLine($"Maximum amount allowed to deposit in sats: {currentLimits.receive.maxSat}");

    // Set the invoice amount you wish the payer to send, which should be within the above limits
    var prepareRequest = new PrepareReceiveRequest(5000, PaymentMethod.Lightning);
    var prepareResponse = sdk.PrepareReceivePayment(prepareRequest);

    // If the fees are acceptable, continue to create the Receive Payment
    var receiveFeesSat = prepareResponse.feesSat;
    Console.WriteLine($"Fees: {receiveFeesSat} sats");
}
catch (Exception)
{
    // Handle error
}

Bitcoin

When receiving via Bitcoin, we generate a Bitcoin BIP21 URI to be paid.

Note: The amount field is currently mandatory when paying via Bitcoin.

Rust
// Fetch the Receive onchain limits
let current_limits = sdk.fetch_onchain_limits().await?;
info!("Minimum amount: {} sats", current_limits.receive.min_sat);
info!("Maximum amount: {} sats", current_limits.receive.max_sat);

// Set the onchain amount you wish the payer to send, which should be within the above limits
let prepare_response = sdk
    .prepare_receive_payment(&PrepareReceiveRequest {
        payer_amount_sat: Some(5_000),
        payment_method: PaymentMethod::BitcoinAddress,
    })
    .await?;

// If the fees are acceptable, continue to create the Receive Payment
let receive_fees_sat = prepare_response.fees_sat;
info!("Fees: {} sats", receive_fees_sat);
Swift
// Fetch the Receive onchain limits
let currentLimits = try? sdk.fetchOnchainLimits()
print("Minimum amount: {} sats", currentLimits?.receive.minSat ?? 0);
print("Maximum amount: {} sats", currentLimits?.receive.maxSat ?? 0);

// Set the onchain amount you wish the payer to send, which should be within the above limits
let prepareResponse = try? sdk
    .prepareReceivePayment(req: PrepareReceiveRequest(
        payerAmountSat: 5_000,
        paymentMethod: PaymentMethod.bitcoinAddress
    ));

// If the fees are acceptable, continue to create the Receive Payment
let receiveFeesSat = prepareResponse!.feesSat;
print("Fees: {} sats", receiveFeesSat);
Kotlin
try {
    // Fetch the onchain Receive limits
    val currentLimits = sdk.fetchOnchainLimits()
    // Log.v("Breez", "Minimum amount allowed to deposit in sats: ${currentLimits.receive.minSat}")
    // Log.v("Breez", "Maximum amount allowed to deposit in sats: ${currentLimits.receive.maxSat}")

    // Set the onchain amount you wish the payer to send, which should be within the above limits
    val prepareRequest = PrepareReceiveRequest(5_000.toULong(), PaymentMethod.BITCOIN_ADDRESS)
    val prepareResponse = sdk.prepareReceivePayment(prepareRequest)

    // If the fees are acceptable, continue to create the Receive Payment
    val receiveFeesSat = prepareResponse.feesSat;
    // Log.v("Breez", "Fees: ${receiveFeesSat} sats")
} catch (e: Exception) {
    // handle error
}
React Native
// Fetch the Onchain lightning limits
const currentLimits = await fetchOnchainLimits()
console.log(`Minimum amount, in sats: ${currentLimits.receive.minSat}`)
console.log(`Maximum amount, in sats: ${currentLimits.receive.maxSat}`)

// Set the onchain amount you wish the payer to send, which should be within the above limits
const prepareResponse = await prepareReceivePayment({
  payerAmountSat: 5_000,
  paymentMethod: PaymentMethod.BITCOIN_ADDRESS
})

// If the fees are acceptable, continue to create the Receive Payment
const receiveFeesSat = prepareResponse.feesSat
console.log(`Fees: ${receiveFeesSat} sats`)
Dart
// Fetch the Receive onchain limits
OnchainPaymentLimitsResponse currentOnchainLimits =
    await breezSDKLiquid.instance!.fetchOnchainLimits();
print("Minimum amount: ${currentOnchainLimits.receive.minSat} sats");
print("Maximum amount: ${currentOnchainLimits.receive.maxSat} sats");

// Or create a cross-chain transfer (Liquid to Bitcoin) via chain swap
PrepareReceiveResponse prepareResponse =
    await breezSDKLiquid.instance!.prepareReceivePayment(
  req: PrepareReceiveRequest(
    payerAmountSat: 5000 as BigInt,
    paymentMethod: PaymentMethod.bitcoinAddress,
  ),
);

// If the fees are acceptable, continue to create the Receive Payment
BigInt receiveFeesSat = prepareResponse.feesSat;
print("Fees: ${receiveFeesSat} sats");
Python
try:
    # Fetch the onchain Receive limits
    current_limits = sdk.fetch_onchain_limits()
    logging.debug("Minimum amount allowed to deposit in sats ", current_limits.receive.min_sat)
    logging.debug("Maximum amount allowed to deposit in sats ", current_limits.receive.max_sat)

    # Set the onchain amount you wish the payer to send, which should be within the above limits
    prepare_request = PrepareReceiveRequest(5_000, PaymentMethod.BITCOIN_ADDRESS)
    prepare_response = sdk.prepare_receive_payment(prepare_request)

    # If the fees are acceptable, continue to create the Receive Payment
    receive_fees_sat = prepare_response.fees_sat
    logging.debug("Fees: ", receive_fees_sat, " sats")
    return prepare_response
except Exception as error:
    logging.error(error)
    raise
Go
// Fetch the onchain Receive limits
if currentLimits, err := sdk.FetchOnchainLimits(); err == nil {
    log.Printf("Minimum amount, in sats: %v", currentLimits.Receive.MinSat)
    log.Printf("Maximum amount, in sats: %v", currentLimits.Receive.MaxSat)
}

// Set the onchain amount you wish the payer to send, which should be within the above limits
optionalPayerAmountSat := uint64(5_000)
prepareRequest := breez_sdk_liquid.PrepareReceiveRequest{
    PayerAmountSat: &optionalPayerAmountSat,
    PaymentMethod:  breez_sdk_liquid.PaymentMethodBitcoinAddress,
}
if prepareResponse, err := sdk.PrepareReceivePayment(prepareRequest); err == nil {
    // If the fees are acceptable, continue to create the Receive Payment
    receiveFeesSat := prepareResponse.FeesSat
    log.Printf("Fees: %v sats", receiveFeesSat)
}
C#
try
{
    // Fetch the onchain Receive limits
    var currentLimits = sdk.FetchOnchainLimits();
    Console.WriteLine($"Minimum amount allowed to deposit in sats: {currentLimits.receive.minSat}");
    Console.WriteLine($"Maximum amount allowed to deposit in sats: {currentLimits.receive.maxSat}");

    // Set the onchain amount you wish the payer to send, which should be within the above limits
    var prepareRequest = new PrepareReceiveRequest(5000, PaymentMethod.BitcoinAddress);
    var prepareResponse = sdk.PrepareReceivePayment(prepareRequest);

    // If the fees are acceptable, continue to create the Receive Payment
    var receiveFeesSat = prepareResponse.feesSat;
    Console.WriteLine($"Fees: {receiveFeesSat} sats");
}
catch (Exception)
{
    // Handle error
}

Developer note

The above checks include validating against maximum and minimum limits. Your application's users must be informed of these limits because if the amount transferred to the swap address falls outside this valid range, the funds will not be successfully received via the normal swap flow. In such cases, a manual refund will be necessary. For further instructions on how to execute a manual refund, see the section on refunding payments.

Liquid

When receiving via Liquid, we can either generate an address to receive to, or a BIP21 URI with information regarding the payment (currently only the amount and message).

To generate a BIP21 address, all you have to do is specify a payer amount.

Rust
// Create a Liquid BIP21 URI/address to receive a payment to.
// There are no limits, but the payer amount should be greater than broadcast fees when specified
let prepare_response = sdk
    .prepare_receive_payment(&PrepareReceiveRequest {
        payer_amount_sat: Some(5_000), // Not specifying the amount will create a plain Liquid address instead
        payment_method: PaymentMethod::LiquidAddress,
    })
    .await?;

// If the fees are acceptable, continue to create the Receive Payment
let receive_fees_sat = prepare_response.fees_sat;
info!("Fees: {} sats", receive_fees_sat);
Swift
// Create a Liquid BIP21 URI/address to receive a payment to.
// There are no limits, but the payer amount should be greater than broadcast fees when specified
let prepareResponse = try? sdk
    .prepareReceivePayment(req: PrepareReceiveRequest(
        payerAmountSat: 5_000, // Not specifying the amount will create a plain Liquid address instead
        paymentMethod: PaymentMethod.liquidAddress
    ))

// If the fees are acceptable, continue to create the Receive Payment
let receiveFeesSat = prepareResponse!.feesSat;
print("Fees: {} sats", receiveFeesSat);
Kotlin
try {
    // Create a Liquid BIP21 URI/address to receive a payment to.
    // There are no limits, but the payer amount should be greater than broadcast fees when specified
    // Note: Not setting the amount will generate a plain Liquid address
    val prepareRequest = PrepareReceiveRequest(5_000.toULong(), PaymentMethod.LIQUID_ADDRESS)
    val prepareResponse = sdk.prepareReceivePayment(prepareRequest)

    // If the fees are acceptable, continue to create the Receive Payment
    val receiveFeesSat = prepareResponse.feesSat;
    // Log.v("Breez", "Fees: ${receiveFeesSat} sats")
} catch (e: Exception) {
    // handle error
}
React Native

// Create a Liquid BIP21 URI/address to receive a payment to.
// There are no limits, but the payer amount should be greater than broadcast fees when specified
const prepareResponse = await prepareReceivePayment({
  payerAmountSat: 5_000, // Not specifying the amount will create a plain Liquid address instead
  paymentMethod: PaymentMethod.LIQUID_ADDRESS
})

// If the fees are acceptable, continue to create the Receive Payment
const receiveFeesSat = prepareResponse.feesSat
console.log(`Fees: ${receiveFeesSat} sats`)
Dart
// Create a Liquid BIP21 URI/address to receive a payment to.
// There are no limits, but the payer amount should be greater than broadcast fees when specified
PrepareReceiveResponse prepareResponse =
    await breezSDKLiquid.instance!.prepareReceivePayment(
  req: PrepareReceiveRequest(
    payerAmountSat: 5000
        as BigInt, // Not specifying the amount will create a plain Liquid address instead
    paymentMethod: PaymentMethod.liquidAddress,
  ),
);

// If the fees are acceptable, continue to create the Receive Payment
BigInt receiveFeesSat = prepareResponse.feesSat;
print("Fees: ${receiveFeesSat} sats");
Python
try:
    # Create a Liquid BIP21 URI/address to receive a payment to.
    # There are no limits, but the payer amount should be greater than broadcast fees when specified
    # Note: Not setting the amount will generate a plain Liquid address
    prepare_request = PrepareReceiveRequest(5_000, PaymentMethod.LIQUID_ADDRESS)
    prepare_response = sdk.prepare_receive_payment(prepare_request)

    # If the fees are acceptable, continue to create the Receive Payment
    receive_fees_sat = prepare_response.fees_sat
    logging.debug("Fees: ", receive_fees_sat, " sats")
    return prepare_response
except Exception as error:
    logging.error(error)
    raise
Go
// Create a Liquid BIP21 URI/address to receive a payment to.
// There are no limits, but the payer amount should be greater than broadcast fees when specified
// Note: Not setting the amount will generate a plain Liquid address
optionalPayerAmountSat := uint64(5_000)
prepareRequest := breez_sdk_liquid.PrepareReceiveRequest{
    PayerAmountSat: &optionalPayerAmountSat,
    PaymentMethod:  breez_sdk_liquid.PaymentMethodLiquidAddress,
}
if prepareResponse, err := sdk.PrepareReceivePayment(prepareRequest); err == nil {
    // If the fees are acceptable, continue to create the Receive Payment
    receiveFeesSat := prepareResponse.FeesSat
    log.Printf("Fees: %v sats", receiveFeesSat)
}
C#
try
{
    // Create a Liquid BIP21 URI/address to receive a payment to.
    // There are no limits, but the payer amount should be greater than broadcast fees when specified
    // Note: Not setting the amount will generate a plain Liquid address
    var prepareRequest = new PrepareReceiveRequest(5000, PaymentMethod.LiquidAddress);
    var prepareResponse = sdk.PrepareReceivePayment(prepareRequest);

    // If the fees are acceptable, continue to create the Receive Payment
    var receiveFeesSat = prepareResponse.feesSat;
    Console.WriteLine($"Fees: {receiveFeesSat} sats");
}
catch (Exception)
{
    // Handle error
}

Receiving Payments

Once the payment has been prepared, all you have to do is pass the prepare response as an argument to the receive method, optionally specifying a description.

Note: The description field will be used differently, depending on the payment method:

  • For Lightning payments, it will be encoded in the invoice
  • For Bitcoin/Liquid BIP21 payments, it will be encoded in the URI as the message field.
  • For plain Liquid payments, the description has no effect.
Rust
let optional_description = Some("<description>".to_string());
let res = sdk
    .receive_payment(&ReceivePaymentRequest {
        prepare_response,
        description: optional_description,
        use_description_hash: None,
    })
    .await?;

let destination = res.destination;
Swift
let optionalDescription = "<description>"
let res = try? sdk.receivePayment(req: ReceivePaymentRequest(
        prepareResponse: prepareResponse,
        description: optionalDescription
    ))

let destination: String = res!.destination;
print("Destination: {}", destination);
Kotlin
try {
    val optionalDescription = "<description>";
    val req = ReceivePaymentRequest(prepareResponse, optionalDescription)
    val res = sdk.receivePayment(req)
    val destination = res.destination;
} catch (e: Exception) {
    // handle error
}
React Native
const optionalDescription = '<description>'
const res = await receivePayment({
  prepareResponse,
  description: optionalDescription
})

const destination = res.destination
Dart
String optionalDescription = "<description>";
ReceivePaymentResponse res = await breezSDKLiquid.instance!.receivePayment(
  req: ReceivePaymentRequest(
    description: optionalDescription,
    prepareResponse: prepareResponse,
  ),
);

String destination = res.destination;
Python
try:
    optional_description = "<description>"
    req = ReceivePaymentRequest(prepare_response, optional_description)
    res = sdk.receive_payment(req)
    destination = res.destination
except Exception as error:
    logging.error(error)
    raise
Go
optionalDescription := "<description>"
req := breez_sdk_liquid.ReceivePaymentRequest{
    PrepareResponse: prepareResponse,
    Description:     &optionalDescription,
}
if res, err := sdk.ReceivePayment(req); err == nil {
    // If the fees are acceptable, continue to create the Receive Payment
    destination := res.Destination
    log.Printf("Destination: %v", destination)
}
C#
try
{
    var optionalDescription = "<description>";
    var req = new ReceivePaymentRequest(prepareResponse, optionalDescription);
    var res = sdk.ReceivePayment(req);
    var destination = res.destination;
}
catch (Exception)
{
    // Handle error
}