Connect your sandbox to see this tutorial in action.

Tutorials

Savings

Learn how to implement a savings balance with Blnk.

A savings balance is the account a customer uses to set money aside on a date they choose. The deposit is recorded now and applied when that date arrives.

This tutorial shows how to implement that with Blnk.

Step

Design the money movement

Before we start building, we need to define our money movement. This helps us outline how money moves into savings.

Alice sets aside $100.00 from outside the system. The source is @WorldUSD, an internal balance for that money, and the destination is her savings balance.

We record the deposit with scheduled_for set to 09:00 UTC on 1 December 2026. Her balance stays at 0 until Blnk applies it.

Step

Create a ledger

Before we start recording transactions, we need to set up our ledger to track customers and their savings balances.

For our savings example, we only support one currency, USD. Therefore, we’ll create a ledger to manage all USD savings balances belonging to our customers.

Create the ledger:

curl -X POST "CORE_URL/ledgers" \
  -H "X-blnk-key: CORE_SECRET_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "{{name}}",
    "meta_data": {
      "description": "{{description}}"
    }
  }'
const response = await blnk.Ledgers.create({
  name: '{{name}}',
  meta_data: {
    description: '{{description}}',
  },
});
ledger, _, _ := client.Ledger.Create(blnkgo.CreateLedgerRequest{
    Name: "{{name}}",
    MetaData: blnkgo.MetaData{
        "description": "{{description}}",
    },
})
response = blnk.ledgers.create({
  "name": "{{name}}",
  "meta_data": {
    "description": "{{description}}",
  },
})
ApiResponse<JsonNode> response = blnk.ledgers().create(
    CreateLedger.create()
        .name("{{name}}")
        .metaData(Map.of(
            "description", "{{description}}"
        )));

Step

Create an identity

An identity is how we record the customer. We pass Alice’s type, name, email, and phone number.

Anything else we want to keep goes in metadata. We’ll store her customer id there as customer_id.

Create the identity:

curl -X POST "CORE_URL/identities" \
  -H "X-blnk-key: CORE_SECRET_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "identity_type": "individual",
    "first_name": "{{first_name}}",
    "last_name": "{{last_name}}",
    "email_address": "{{email_address}}",
    "phone_number": "{{phone_number}}",
    "meta_data": {
      "customer_id": "{{customer_id}}"
    }
  }'
const response = await blnk.Identity.create({
  identity_type: 'individual',
  first_name: '{{first_name}}',
  last_name: '{{last_name}}',
  email_address: '{{email_address}}',
  phone_number: '{{phone_number}}',
  meta_data: {
    customer_id: '{{customer_id}}',
  },
});
identity, _, _ := client.Identity.Create(blnkgo.Identity{
    IdentityType: blnkgo.Individual,
    FirstName: "{{first_name}}",
    LastName: "{{last_name}}",
    EmailAddress: "{{email_address}}",
    PhoneNumber: "{{phone_number}}",
    MetaData: blnkgo.MetaData{
        "customer_id": "{{customer_id}}",
    },
})
response = blnk.identity.create({
  "identity_type": "individual",
  "first_name": "{{first_name}}",
  "last_name": "{{last_name}}",
  "email_address": "{{email_address}}",
  "phone_number": "{{phone_number}}",
  "meta_data": {
    "customer_id": "{{customer_id}}",
  },
})
ApiResponse<JsonNode> response = blnk.identity().create(
    IdentityData.create()
        .identityType("individual")
        .firstName("{{first_name}}")
        .lastName("{{last_name}}")
        .emailAddress("{{email_address}}")
        .phoneNumber("{{phone_number}}")
        .metaData(Map.of("customer_id", "{{customer_id}}")));

Step

Create the savings balance

Now that we have Alice in our ledger, we can create a balance for her, stored in the ledger from step 2.

We’ll use the ledger_id and identity_id from the earlier steps, set the currency, and submit. Blnk creates the balance and attaches it to Alice.

Create the savings balance:

curl -X POST "CORE_URL/balances" \
  -H "X-blnk-key: CORE_SECRET_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "ledger_id": "{{ledger_id}}",
    "identity_id": "{{identity_id}}",
    "currency": "{{currency}}"
  }'
