# Split transactions

Move money from multiple sources to one destination, or from one source to multiple destinations.

<Version>Available in version 0.6.0 and later.</Version>

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.

<Warning>
A split is one side only. A payload that includes both `sources` and `destinations` is rejected with `400 TXN_VALIDATION_ERROR`.
</Warning>

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

<Map
  src="https://map.blnkfinance.xyz/GvPWMwzF3r"
  title="Multiple sources"
/>

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

<Map
  src="https://map.blnkfinance.xyz/2MmTXXT8tj"
  title="Multiple destinations"
/>

### Using the API

Call [Create transaction](/reference/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](/transactions/dry-run).

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](/transactions/inflight/create-inflight#record-split-inflight-transaction).

<Tabs>
<Tab title="Multiple sources">

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

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

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

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

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

```bash Blnk CLI wrap
blnk transactions create
```
</CodeGroup>

```json Response {7,23,28,33}
{
    "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"
    }
}
```

</Tab>
<Tab title="Multiple destinations">

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

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

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

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

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

```bash Blnk CLI wrap
blnk transactions create
```
</CodeGroup>

```json Response {7,23,28,33}
{
    "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"
    }
}
```

</Tab>
</Tabs>

### 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](img/transactions/create-transaction-multiple-sources.png)

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

![Create transaction form with multiple destinations](img/transactions/create-transaction-multiple-destinations.png)

## How it works

### Distribution

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

| Type | Description | Example |
| :--- | :--- | :--- |
| **Specific amount** | Fixed amount. Use `precise_distribution` when the transaction uses `precise_amount`. | `"precise_distribution": "2000000"` |
| **Percentage** | Percentage of the total amount | `"distribution": "10%"` |
| **Remaining** | Whatever is left after the other legs | `"distribution": "left"` |

<Warning>
You can only use `"left"` once per transaction, and all distributions must sum to the total amount.
</Warning>

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

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

<Tip>
For how `precise_amount` and `precision` work, see [Precision](/transactions/precision).
</Tip>

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

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

```typescript TypeScript wrap
const response = await blnk.Search.filter(
  {
    filters: [
      {
        field: 'meta_data.QUEUED_PARENT_TRANSACTION',
        operator: 'eq',
        value: '<queued_parent_transaction_id>',
      },
    ],
  },
  'transactions',
);
```

```go Go wrap
results, _, _ := client.Transaction.Filter(blnkgo.FilterParams{
    Filters: []blnkgo.Filter{
        {
            Field: "meta_data.QUEUED_PARENT_TRANSACTION",
            Operator: blnkgo.OpEqual,
            Value: "<queued_parent_transaction_id>",
        },
    },
})
```

```python Python wrap
response = blnk.search.filter(
  {
    "filters": [
      {
        "field": "meta_data.QUEUED_PARENT_TRANSACTION",
        "operator": "eq",
        "value": "<queued_parent_transaction_id>",
      },
    ],
  },
  "transactions",
)
```

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

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.

<Tip>
Use `atomic: true` when a partial result is not acceptable, such as settling an invoice where every contributor must cover its share, or paying out a split where every recipient must succeed.
</Tip>

<RelatedTopics
  items={[
    { title: "Dry-run transactions", href: "/transactions/dry-run" },
    { title: "Create inflight", href: "/transactions/inflight/create-inflight#record-split-inflight-transaction" },
    { title: "Record a transaction", href: "/transactions/single-transaction" },
    { title: "Split transactions", href: "/reference/split-transactions" },
    { title: "Precision", href: "/transactions/precision" },
  ]}
/>