Overview

Transactions are used to enable money movement between two or more balances. These can be payments, transfers, settlements, internal treasury management, etc. All transactions in Blnk are recorded with the double entry principle, i.e., there is a source and a corresponding destination for each transaction entry.

In this guide, you’ll learn:

  1. Transaction properties
  2. Recording a transaction
  3. How transactions work in Blnk
  4. Managing insufficient funds

Transaction properties

  1. Immutability: Once recorded, transactions in Blnk cannot be modified or deleted. This fundamental property ensures the integrity and reliability of your transaction history, preventing any unauthorized alterations. See also: Transaction hashing

  2. Idempotency: Each transaction in Blnk produces the same result whether executed once or multiple times. This is crucial for maintaining data consistency, especially during network failures or system retries.

    Blnk implements idempotency by requiring a unique reference for every transaction. This reference serves as a transaction identifier, preventing duplicate processing and ensuring consistent outcomes.


Recording a transaction

To record a transaction, call the record-transaction endpoint:

POST http://YOUR_BLNK_INSTANCE_URL/transactions

With the following request body:

{
    "amount": 750,
    "reference": "ref_001adcfgf",
    "currency": "USD",
    "precision": 100,
    "source": "@FundingPool",
    "destination": "bln_ebcd230f-6265-4d4a-a4ca-45974c47f746",
    "description": "Fund with starting balance amount",
    "allow_overdraft": true,
    "meta_data": {
      "sender_name": "John Doe",
      "sender_account": "00000000000"
    }
}

If this is your first transaction, the participating balances will start at 0. To ensure the transaction is successful, enable overdrafts as shown above, allowing the source balance to go negative.

Learn more about Overdrafts and Negative Balances.

Response
{
    "id": "txn_6164573b-6cc8-45a4-ad2e-7b4ba6a60f7d",
    "source": "@FundingPool",
    "destination": "bln_ebcd230f-6265-4d4a-a4ca-45974c47f746",
    "reference": "ref_001adcfgf",
    "amount": 750,
    "precision": 100,
    "precise_amount": 75000,
    "currency": "USD",
    "description": "Fund with starting balance amount",
    "status": "QUEUED",
    "created_at": "2024-12-21T01:36:46.997063436Z",
    "meta_data": {
      "sender_name": "John Doe",
      "sender_account": "00000000000"
    }
}
FieldDescriptionRequiredType
amountThe transaction amount.Yesfloat
referenceYour unique reference to ensure idempotency.Yesstring
currencyShort code for your asset class. See also: Asset classesYesstring
precisionPrecision for the currency/asset passed. See also: PrecisionNoint64
sourceSender’s balance IDYesstring
destinationRecipient’s balance ID.Yesstring
descriptionDescription or narration of the transaction.Nostring
meta_dataCustom data associated with the transactionNoobject

Passing detailed data with the meta_data object is encouraged; it provides you with 360-degree insights about each transaction record. Examples of data you can pass include sender_name, account_number, bank_name, receiver_name, payment_id, ip_address, location, payment_method, etc.

Next, you can view a list of all transactions in your ledger:

bash
blnk transactions list

How transactions work in Blnk

Every transaction goes through multiple states in Blnk, and each state change is recorded as a separate record in the database. This gives you complete traceability, allowing to see the lifecycle of a transaction from initiation to completion.

Each state is connected to the previous state through a parent_transaction attribute. Here’s how it works:

1

Transaction lifecycle

By default, every transaction begins in a QUEUED state.

You can choose to skip this QUEUED state altogether and directly process your transactions. Learn more: Skip Transaction Queue

Within milliseconds of being queued, Blnk processes it and transitions it to one of three possible states:

  • INFLIGHT: If the transaction request includes "inflight": "true".
    • APPLIED: If the inflight transaction is committed.
    • VOID: If the inflight transaction is voided.
  • APPLIED: When the transaction is completed and applied to the balances.
  • REJECTED: When the transaction is not processed due to reasons like insufficient funds.

Here’s an example response when you record a new transaction on Blnk:

Record transaction response
{
  "precise_amount": 10000000,
  "amount": 100000,
  "rate": 0,
  "precision": 100,
  "transaction_id": "txn_d4951810-706c-44d1-be45-6f254be0e167",
  "parent_transaction": "",
  "source": "bln_7769aedf-bc88-49f7-bbb2-118f121daee6",
  "destination": "bln_c42e4bbd-4ea9-494a-89be-7634b0c1e41a",
  "reference": "ref_e55c4f33-bff7-4c30-9b9f-5d2d10a29b7a",
  "currency": "USD",
  "description": "Sample transaction",
  "status": "QUEUED",
  "hash": "3ef19e9cd9aba07d33068d096da1e1596f1270a70c9aa2d160206b4d6da553dc",
  "allow_overdraft": true,
  "inflight": false,
  "created_at": "2025-02-02T02:35:16.606614793Z",
  "scheduled_for": "0001-01-01T00:00:00Z",
  "inflight_expiry_date": "0001-01-01T00:00:00Z"
}
2

