<!-- Source: https://blnkfinance.com/blog/building-wallet-with-stripe-and-blnk-finance -->

[Blog](https://blnkfinance.com/blog) [Build](https://blnkfinance.com/blog/build)

5 min read

# How to Build a Wallet with Stripe & Blnk Finance

Take a payment with Stripe and record it on Blnk Core. A wallet that stays in sync when the card charge succeeds or fails.

* * *

![How to build a wallet with Stripe & Blnk Finance](https://cdn.sanity.io/images/06pses5q/production/c7028b86f28535f9eee982ec9f12073ce6c7118e-3840x2160.webp?w=1600&fit=max&auto=format)

Wallets are one of the most popular fintech products in the world today. It serves a wide range of use cases from traditional fintech apps like CashApp to other app categories like eCommerce (Shopify), travel (Booking.com), gaming (Call of Duty Mobile), etc.

To use a wallet, you typically add money from a bank account or credit card before making transactions in the app.

In this guide, we’ll show you how to build a wallet product step-by-step using Blnk Finance, with Stripe as your payment provider, to create a smooth and reliable experience.

## The user experience

Let’s create a wallet feature for an eCommerce app using AcmePay, a payment method that offers 5% [cashback](https://blnkfinance.com/blog/how-to-build-a-reward-system-for-an-e-commerce-platform-using-blnk) on checkout purchases. When users sign up, an AcmePay wallet is automatically created for them. Here’s how it works:

1.  Users fund their AcmePay wallet via bank transfer or credit/debit card.
2.  At checkout, users choose AcmePay as their payment option.
3.  The purchase amount is deducted from their AcmePay wallet balance.
4.  Users receive 5% cashback, credited directly to their AcmePay wallet.

To build this, you need the following:

1.  A payment provider to handle online payments. We'll use Stripe for this guide
2.  A [double-entry ledger](https://blnkfinance.com) to accurately track transactions and wallet balances.

## [Money movement map](https://blnkfinance.com/glossary/money-movement-map)

First, start by determining how money moves in our system for each transaction — wallet funding, making a purchase, and receiving cashback. This provides a bird's eye view of the flow of funds within AcmePay.

![](https://cdn.sanity.io/images/06pses5q/production/022fdd9a4ea387445c7fbacb94b38bc2fb547a67-2224x996.png?w=1920&fit=max&auto=format)

Simplified money movement map for AcmePay

Next, we set up our ledger architecture. Our ledger is how we know how much each user has in our system because Stripe will only show the total amount deposited across all users in our system.

![](https://cdn.sanity.io/images/06pses5q/production/04115851a202f39f6f5f33c55573c351128545fa-2224x996.png?w=1920&fit=max&auto=format)

Ledgers helps you keep an accurate record of how much belongs to each user in your application.

## 1\. Implementing our wallet

Now that we've defined our user experience and money movement map, let's dive into building our wallet. To follow this guide, you need to have a live instance of [Blnk Core](https://blnkfinance.com/products/core) and a Stripe account.

1.  1
    
    Set up your users ledger
    
    You need to create a ledger to keep track of all balances created for users in AcmePay. This is the only ledger we need to create for this guide.
    
    To set up our Users Ledger, make a request to the [Create Ledger](https://docs.blnkfinance.com/reference/create-ledger) endpoint as follows:
    
    <!-- TypeScript -->
    ```
    const response = await blnk.Ledgers.create({
      name: 'Users Ledger',
      meta_data: {
        organization: 'AcmePay',
        description: 'For all users wallet created & managed by Acme.',
      },
    });
    ```
    
    <!-- Go -->
    ```
    ledger, resp, err := client.Ledger.Create(blnkgo.CreateLedgerRequest{
      Name: "Users Ledger",
      MetaData: blnkgo.MetaData{
        "organization": "AcmePay",
        "description": "For all users wallet created & managed by Acme.",
      },
    })
    ```
    
    <!-- Python -->
    ```
    response = blnk.ledgers.create({
      "name": "Users Ledger",
      "meta_data": {
        "organization": "AcmePay",
        "description": "For all users wallet created & managed by Acme.",
      },
    })
    ```
    
    <!-- Java -->
    ```
    ApiResponse<JsonNode> response = blnk.ledgers().create(
      CreateLedger.create()
        .name("Users Ledger")
        .metaData(Map.of("organization", "AcmePay", "description", "For all users wallet created & managed by Acme.")));
    ```
    
2.  2
    
    Creating the user wallet
    
    To create the user wallet, we'll do the following:
    
    1.  Create a customer on Stripe, and retrieve the customer id.
    2.  Create an identity on Blnk and add the Stripe customer id to its metadata.
    3.  Create a balance on Blnk using the identity id from Blnk.
    
3.  3
    
    Create a customer on Stripe
    
    This helps us identify the user when they fund their wallet via Stripe checkout.
    
    ```
    const stripe = require('stripe')('sk_test_51Q8vs7Rr ... Eh00okDxEs1L');
    
    const customer = await stripe.customers.create({
      name: "Charles Xavier",
      email: "charlesxavier@example.com",
      metadata: { "userId": "123" }
    });
    ```
    
4.  4
    
    Create an identity on Blnk
    
    This helps us identify the user within our ledger. Once linked to a balance, all transactions performed by the balance can be traced to a user.
    
    <!-- TypeScript -->
    ```
    async function createIdentity(stripeCreatedId: string, user: {firstName: string; lastName: string; email: string}) {
      const response = await blnk.Identities.create({
        first_name: user.firstName,
        last_name: user.lastName,
        email: user.email,
        meta_data: {
          stripe_id: stripeCreatedId,
        },
      });
      console.log('Customer Identity created:', response.data.identity_id);
      return response.data.identity_id;
    }
    ```
    
    <!-- Go -->
    ```
    func createIdentity(stripeCreatedID string, user User) {
      identity, resp, err := client.Identity.Create(blnkgo.Identity{
        FirstName: "User.firstName",
        LastName: "User.lastName",
        Email: "User.email",
        MetaData: blnkgo.MetaData{
          "stripe_id": "stripe_created_id",
        },
      })
      fmt.Println("Customer Identity created:", identity.IdentityID)
      return identity.IdentityID, nil
    }
    ```
    
    <!-- Python -->
    ```
    def create_identity(stripe_created_id, user):
      response = blnk.identity.create({
        "first_name": user["first_name"],
        "last_name": user["last_name"],
        "email": user["email"],
        "meta_data": {
          "stripe_id": stripe_created_id,
        },
      })
      print("Customer Identity created:", response.data["identity_id"])
      return response.data["identity_id"]
    ```
    
    <!-- Java -->
    ```
    ApiResponse<JsonNode> createIdentity(String stripeCreatedId, User user) {
      ApiResponse<JsonNode> response = blnk.identity().create(
        CreateIdentity.create()
          .firstName("User.firstName")
          .lastName("User.lastName")
          .email("User.email")
          .metaData(Map.of("stripe_id", "stripe_created_id")));
        System.out.println("Customer Identity created: " + response.data().get("identity_id").asText());
        return response.data().get("identity_id").asText();
      }
    ```
    
5.  5
    
    Create a balance for the user
    
    This is how we store cash balances and record transactions that the user makes within our application.
    
    <!-- TypeScript -->
    ```
    async function createMainWallet(ledgerId: string, identityId: string, currency: string) {
      const response = await blnk.LedgerBalances.create({
        ledger_id: ledgerId,
        identity_id: identityId,
        currency,
        meta_data: {
          wallet_type: 'main',
        },
      });
      console.log('Main Wallet created:', response.data.balance_id);
      return response.data.balance_id;
    }
    ```
    
    <!-- Go -->
    ```
    func createMainWallet(ledgerID, identityID, currency string) {
      balance, resp, err := client.LedgerBalance.Create(blnkgo.CreateLedgerBalanceRequest{
        LedgerID: "ledgerId",
        IdentityID: "identityId",
        Currency: "currency",
        MetaData: blnkgo.MetaData{
          "wallet_type": "main",
        },
      })
      fmt.Println("Main Wallet created:", balance.BalanceID)
      return balance.BalanceID, nil
    }
    ```
    
    <!-- Python -->
    ```
    def create_main_wallet(ledger_id, identity_id, currency):
      response = blnk.ledger_balances.create({
        "ledger_id": ledger_id,
        "identity_id": identity_id,
        "currency": currency,
        "meta_data": {
          "wallet_type": "main",
        },
      })
      print("Main Wallet created:", response.data["balance_id"])
      return response.data["balance_id"]
    ```
    
    <!-- Java -->
    ```
    ApiResponse<JsonNode> createMainWallet(String ledgerId, String identityId, String currency) {
      ApiResponse<JsonNode> response = blnk.ledgerBalances().create(
        CreateLedgerBalance.create()
          .ledgerId("ledgerId")
          .identityId("identityId")
          .currency("currency")
          .metaData(Map.of("wallet_type", "main")));
        System.out.println("Main Wallet created: " + response.data().get("balance_id").asText());
        return response.data().get("balance_id").asText();
      }
    ```
    

## 2\. Wallet funding

To handle wallet top-up, we will:

1.  Get the amount from the customer via the app.
2.  Initiate a Stripe checkout session with customer's email or id and generate a unique reference id.
3.  Listen for webhooks to know when the payment is created or completed.
4.  Create a transaction in the ledger to update your user's balance. Use the same reference id.

1.  1
    
    Create a new Stripe checkout payment
    
    Start by creating an [inflight transaction](https://docs.blnkfinance.com/transactions/inflight/creating-inflight) to initiate the payment in your ledger. This creates the transaction but doesn't apply it to the balances until payment is confirmed by Stripe.
    
    Make sure to generate a unique reference id for each new transaction in your app.
    
    <!-- TypeScript -->
    ```
    async function walletFunding(reference, amount, currency, customerBalanceId, stripeSessionId, paymentMethod) {
      const response = await blnk.Transactions.create({
        amount,
        precision: 100,
        currency,
        reference,
        source: '@Stripe',
        destination: customerBalanceId,
        allow_overdraft: true,
        inflight: true,
        description: 'Topup via Stripe',
        meta_data: {
          payment_method: paymentMethod,
          stripe_session_id: stripeSessionId,
        },
      });
      console.log('Transaction created:', response.data.transaction_id);
      return response.data.transaction_id;
    }
    ```
    
    <!-- Go -->
    ```
    func walletFunding(reference string, amount float64, currency string, customerBalanceId string, stripeSessionId string, paymentMethod string) {
      transaction, resp, err := client.Transaction.Create(
        blnkgo.CreateTransactionRequest{
          ParentTransaction: blnkgo.ParentTransaction{
            Amount: amount,
            Precision: 100,
            Currency: currency,
            Reference: reference,
            Source: "@Stripe",
            Destination: customerBalanceId,
            Description: "Topup via Stripe",
            MetaData: blnkgo.MetaData{
              "payment_method": paymentMethod,
              "stripe_session_id": stripeSessionId,
            },
          },
          AllowOverdraft: true,
          Inflight: true,
        },
      )
      fmt.Println("Transaction created:", transaction.TransactionID)
      return transaction.TransactionID, nil
    }
    ```
    
    <!-- Python -->
    ```
    def wallet_funding(reference, amount, currency, customerBalanceId, stripeSessionId, paymentMethod):
      response = blnk.transactions.create({
        "amount": amount,
        "precision": 100,
        "currency": currency,
        "reference": reference,
        "source": "@Stripe",
        "destination": customerBalanceId,
        "allow_overdraft": True,
        "inflight": True,
        "description": "Topup via Stripe",
        "meta_data": {
          "payment_method": paymentMethod,
          "stripe_session_id": stripeSessionId,
        },
      })
      print("Transaction created:", response.data["transaction_id"])
      return response.data["transaction_id"]
    ```
    
    <!-- Java -->
    ```
    String walletFunding(String reference, Number amount, String currency, String customerBalanceId, String stripeSessionId, String paymentMethod) {
      ApiResponse<JsonNode> response = blnk.transactions().create(
        CreateTransactions.create()
          .amount(amount)
          .precision(100)
          .currency(currency)
          .reference(reference)
          .source("@Stripe")
          .destination(customerBalanceId)
          .allowOverdraft(true)
          .inflight(true)
          .description("Topup via Stripe")
          .metaData(Map.of("payment_method", paymentMethod, "stripe_session_id", stripeSessionId)));
        System.out.println("Transaction created: " + response.data().get("transaction_id").asText());
        return response.data().get("transaction_id").asText();
      }
    ```
    
    Next, create a Stripe amount using the same reference and adding the transaction and balance id to the metadata:
    
    ```
    const stripe = require('stripe')('sk_test_...');
    const session = await stripe.checkout.sessions.create({
      payment_method_types: ['card'],
      line_items: [
        {
          price_data: {
            currency: 'usd',
            product_data: {
              name: 'Top-up',
            },
            unit_amount: 2000,
          },
          quantity: 1,
        },
      ],
      metadata: {
        blnk_balance_id: "bln_ 123",
        blnk_transaction_id: transactionId
      },
      mode: 'payment',
      success_url: 'https://yourdomain.com/success',
      cancel_url: 'https://yourdomain.com/cancel',
      client_reference_id: 'ref_acmepay-001'
    });
    ```
    
2.  2
    
    Listen for webhooks to know when the payment is captured
    
    Set up a webhook handler to listen for events from Stripe. Then use these events to handle updating the status of the inflight transaction in your ledger.
    
    If successful, the inflight transaction is committed. If failed or expired, it is voided.
    
    <!-- commitPayment -->
    ```
    const express = require('express');
    const app = express();
    const stripe = require('stripe')('sk_test_51Q8v ... MnEh00okDxEs1L');
    const endpointSecret = 'whsec_b653c958ed ... 578088ea2';
    
    app.post('/webhook', express.raw({ type: 'application/json' }), (request, response) => {
      const sig = request.headers['stripe-signature'];
      let event;
      try {
        event = stripe.webhooks.constructEvent(request.body, sig, endpointSecret);
      } catch (err) {
        response.status(400).send(`Webhook Error: ${err.message}`);
        return;
      }
    
      const session = event.data.object;
      console.log('Checkout session completed:', session.id);
    
      if (event.type === 'checkout.session.completed') {
        function commitPayment(session.metadata.blnk_transaction_id)
      } else if (event.type === 'checkout.session.async_payment_failed' || 'checkout.session.expired') {
        function voidPayment(session.metadata.blnk_transaction_id)
      }
    
      response.status(200).end();
    });
    
    app.listen(4242, () => console.log('Running on port 4242'));
    ```
    
3.  3
    
    Update the user balance in your ledger
    
    If successful, commit the inflight transaction in your ledger to update your user's balance.
    
    <!-- TypeScript -->
    ```
    async function commitPayment(transactionId: string) {
      const response = await blnk.Transactions.updateStatus(
        transactionId,
        { status: 'commit' },
      );
      console.log('Transaction committed:', response.data.transaction_id);
      return response.data.transaction_id;
    }
    ```
    
    <!-- Go -->
    ```
    func commitPayment(transactionID string) {
      transaction, resp, err := client.Transaction.Update(
        transactionID,
        blnkgo.UpdateStatus{
          Status: blnkgo.InflightStatusCommit,
        },
      )
      fmt.Println("Transaction committed:", transaction.TransactionID)
      return transaction.TransactionID, nil
    }
    ```
    
    <!-- Python -->
    ```
    def commit_payment(transaction_id):
      response = blnk.transactions.update_status(
        transaction_id,
        {"status": "commit"},
      )
      print("Transaction committed:", response.data["transaction_id"])
      return response.data["transaction_id"]
    ```
    
    <!-- Java -->
    ```
    String commitPayment(String transactionId) {
      ApiResponse<JsonNode> response = blnk.transactions().updateStatus(
        transactionId,
        UpdateTransactionStatus.create()
          .status("commit"));
        System.out.println("Transaction committed: " + response.data().get("transaction_id").asText());
        return response.data().get("transaction_id").asText();
      }
    ```
    
    If failed, void the transaction instead:
    
    <!-- TypeScript -->
    ```
    async function voidPayment(transactionId: string) {
      const response = await blnk.Transactions.updateStatus(
        transactionId,
        { status: 'void' },
      );
      console.log('Transaction voided:', response.data.transaction_id);
      return response.data.transaction_id;
    }
    ```
    
    <!-- Go -->
    ```
    func voidPayment(transactionID string) {
      transaction, resp, err := client.Transaction.Update(
        transactionID,
        blnkgo.UpdateStatus{
          Status: blnkgo.InflightStatusVoid,
        },
      )
      fmt.Println("Transaction voided:", transaction.TransactionID)
      return transaction.TransactionID, nil
    }
    ```
    
    <!-- Python -->
    ```
    def void_payment(transaction_id):
      response = blnk.transactions.update_status(
        transaction_id,
        {"status": "void"},
      )
      print("Transaction voided:", response.data["transaction_id"])
      return response.data["transaction_id"]
    ```
    
    <!-- Java -->
    ```
    String voidPayment(String transactionId) {
      ApiResponse<JsonNode> response = blnk.transactions().updateStatus(
        transactionId,
        UpdateTransactionStatus.create()
          .status("void"));
        System.out.println("Transaction voided: " + response.data().get("transaction_id").asText());
        return response.data().get("transaction_id").asText();
      }
    ```
    

## 3\. Making a purchase

According to our flow of funds, when our user makes a purchase, we record a transaction from the user balance to an internal Revenue balance in our ledger.

To implement this, make a request to the [Record Transaction](https://docs.blnkfinance.com/reference/create-transaction) endpoint as follows:

<!-- TypeScript -->
```
async function walletFunding(reference, purchaseAmount, currency, customerBalanceId) {
  const response = await blnk.Transactions.create({
    amount: purchaseAmount,
    precision: 100,
    currency,
    reference,
    source: customerBalanceId,
    destination: '@Revenue',
    description: 'Payment for online purchase',
    meta_data: {
      payment_method: 'AcmePay',
    },
  });
  console.log('Transaction created:', response.data.transaction_id);
  return response.data.transaction_id;
}
```

<!-- Go -->
```
func walletFunding(reference string, purchaseAmount float64, currency string, customerBalanceId string) {
  transaction, resp, err := client.Transaction.Create(
    blnkgo.CreateTransactionRequest{
      ParentTransaction: blnkgo.ParentTransaction{
        Amount: purchaseAmount,
        Precision: 100,
        Currency: currency,
        Reference: reference,
        Source: customerBalanceId,
        Destination: "@Revenue",
        Description: "Payment for online purchase",
        MetaData: blnkgo.MetaData{
          "payment_method": "AcmePay",
        },
      },
    },
  )
  fmt.Println("Transaction created:", transaction.TransactionID)
  return transaction.TransactionID, nil
}
```

<!-- Python -->
```
def wallet_funding(reference, purchaseAmount, currency, customerBalanceId):
  response = blnk.transactions.create({
    "amount": purchaseAmount,
    "precision": 100,
    "currency": currency,
    "reference": reference,
    "source": customerBalanceId,
    "destination": "@Revenue",
    "description": "Payment for online purchase",
    "meta_data": {
      "payment_method": "AcmePay",
    },
  })
  print("Transaction created:", response.data["transaction_id"])
  return response.data["transaction_id"]
```

<!-- Java -->
```
String walletFunding(String reference, Number purchaseAmount, String currency, String customerBalanceId) {
  ApiResponse<JsonNode> response = blnk.transactions().create(
    CreateTransactions.create()
      .amount(purchaseAmount)
      .precision(100)
      .currency(currency)
      .reference(reference)
      .source(customerBalanceId)
      .destination("@Revenue")
      .description("Payment for online purchase")
      .metaData(Map.of("payment_method", "AcmePay")));
    System.out.println("Transaction created: " + response.data().get("transaction_id").asText());
    return response.data().get("transaction_id").asText();
  }
```

## 4\. Crediting user cashback

Once the purchase has been completed, we record another transaction to credit the customer with their cashback reward from an internal Cashback balance in our ledger:

<!-- TypeScript -->
```
async function creditCashback(reference, cashbackAmount, currency, customerBalanceId) {
  const response = await blnk.Transactions.create({
    amount: cashbackAmount,
    precision: 100,
    currency,
    reference,
    source: '@CashBack',
    destination: customerBalanceId,
    description: 'Cashback reward',
  });
  console.log('Cashback credited:', response.data.transaction_id);
  return response.data.transaction_id;
}
```

<!-- Go -->
```
func creditCashback(reference string, cashbackAmount float64, currency string, customerBalanceId string) {
  transaction, resp, err := client.Transaction.Create(
    blnkgo.CreateTransactionRequest{
      ParentTransaction: blnkgo.ParentTransaction{
        Amount: cashbackAmount,
        Precision: 100,
        Currency: currency,
        Reference: reference,
        Source: "@CashBack",
        Destination: customerBalanceId,
        Description: "Cashback reward",
      },
    },
  )
  fmt.Println("Cashback credited:", transaction.TransactionID)
  return transaction.TransactionID, nil
}
```

<!-- Python -->
```
def credit_cashback(reference, cashbackAmount, currency, customerBalanceId):
  response = blnk.transactions.create({
    "amount": cashbackAmount,
    "precision": 100,
    "currency": currency,
    "reference": reference,
    "source": "@CashBack",
    "destination": customerBalanceId,
    "description": "Cashback reward",
  })
  print("Cashback credited:", response.data["transaction_id"])
  return response.data["transaction_id"]
```

<!-- Java -->
```
String creditCashback(String reference, Number cashbackAmount, String currency, String customerBalanceId) {
  ApiResponse<JsonNode> response = blnk.transactions().create(
    CreateTransactions.create()
      .amount(cashbackAmount)
      .precision(100)
      .currency(currency)
      .reference(reference)
      .source("@CashBack")
      .destination(customerBalanceId)
      .description("Cashback reward"));
    System.out.println("Cashback credited: " + response.data().get("transaction_id").asText());
    return response.data().get("transaction_id").asText();
  }
```

## Conclusion

This guide covers the key steps for managing a wallet, but there are still several important challenges and considerations you’ll need to address when building your wallet product.

For example, you may need to correct an error in your transactions. Since Blnk is [immutable](https://blnkfinance.com/glossary/immutability), it is impossible to edit a transaction that has been created. The only way to do it is to first [refund the transaction](https://docs.blnkfinance.com/transactions/refunds), and then post the correct record.

Other considerations include, performing some checks before completing a transaction, handling Stripe refunds, managing wallet withdrawals, and collaborating with other teams like [Customer Support](https://blnkfinance.com/blog/how-customer-support-teams-use-blnk-finance) for access to your users' financial data.

## Getting started

This article outlined a straightforward way to designing a wallet product, however it doesn't cover all of the unique complexities that different wallet products may involve.

If you have questions about how to build your specific use case with Blnk, feel free to reach out to us via Support or [contact Sales](https://blnkfinance.com/contact/us).

On this page

1.  [The user experience](#the-user-experience)
2.  [Money movement map](#money-movement-map)
3.  [1\. Implementing our wallet](#1-implementing-our-wallet)
4.  [2\. Wallet funding](#2-wallet-funding)
5.  [3\. Making a purchase](#3-making-a-purchase)
6.  [4\. Crediting user cashback](#4-crediting-user-cashback)
7.  [Conclusion](#conclusion)
8.  [Getting started](#getting-started)

Author

-    ![](https://cdn.sanity.io/images/06pses5q/production/140e675048b3b044758196586e139361bbc94f31-500x500.jpg?w=80&h=80&fit=crop&auto=format)Praise Philemon Co-founder & Head of Revenue

Updated on

August 17, 2026

## Related articles

-   [
    
    ![How Blnk handles high-traffic hot balances](https://cdn.sanity.io/images/06pses5q/production/fa2035613e84c271b8deae8f0443488fc8b9431f-1792x1008.png?rect=140,0,1512,1008&w=1500&h=1000&fit=crop&auto=format)
    
    Build
    
    ### How Blnk handles high-traffic hot balances
    
    July 17, 2026
    
    ](https://blnkfinance.com/blog/how-blnk-handles-high-traffic-hot-balances)
-   [
    
    ![How to split payments for a delivery app across merchants, riders, and fees using the Blnk Ledger](https://cdn.sanity.io/images/06pses5q/production/0224ee04875ffed336bb60bf54bc2993a3f7a0a3-1792x1008.png?rect=140,0,1512,1008&w=1500&h=1000&fit=crop&auto=format)
    
    Build
    
    ### How to split payments for a delivery app across merchants, riders, and fees using the Blnk Ledger
    
    July 1, 2026
    
    ](https://blnkfinance.com/blog/how-to-split-payments-across-merchants-fees-and-revenue-with-blnk)
-   [
    
    ![How to build a loan disbursement and repayment app with Flutterwave + Blnk](https://cdn.sanity.io/images/06pses5q/production/a7bba474ff8e34e828ce6453ddde49a6457461ef-1920x1080.png?rect=150,0,1620,1080&w=1500&h=1000&fit=crop&auto=format)
    
    Build
    
    ### How to build a loan disbursement and repayment app with Flutterwave + Blnk
    
    April 23, 2026
    
    ](https://blnkfinance.com/blog/how-to-build-a-loan-disbursement-and-repayment-app-with-flutterwave-blnk)
