Transactions

Split transactions

Move money from several balances to one, or from one balance to several.

A split moves money in one request, with more than one balance on a single side.

Send sources when several balances pay one destination. Send destinations when one balance pays several recipients.

Record split

Sarah’s balance is bln_92e4b9b6-0b85-4ef4-87a2-682c31500d38. Alice, Bob, and Charlie use the same balances in both scenarios. Alice’s leg is a percentage, Bob’s is a fixed amount, and Charlie’s is "left".

Several sources. They pay Sarah USD 30,000. Alice sends 10%, Bob sends $20,000, and Charlie sends the rest.

Several destinations. Sarah pays USD 30,000 out. Alice receives 20%, Bob receives $10,000, and Charlie receives the rest.

Using the API

Call Create transaction. Send sources instead of source, or destinations instead of destination. To preview the split without writing it, set dry_run to true. See Dry-run transactions.

Blnk returns one id for the split, and an id for each leg on the array you sent. With inflight: true, that split id commits or voids every leg. See Record split inflight transaction.

curl -X POST http://localhost:5001/transactions \
  -H "Content-Type: application/json" \
  -H "X-Blnk-Key: <api-key>" \
  -d '{
    "precise_amount": 3000000,
    "precision": 100,
    "reference": "ref_001adcfgf",
    "currency": "USD",
    "sources": [
        {
            "identifier": "bln_f2073f6b-905a-4e3e-b5a2-8d1b3dc2fb7f",
            "distribution": "10%"
        },
        {
            "identifier": "bln_64c50fb5-32d5-4f78-9f4a-e8b01aaf025d",
            "precise_distribution": "2000000"
        },
        {
            "identifier": "bln_7d98dfe9-5c3e-4c9b-b96a-65f6d9f7b89b",
            "distribution": "left"
        }
    ],
    "destination": "bln_92e4b9b6-0b85-4ef4-87a2-682c31500d38",
    "description": "Payment to Sarah"
  }'
const response = await blnk.Transactions.create({
  precise_amount: 3000000,
  precision: 100,
  reference: 'ref_001adcfgf',
  currency: 'USD',
  sources: [
    { identifier: 'bln_f2073f6b-905a-4e3e-b5a2-8d1b3dc2fb7f', distribution: '10%' },
    { identifier: 'bln_64c50fb5-32d5-4f78-9f4a-e8b01aaf025d', precise_distribution: '2000000' },
    { identifier: 'bln_7d98dfe9-5c3e-4c9b-b96a-65f6d9f7b89b', distribution: 'left' },
  ],
  destination: 'bln_92e4b9b6-0b85-4ef4-87a2-682c31500d38',
  description: 'Payment to Sarah',
});
transaction, _, _ := client.Transaction.Create(blnkgo.CreateTransactionRequest{
    ParentTransaction: blnkgo.ParentTransaction{
        PreciseAmount: big.NewInt(3000000),
        Precision: 100,
        Reference: "ref_001adcfgf",
        Currency: "USD",
        Description: "Payment to Sarah",
        Sources: []blnkgo.Source{
            {Identifier: "bln_f2073f6b-905a-4e3e-b5a2-8d1b3dc2fb7f", Distribution: "10%"},
            {Identifier: "bln_64c50fb5-32d5-4f78-9f4a-e8b01aaf025d", PreciseDistribution: "2000000"},
            {Identifier: "bln_7d98dfe9-5c3e-4c9b-b96a-65f6d9f7b89b", Distribution: "left"},
        },
        Destination: "bln_92e4b9b6-0b85-4ef4-87a2-682c31500d38",
    },
})
response = blnk.transactions.create({
  "precise_amount": 3000000,
  "precision": 100,
  "reference": "ref_001adcfgf",
  "currency": "USD",
  "sources": [
    {"identifier": "bln_f2073f6b-905a-4e3e-b5a2-8d1b3dc2fb7f", "distribution": "10%"},
    {"identifier": "bln_64c50fb5-32d5-4f78-9f4a-e8b01aaf025d", "precise_distribution": "2000000"},
    {"identifier": "bln_7d98dfe9-5c3e-4c9b-b96a-65f6d9f7b89b", "distribution": "left"},
  ],
  "destination": "bln_92e4b9b6-0b85-4ef4-87a2-682c31500d38",
  "description": "Payment to Sarah",
})
ApiResponse<JsonNode> response = blnk.transactions().create(
    CreateTransactions.create()
        .preciseAmount(3000000)
        .precision(100)
        .reference("ref_001adcfgf")
        .currency("USD")
        .sources(List.of(
            MultipleSourcesT.create()
            .identifier("bln_f2073f6b-905a-4e3e-b5a2-8d1b3dc2fb7f")
            .distribution("10%"),
            MultipleSourcesT.create()
            .identifier("bln_64c50fb5-32d5-4f78-9f4a-e8b01aaf025d")
            .preciseDistribution("2000000"),
            MultipleSourcesT.create()
            .identifier("bln_7d98dfe9-5c3e-4c9b-b96a-65f6d9f7b89b")
            .distribution("left")
        ))
        .destination("bln_92e4b9b6-0b85-4ef4-87a2-682c31500d38")
        .description("Payment to Sarah"));