Record creation and tracking

When a transaction moves to its next state (INFLIGHT, APPLIED, or REJECTED), Blnk creates a new record that maintains a connection to the original queued transaction. This connection is maintained in two ways:

  1. Parent-Child Relationship: The new record’s parent_transaction field stores the original transaction’s transaction_id. This creates a clear lineage between related transaction records.
  2. Reference Tracking: To ensure each record remains uniquely identifiable while preserving its relationship to other states, Blnk:
    • Uses the same base reference as the original transaction.
    • Appends a _q suffix to create a unique reference.

For example, if the original transaction has:

{
  ...
  "transaction_id": "txn_123",
  "reference": "payment_abc"
}

The next state’s record would have:

{
  ...
  "parent_transaction": "txn_123",
  "reference": "payment_abc_q"
}
3

Tracking transaction status

You can track the final state of your transactions using either of these methods:

  1. Reference Search: Query transactions using the original reference. Blnk will return the INFLIGHT or APPLIED record associated with that reference.
    {
      "q": "payment_abc",
      "query_by": "reference"
    }
    
  2. Parent Transaction Search: Look up transactions using the original transaction_id as a parent transaction identifier. This returns the same result as the reference search but uses the parent-child relationship instead of the reference string.
    {
      "q": "txn_123",
      "query_by": "parent_transaction"
    }
    
4

Discarded transactions

A discarded transaction is not recorded in the ledger. Blnk discards transactions for one reason:

  1. Duplicate reference: Your new transaction reference matches an existing reference in your ledger. Blnk requires unique reference values per transaction. Options are timestamps (e.g. UNIX timestamp), random string or UUID (e.g. ref_e55c4f33-bff7-4c30-9b9f-5d2d10a29b7a), or a business identifier like an order_id.
Make sure your request body match the Blnk Ledger API specifications. For example, avoid passing apply_overdraft instead of allow_overdraft.

Skip transaction queue

Available in version 0.8.2 and later.

The skip_queue feature allows you to bypass the default transaction queuing system outlined above and process transactions directly. This is useful for scenarios where you need real-time transaction processing while still maintaining data consistency.

To enable this feature, include “skip_queue”: true in the request body when calling the Create Transaction endpoint:

{
  "amount": 102.12,
  "precision": 100,
  ...
  "allow_overdraft": true,
  "skip_queue": true
}

How it works

When you enable skip_queue, the transaction:

  • Bypasses the normal queuing process
  • Executes immediately on the balance
  • Uses distributed locks via Redis to maintain consistency
  • Applies optimistic locking at the database level

Example applications

Use skip_queue for:

  • Real-time payment processing in your ledger
  • Interactive user sessions requiring immediate feedback
  • Time-sensitive financial operations
Consider rate limiting for high traffic scenarios. Learn how: blnk.json Configuration File

Managing insufficient funds

You can handle insufficient funds scenarios in two ways: through automatic rejection handling when transactions are attempted with insufficient balance, and through proactive balance checking before initiating transactions.

1. Automatic rejection

When a transaction is posted where the source balance has insufficient funds, Bink automatically handles this scenario to maintain ledger integrity. Blnk:

  1. Rejects the transaction.
  2. Records this rejection in your ledger using the same state tracking mechanism we discussed above (i.e. QUEUEDREJECTED).
  3. Sends a webhook notification to inform your system of the state change and new ledger record.
You can also preemptively track the transaction status (via reference or parent_transaction) to know if the transaction was successful or rejected.

2. Proactive balance verification

Instead of waiting for a transaction.rejected webhook, you can implement a preemptive available balance check in your workflow. Here’s how:

First, query the balance of the sender using:

GET /balances/{balance_id}?with_queued=true

Next, calculate your available balance:

available_balance = balance - queued_debit_balance
  • If the available balance is sufficient, proceed with posting your transaction.
  • If the available balance is insufficient, you can gracefully handle this scenario in your application by notifying the customer immediately, avoiding the need for webhook handling.

Queued balances

Learn how queued balances work

Insufficient funds for inflight transactions

For a detailed understanding of how insufficient funds can be managed in inflight scenarios, please refer to our Applying inflight guide.



Need help?

We are very happy to help you make the most of Blnk, regardless of whether it is your first time or you are switching from another tool.

To ask questions or discuss issues, please contact us or join our Discord community.

Love building with Blnk? We’d love to hear your feedback. Tell us here.