Available in version 0.9.0 and later.

Overview

The Bulk Transaction API enables you to process multiple transactions within a single request. It offers two processing options: atomic processing, where all transactions either succeed or fail as a unit, and independent processing, where each transaction is handled separately.

Additionally, the API supports asynchronous processing to efficiently manage large batches of transactions.


Creating bulk transactions

To process multiple transactions in a single request, call the Bulk Transactions endpoint.

POST http://YOUR_BLNK_INSTANCE_URL/transactions/bulk

Request body

{
  "atomic": true,
  "inflight": true,
  "run_async": true,
  "transactions": [
    {
      "amount": 358.90,
      "precision": 100,
      "reference": "unique_reference_1",
      "description": "Transaction description",
      "currency": "NGN",
      "source": "@source_account",
      "allow_overdraft": true,
      "destination": "@destination_account"
    },
    {
      "amount": 358.90,
      "precision": 100,
      "reference": "unique_reference_2",
      "description": "Transaction description",
      "currency": "NGN",
      "source": "@source_account",
      "allow_overdraft": true,
      "destination": "@destination_account"
    }
  ]
}
FieldTypeRequiredDescription
atomicBooleanYesWhen true, either all transactions succeed or all fail. When false, transactions are processed independently.
inflightBooleanYesWhen true, transactions are created in INFLIGHT status and require a separate commit. When false, transactions are processed immediately.
run_asyncBooleanNoWhen true, processing happens in the background and results are delivered via webhook. When false or not provided, processing happens synchronously and results are returned in the response.
transactionsArrayYesArray of transaction objects.

Synchronous response

When run_async is false:

{
  "batch_id": "bulk_c62f200b-905f-4983-a349-cadd279234aa",
  "status": "applied | inflight",
  "transaction_count": 4
}

Asynchronous response

When run_async is true:

{
  "batch_id": "bulk_c62f200b-905f-4983-a349-cadd279234aa",
  "status": "processing",
  "message": "Bulk transaction processing started"
}

Commit or void bulk inflight

To commit or void all transactions in a batch:

PUT http://YOUR_BLNK_INSTANCE_URL/transactions/inflight/{batch_id}
Request body
{
  "status": "commit | void"
}

Webhook notifications

When using run_async: true, the API sends webhook notifications upon completion or failure.

Webhook structure

The webhooks follow this structure:

{
  "event": "bulk_transaction.applied",
  "data": {
    "batch_id": "bulk_c62f200b-905f-4983-a349-cadd279234aa",
    "status": "applied",
    "transaction_count": 4,       
    "error": "error message",     
    "timestamp": "2025-03-02T15:30:45+01:00"
  }
}
FieldTypeDescription
eventStringName of event. Can be bulk_transaction.applied, bulk_transaction.inflight, or bulk_transaction.failed.
batch_idStringSpecifies the id of the batch transaction.
statusStringStatus of the batch transaction. Can be applied, inflight, or failed.
transaction_countStringNumber of transactions in the batch. Only included for successful cases.
errorStringError message. Only included for failure cases.
timestampStringSpecifies the date & time when the batch transaction was completed.
{
  "event": "bulk_transaction.applied",
  "data": {
    "batch_id": "bulk_c62f200b-905f-4983-a349-cadd279234aa",
    "status": "applied",
    "transaction_count": 4,
    "timestamp": "2025-03-02T15:30:45+01:00"
  }
}

Usage examples

Synchronous processing

Process multiple transactions atomically (all or nothing):

Request
{
  "atomic": true,
  "inflight": false,
  "transactions": [
    {
      "amount": 100.00,
      "precision": 100,
      "reference": "tx_001",
      "description": "First transaction",
      "currency": "NGN",
      "source": "@account1",
      "destination": "@account2"
    },
    {
      "amount": 50.00,
      "precision": 100,
      "reference": "tx_002",
      "description": "Second transaction",
      "currency": "NGN",
      "source": "@account2",
      "destination": "@account3"
    }
  ]
}

Asynchronous processing

Process a large batch of transactions in the background:

{
  "atomic": true,
  "inflight": false,
  "run_async": true,
  "transactions": [
    {
      "amount": 100.00,
      "precision": 100,
      "reference": "tx_001",
      "description": "First transaction",
      "currency": "NGN",
      "source": "@account1",
      "destination": "@account2"
    },
    {
      "amount": 75.00,
      "precision": 100,
      "reference": "tx_999",
      "description": "Last transaction",
      "currency": "NGN",
      "source": "@account5",
      "destination": "@account6"
    }
  ]
}

Inflight transactions

1

Create inflight transactions

{
  "atomic": true,
  "inflight": true,
  "transactions": [
    {
      "amount": 100.00,
      "precision": 100,
      "reference": "tx_003",
      "description": "First transaction",
      "currency": "NGN",
      "source": "@account1",
      "destination": "@account2"
    },
    {
      "amount": 50.00,
      "precision": 100,
      "reference": "tx_004",
      "description": "Second transaction",
      "currency": "NGN",
      "source": "@account2",
      "destination": "@account3"
    }
  ]
}
2

Later, commit the batch

PUT http://YOUR_BLNK_INSTANCE_URL/transactions/inflight/bulk_c62f200b-905f-4983-a349-cadd279234aa
{
  "status": "commit"
}

Error handling

Failed atomic transactions (synchronous)

When using atomic: true with inflight: false and run_async: false, if any transaction in the batch fails, all previously processed transactions will be automatically refunded, and you’ll receive an error response like this:

{
  "batch_id": "bulk_4192d961-5b0e-46ca-bf2f-9386763057f8",
  "error": "failed to queue transaction 1 (Reference: ref001, Source: @account1, Destination: @account2, Amount: 50.00): transaction validation failed: reference ref001 has already been used. All transactions in this batch have been refunded."
}

Failed atomic transactions (asynchronous)

When using atomic: true with run_async: true, if any transaction fails, all transactions will be rolled back, and you’ll receive a webhook notification with an error message containing the rollback status:

{
  "batch_id": "bulk_4192d961-5b0e-46ca-bf2f-9386763057f8",
  "status": "failed",
  "error": "failed to queue transaction 2 (Reference: ref002, Source: @account1, Destination: @account2, Amount: 75.50): transaction validation failed: insufficient balance. All transactions in this batch have been refunded.",
  "timestamp": "2025-03-02T15:30:45Z"
}

Failed atomic inflight transaction

When using atomic: true with inflight: true, if any transaction in the batch fails during the inflight creation phase, all previously created inflight transactions will be automatically voided, and you’ll receive an error response (or webhook for async) like this:

{
  "batch_id": "bulk_0813d39e-7ead-406b-83de-51eb1975357c",
  "error": "failed to queue transaction 1 (Reference: ref003, Source: @account1, Destination: @account2, Amount: 25.00): transaction validation failed: reference ref003 has already been used. All transactions in this batch have been voided."
}

Failed non-atomic transactions

When using atomic: false, if a transaction in the batch fails, only that transaction and the subsequent transactions in the sequence will fail; all previous transactions that succeeded before the failed one will remain applied in your ledger.

You’ll receive an error response (or webhook for async) like this:

{
  "batch_id": "bulk_2adde6a2-87b9-4ef1-ab10-8c5f1a82083c",
  "error": "failed to queue transaction 1 (Reference: ref004, Source: @account1, Destination: @account2, Amount: 125.00): transaction validation failed: reference ref004 has already been used. Previous transactions were not rolled back."
}

Important notes

  1. When atomic is true, transactions are processed in the order provided in the request.
  2. Each transaction’s reference must be unique.
  3. When run_async is true, processing happens in the background and you’ll receive an immediate response with a batch ID.
  4. For large transaction batches, using run_async: true is recommended to avoid timeout issues.
  5. Webhook notifications for async processing contain the same detailed error information as synchronous responses, including rollback status.

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.

Sign up on Blnk Cloud

Connect your Blnk Ledger and explore advanced features (access control & collaboration, anomaly detection, secure storage & file management, etc.) in one intuitive dashboard.