blnk transactions create
{
    "precise_amount": 3000000,
    "amount": 30000,
    "precision": 100,
    "overdraft_limit": 0,
    "transaction_id": "txn_0b59f6e6-6c4a-4efa-915c-526f77ef61ab",
    "parent_transaction": "",
    "source": "",
    "reference": "ref_001adcfgf",
    "currency": "USD",
    "description": "txn",
    "status": "QUEUED",
    "hash": "8cfdc0f2562ce30c3728ef624dc29fbd0e4207c77df9220df0c699d45de0eef",
    "allow_overdraft": true,
    "inflight": false,
    "skip_queue": false,
    "atomic": false,
    "sources": [
        {
            "identifier": "@test-2024",
            "distribution": "10%",
            "transaction_id": "txn_59347177-aa7e-d8ad-9f4f-d09628b32ec3"
        },
        {
            "identifier": "@test-21",
            "distribution": "20000",
            "transaction_id": "txn_7ddc8d4f-3b77-4b7d-a37f-240216ab074c"
        },
        {
            "identifier": "@test-218",
            "distribution": "left",
            "transaction_id": "txn_5aad04dd-ed53-4f77-9f01-4916d31fac5f"
        }
    ],
    "destination": "bln_92e4b9b6-0b85-4ef4-87a2-682c31500d38",
    "created_at": "2025-09-18T01:26:30.648049042Z",
    "scheduled_for": "0001-01-01T00:00:00Z",
    "inflight_expiry_date": "0001-01-01T00:00:00Z",
    "meta_data": {
        "QUEUED_PARENT_TRANSACTION": "txn_0b59f6e6-6c4a-4efa-915c-526f77ef61ab"
    }
}
curl -X POST http://localhost:5001/transactions \
  -H "Content-Type: application/json" \
  -H "X-Blnk-Key: <api-key>" \
  -d '{
    "precise_amount": 3000000,
    "precision": 100,
    "reference": "ref_001adcfgf",
    "currency": "USD",
    "source": "bln_92e4b9b6-0b85-4ef4-87a2-682c31500d38",
    "destinations": [
        {
            "identifier": "bln_f2073f6b-905a-4e3e-b5a2-8d1b3dc2fb7f",
            "distribution": "20%"
        },
        {
            "identifier": "bln_64c50fb5-32d5-4f78-9f4a-e8b01aaf025d",
            "precise_distribution": "1000000"
        },
        {
            "identifier": "bln_7d98dfe9-5c3e-4c9b-b96a-65f6d9f7b89b",
            "distribution": "left"
        }
    ],
    "description": "Payment from Sarah"
  }'