const response = await blnk.LedgerBalances.create({
  ledger_id: '{{ledger_id}}',
  identity_id: '{{identity_id}}',
  currency: '{{currency}}',
});
balance, _, _ := client.LedgerBalance.Create(blnkgo.CreateLedgerBalanceRequest{
    LedgerID: "{{ledger_id}}",
    IdentityID: "{{identity_id}}",
    Currency: "{{currency}}",
})
response = blnk.ledger_balances.create({
  "ledger_id": "{{ledger_id}}",
  "identity_id": "{{identity_id}}",
  "currency": "{{currency}}",
})
ApiResponse<JsonNode> response = blnk.ledgerBalances().create(
    CreateLedgerBalance.create()
        .ledgerId("{{ledger_id}}")
        .identityId("{{identity_id}}")
        .currency("{{currency}}"));

Step

Schedule a deposit

Alice sets aside $100.00 on 1 December 2026. We record that now, with scheduled_for set to 2026-12-01T09:00:00+00:00, and Blnk applies it at 09:00 UTC that day.

The source is @WorldUSD, and the destination is her savings balance. The reference and the description are already set.

Schedule the deposit:

curl -X POST "CORE_URL/transactions" \
  -H "X-blnk-key: CORE_SECRET_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "precise_amount": {{precise_amount}},
    "precision": 100,
    "reference": "SAV-20261201-090000",
    "description": "Scheduled savings deposit",
    "currency": "{{currency}}",
    "source": "{{source}}",
    "destination": "{{destination}}",
    "scheduled_for": "{{scheduled_for}}",
    "allow_overdraft": true
  }'
const amount = {{amount}};
const precision = 100;
const precise_amount = Math.round(amount * precision);

const response = await blnk.Transactions.create({
  precise_amount,
  precision,
  reference: 'SAV-20261201-090000',
  description: 'Scheduled savings deposit',
  currency: '{{currency}}',
  source: '{{source}}',
  destination: '{{destination}}',
  scheduled_for: '{{scheduled_for}}',
  allow_overdraft: true,
});
amount := {{amount}}
precision := 100
preciseAmount := big.NewInt(int64(math.Round(amount * float64(precision))))
scheduledFor, _ := time.Parse(time.RFC3339, "{{scheduled_for}}")

transaction, _, _ := client.Transaction.Create(blnkgo.CreateTransactionRequest{
    ParentTransaction: blnkgo.ParentTransaction{
        PreciseAmount: preciseAmount,
        Precision: precision,
        Reference: "SAV-20261201-090000",
        Description: "Scheduled savings deposit",
        Currency: "{{currency}}",
        Source: "{{source}}",
        Destination: "{{destination}}",
    },
    ScheduledFor: &scheduledFor,
    AllowOverdraft: true,
})
amount = {{amount}}
precision = 100
precise_amount = round(amount * precision)

response = blnk.transactions.create({
  "precise_amount": precise_amount,
  "precision": precision,
  "reference": "SAV-20261201-090000",
  "description": "Scheduled savings deposit",
  "currency": "{{currency}}",
  "source": "{{source}}",
  "destination": "{{destination}}",
  "scheduled_for": "{{scheduled_for}}",
  "allow_overdraft": True,
})
double amount = {{amount}};
int precision = 100;
int preciseAmount = (int) Math.round(amount * precision);

ApiResponse<JsonNode> response = blnk.transactions().create(
    CreateTransactions.create()
        .preciseAmount(preciseAmount)
        .precision(precision)
        .reference("SAV-20261201-090000")
        .description("Scheduled savings deposit")
        .currency("{{currency}}")
        .source("{{source}}")
        .destination("{{destination}}")
        .scheduledFor("{{scheduled_for}}")
        .allowOverdraft(true));

Step

Confirmation

We should now have a scheduled deposit of $100.00 into Alice’s savings balance. The balance stays at 0 until 09:00 UTC on 1 December 2026, when Blnk applies the transaction.

If you have a Blnk Cloud account or an Enterprise license, you can confirm this by checking the dashboard or using the CLI.

Print every balance:

blnk balances list