# 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.

<TutorialSteps>
  <TutorialStep title="Design the money movement">
    Before we start building, we need to define our [money movement](/ledgers/money-movement-map). 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](/balances/internal-balances) for that money, and the destination is her savings balance.

    We record the deposit with [scheduled_for](/transactions/scheduling) set to 09:00 UTC on 1 December 2026. Her balance stays at 0 until Blnk applies it.

    <TutorialFrame plain>
      <Map src="https://map.blnkfinance.xyz/lRQw98JqFO" title="Savings money movement" />
    </TutorialFrame>
  </TutorialStep>

  <TutorialStep title="Create a ledger">
    Before we start recording transactions, we need to set up our [ledger](/ledgers/introduction) 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.

    <Tip>
      `@WorldUSD` is created in the [General Ledger](/ledgers/general-ledger) when we schedule the deposit, separate from this customer ledger.
    </Tip>

    Create the ledger:

<TutorialCode>
<CodeGroup>

```bash cURL wrap
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}}"
    }
  }'
```

```typescript TypeScript wrap
const response = await blnk.Ledgers.create({
  name: '{{name}}',
  meta_data: {
    description: '{{description}}',
  },
});
```

```go Go wrap
ledger, _, _ := client.Ledger.Create(blnkgo.CreateLedgerRequest{
    Name: "{{name}}",
    MetaData: blnkgo.MetaData{
        "description": "{{description}}",
    },
})
```

```python Python wrap
response = blnk.ledgers.create({
  "name": "{{name}}",
  "meta_data": {
    "description": "{{description}}",
  },
})
```

```java Java wrap
ApiResponse<JsonNode> response = blnk.ledgers().create(
    CreateLedger.create()
        .name("{{name}}")
        .metaData(Map.of(
            "description", "{{description}}"
        )));
```

</CodeGroup>
</TutorialCode>

    <TutorialFrame>
      <Tabs>
        <Tab title="Try it out">
          <TutorialForm id="create-ledger" method="POST" path="/ledgers" save="ledger_id">
            <TutorialInput name="name" label="Ledger name" value="Customer savings" />
            <TutorialInput name="description" label="Description" value="USD balances customers set aside" group="meta_data" />
          </TutorialForm>
        </Tab>
        <Tab title="Response">
          <TutorialResponse />
        </Tab>
      </Tabs>
    </TutorialFrame>
  </TutorialStep>

  <TutorialStep title="Create an identity">
    An [identity](/identities/introduction) 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](/search/metadata). We'll store her customer id there as `customer_id`.

    Create the identity:

<CodeGroup>

```bash cURL wrap
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}}"
    }
  }'
```

```typescript TypeScript wrap
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}}',
  },
});
```

```go Go wrap
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}}",
    },
})
```

```python Python wrap
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}}",
  },
})
```

```java Java wrap
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}}")));
```

</CodeGroup>

    <TutorialFrame>
      <Tabs>
        <Tab title="Try it out">
          <TutorialForm id="create-identity" method="POST" path="/identities" save="identity_id">
            <TutorialValue name="identity_type" value="individual" />
            <TutorialInput name="first_name" label="First name" value="Alice" />
            <TutorialInput name="last_name" label="Last name" value="Johnson" />
            <TutorialInput name="email_address" label="Email" value="alice@example.com" />
            <TutorialInput name="phone_number" label="Phone" value="+1234567890" />
            <TutorialInput name="customer_id" label="Customer id" value="CUST-001" group="meta_data" />
          </TutorialForm>
        </Tab>
        <Tab title="Response">
          <TutorialResponse />
        </Tab>
      </Tabs>
    </TutorialFrame>
  </TutorialStep>

  <TutorialStep title="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:

<CodeGroup>

```bash cURL wrap
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}}"
  }'
```

```typescript TypeScript wrap
const response = await blnk.LedgerBalances.create({
  ledger_id: '{{ledger_id}}',
  identity_id: '{{identity_id}}',
  currency: '{{currency}}',
});
```

```go Go wrap
balance, _, _ := client.LedgerBalance.Create(blnkgo.CreateLedgerBalanceRequest{
    LedgerID: "{{ledger_id}}",
    IdentityID: "{{identity_id}}",
    Currency: "{{currency}}",
})
```

```python Python wrap
response = blnk.ledger_balances.create({
  "ledger_id": "{{ledger_id}}",
  "identity_id": "{{identity_id}}",
  "currency": "{{currency}}",
})
```

```java Java wrap
ApiResponse<JsonNode> response = blnk.ledgerBalances().create(
    CreateLedgerBalance.create()
        .ledgerId("{{ledger_id}}")
        .identityId("{{identity_id}}")
        .currency("{{currency}}"));
```

</CodeGroup>

    <TutorialFrame>
      <Tabs>
        <Tab title="Try it out">
          <TutorialForm id="create-balance" method="POST" path="/balances" save="balance_id">
            <TutorialInput name="ledger_id" label="Ledger" from="ledger_id" />
            <TutorialInput name="identity_id" label="Identity" from="identity_id" />
            <TutorialInput name="currency" label="Currency" value="USD" />
          </TutorialForm>
        </Tab>
        <Tab title="Response">
          <TutorialResponse />
        </Tab>
      </Tabs>
    </TutorialFrame>
  </TutorialStep>

  <TutorialStep title="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.

    <Note>
      To make sure the deposit applies, we need to turn on [overdraft](/transactions/overdrafts). Without it, `@WorldUSD` is created with a 0 balance, and Blnk would reject the record because the source has insufficient funds.
    </Note>

    Schedule the deposit:

<CodeGroup>

```bash cURL wrap
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
  }'
```

```typescript TypeScript wrap
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,
});
```

```go Go wrap
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,
})
```

```python Python wrap
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,
})
```

```java Java wrap
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));
```

</CodeGroup>

    <TutorialFrame>
      <Tabs>
        <Tab title="Try it out">
          <TutorialForm id="schedule-deposit" method="POST" path="/transactions">
            <TutorialValue name="reference" value="SAV-20261201-090000" />
            <TutorialValue name="description" value="Scheduled savings deposit" />
            <TutorialValue name="allow_overdraft" value="true" type="boolean" />
            <TutorialInput name="amount" label="Amount" value="100.00" type="amount" precision="100" />
            <TutorialInput name="currency" label="Currency" value="USD" />
            <TutorialInput name="source" label="Source" value="@WorldUSD" />
            <TutorialInput name="destination" label="Destination" from="balance_id" />
            <TutorialInput name="scheduled_for" label="Scheduled for" value="2026-12-01T09:00:00+00:00" />
          </TutorialForm>
        </Tab>
        <Tab title="Response">
          <TutorialResponse />
        </Tab>
      </Tabs>
    </TutorialFrame>
  </TutorialStep>

  <TutorialStep title="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.

    <Tip>
      When that deposit applies, schedule the next one the same way. Use a new reference and the next date.
    </Tip>

    If you have a Blnk Cloud account or an Enterprise license, you can confirm this by checking the dashboard or using the [CLI](/cli/balances).

    Print every balance:

```bash List balances wrap
blnk balances list
```

  </TutorialStep>
</TutorialSteps>