const response = await blnk.Transactions.create({
  precise_amount: 3000000,
  precision: 100,
  reference: 'ref_001adcfgf',
  currency: 'USD',
  source: 'bln_92e4b9b6-0b85-4ef4-87a2-682c31500d38',
  destinations: [
    { identifier: 'bln_f2073f6b-905a-4e3e-b5a2-8d1b3dc2fb7f', distribution: '20%' },
    { identifier: 'bln_64c50fb5-32d5-4f78-9f4a-e8b01aaf025d', precise_distribution: '1000000' },
    { identifier: 'bln_7d98dfe9-5c3e-4c9b-b96a-65f6d9f7b89b', distribution: 'left' },
  ],
  description: 'Payment from Sarah',
});
transaction, _, _ := client.Transaction.Create(blnkgo.CreateTransactionRequest{
    ParentTransaction: blnkgo.ParentTransaction{
        PreciseAmount: big.NewInt(3000000),
        Precision: 100,
        Reference: "ref_001adcfgf",
        Currency: "USD",
        Source: "bln_92e4b9b6-0b85-4ef4-87a2-682c31500d38",
        Description: "Payment from Sarah",
        Destinations: []blnkgo.Source{
            {Identifier: "bln_f2073f6b-905a-4e3e-b5a2-8d1b3dc2fb7f", Distribution: "20%"},
            {Identifier: "bln_64c50fb5-32d5-4f78-9f4a-e8b01aaf025d", PreciseDistribution: "1000000"},
            {Identifier: "bln_7d98dfe9-5c3e-4c9b-b96a-65f6d9f7b89b", Distribution: "left"},
        },
    },
})
response = blnk.transactions.create({
  "precise_amount": 3000000,
  "precision": 100,
  "reference": "ref_001adcfgf",
  "currency": "USD",
  "source": "bln_92e4b9b6-0b85-4ef4-87a2-682c31500d38",
  "destinations": [
    {"identifier": "bln_f2073f6b-905a-4e3e-b5a2-8d1b3dc2fb7f", "distribution": "20%"},
    {"identifier": "bln_64c50fb5-32d5-4f78-9f4a-e8b01aaf025d", "precise_distribution": "1000000"},
    {"identifier": "bln_7d98dfe9-5c3e-4c9b-b96a-65f6d9f7b89b", "distribution": "left"},
  ],
  "description": "Payment from Sarah",
})
ApiResponse<JsonNode> response = blnk.transactions().create(
    CreateTransactions.create()
        .preciseAmount(3000000)
        .precision(100)
        .reference("ref_001adcfgf")
        .currency("USD")
        .source("bln_92e4b9b6-0b85-4ef4-87a2-682c31500d38")
        .destinations(List.of(
            MultipleSourcesT.create()
            .identifier("bln_f2073f6b-905a-4e3e-b5a2-8d1b3dc2fb7f")
            .distribution("20%"),
            MultipleSourcesT.create()
            .identifier("bln_64c50fb5-32d5-4f78-9f4a-e8b01aaf025d")
            .preciseDistribution("1000000"),
            MultipleSourcesT.create()
            .identifier("bln_7d98dfe9-5c3e-4c9b-b96a-65f6d9f7b89b")
            .distribution("left")
        ))
        .description("Payment from Sarah"));
blnk transactions create
{
    "precise_amount": 3000000,
    "amount": 30000,
    "precision": 100,
    "overdraft_limit": 0,
    "transaction_id": "txn_0b59f6e6-6c4a-4efa-915c-526f77ef61ab",
    "parent_transaction": "",
    "source": "bln_92e4b9b6-0b85-4ef4-87a2-682c31500d38",
    "reference": "ref_001adcfgf",
    "currency": "USD",
    "description": "Payment from Sarah",
    "status": "QUEUED",
    "hash": "8cfdc0f2562ce30c3728ef624dc29fbd0e4207c77df9220df0c699d45de0eef",
    "allow_overdraft": true,
    "inflight": false,
    "skip_queue": false,
    "atomic": false,
    "destinations": [
        {
            "identifier": "bln_f2073f6b-905a-4e3e-b5a2-8d1b3dc2fb7f",
            "distribution": "20%",
            "transaction_id": "txn_59347177-aa7e-d8ad-9f4f-d09628b32ec3"
        },
        {
            "identifier": "bln_64c50fb5-32d5-4f78-9f4a-e8b01aaf025d",
            "distribution": "10000",
            "transaction_id": "txn_7ddc8d4f-3b77-4b7d-a37f-240216ab074c"
        },
        {
            "identifier": "bln_7d98dfe9-5c3e-4c9b-b96a-65f6d9f7b89b",
            "distribution": "left",
            "transaction_id": "txn_5aad04dd-ed53-4f77-9f01-4916d31fac5f"
        }
    ],
    "created_at": "2025-09-18T01:26:30.648049042Z",
    "scheduled_for": "0001-01-01T00:00:00Z",
    "inflight_expiry_date": "0001-01-01T00:00:00Z",
    "meta_data": {
        "QUEUED_PARENT_TRANSACTION": "txn_0b59f6e6-6c4a-4efa-915c-526f77ef61ab"
    }
}

Using the Dashboard

On Transactions, open Create transaction.

For several sources, click Add another source under Source and set the balance and amount for each leg. The destination stays one balance.

Create transaction form with multiple sources

For several destinations, click Add another destination under Destination. The source stays one balance.

Create transaction form with multiple destinations

How it works

Distribution

You can specify distribution amounts in three ways. The same rules apply to sources and to destinations.

TypeDescriptionExample
Specific amountFixed amount. Use precise_distribution when the transaction uses precise_amount."precise_distribution": "2000000"
PercentagePercentage of the total amount"distribution": "10%"
RemainingWhatever is left after the other legs"distribution": "left"

When a transaction uses precise_amount, use precise_distribution instead of distribution only for legs that specify an exact value. Percentages ("10%") and the remainder ("left") still use distribution.

{
  "precise_amount": 189207535698279000,
  "sources": [
    {
      "identifier": "bln_f2073f6b-905a-4e3e-b5a2-8d1b3dc2fb7f",
      "precise_distribution": "37841507139655800"
    },
    {
      "identifier": "bln_64c50fb5-32d5-4f78-9f4a-e8b01aaf025d",
      "distribution": "20%"
    }
  ]
}

Transaction references

Blnk generates a unique reference for each leg by appending a counter to your reference, starting at 1.

From version 0.15.4 the suffix follows the order of the array you sent, sources or destinations, and stays stable across retries.

If your reference is ref_001adcfgf, the legs are ref_001adcfgf_1, ref_001adcfgf_2, and ref_001adcfgf_3.

Retrieving child transactions

Blnk records one coordinated request and a separate ledger movement for each leg. Filter on meta_data.QUEUED_PARENT_TRANSACTION to retrieve those movements.

curl -X POST "http://localhost:5001/transactions/filter" \
  -H "X-blnk-key: <api-key>" \
  -H "Content-Type: application/json" \
  -d '{
    "filters": [
      {
        "field": "meta_data.QUEUED_PARENT_TRANSACTION",
        "operator": "eq",
        "value": "<queued_parent_transaction_id>"
      }
    ]
  }'
const response = await blnk.Search.filter(
  {
    filters: [
      {
        field: 'meta_data.QUEUED_PARENT_TRANSACTION',
        operator: 'eq',
        value: '<queued_parent_transaction_id>',
      },
    ],
  },
  'transactions',
);
results, _, _ := client.Transaction.Filter(blnkgo.FilterParams{
    Filters: []blnkgo.Filter{
        {
            Field: "meta_data.QUEUED_PARENT_TRANSACTION",
            Operator: blnkgo.OpEqual,
            Value: "<queued_parent_transaction_id>",
        },
    },
})
response = blnk.search.filter(
  {
    "filters": [
      {
        "field": "meta_data.QUEUED_PARENT_TRANSACTION",
        "operator": "eq",
        "value": "<queued_parent_transaction_id>",
      },
    ],
  },
  "transactions",
)
ApiResponse<JsonNode> response = blnk.search().filter(
    FilterParams.create()
        .filters(List.of(
            FilterCondition.create()
            .field("meta_data.QUEUED_PARENT_TRANSACTION")
            .operator("eq")
            .value("<queued_parent_transaction_id>")
        )),
    "transactions");

The filter returns every transaction created as part of the split.

Atomic processing

By default, Blnk processes a split with atomic: false. Each leg is evaluated on its own. Legs that pass are marked APPLIED, and legs that fail are marked REJECTED. That can leave a partial split.

Set atomic: true for all-or-nothing processing. Every leg must succeed. If one leg fails, Blnk refunds the legs that already processed. Each refund cancels that movement, so the split does not leave a partial result.