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": false,
"run_async": false,
"skip_queue": false,
"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"
}
]
}
| Field | Type | Required | Description |
|---|
atomic | Boolean | Yes | When true, either all transactions succeed or all fail. When false, transactions are processed independently. |
inflight | Boolean | Yes | When true, transactions are created in INFLIGHT status and require a separate commit. When false, transactions are processed immediately. |
run_async | Boolean | No | When 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. |
skip_queue | Boolean | No | Defaults to false. When true, transactions bypass the queue system. Learn more: Handling Hot Balances. |
transactions | Array | Yes | Array 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}
{
"status": "commit | void"
}
Retrieving transactions in a batch
When you submit a bulk transaction request, Blnk assigns each transaction in the batch its own unique transaction ID but tags them all with the same parent_transaction (which is your original batch_id).
To retrieve every transaction in that batch:
POST http://YOUR_BLNK_INSTANCE_URL/search/transactions
curl -X POST http://localhost:5001/search/transactions \
-H "Content-Type: application/json" \
-H "X-blnk-key: <api-key>" \
-d '{
"q": "<batch-id>",
"query_by": "parent_transaction"
}'
q: The batch_id returned when you created the request.
query_by: Must be set to parent_transaction.
The response will include an array of all child transactions linked to that batch_id.
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"
}
}
| Field | Type | Description |
|---|
event | String | Name of event. Can be bulk_transaction.applied, bulk_transaction.inflight, or bulk_transaction.failed. |
batch_id | String | Specifies the id of the batch transaction. |
status | String | Status of the batch transaction. Can be applied, inflight, or failed. |
transaction_count | String | Number of transactions in the batch. Only included for successful cases. |
error | String | Error message. Only included for failure cases. |
timestamp | String | Specifies the date & time when the batch transaction was completed. |
Successful webhook
Failure webhook
{
"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):
{
"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
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"
}
]
}
Later, commit the batch
PUT http://YOUR_BLNK_INSTANCE_URL/transactions/inflight/bulk_c62f200b-905f-4983-a349-cadd279234aa
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
- When
atomic is true, transactions are processed in the order provided in the request.
- Each transaction’s
reference must be unique.
- When
run_async is true, processing happens in the background and you’ll receive an immediate response with a batch ID.
- For large transaction batches, using
run_async: true is recommended to avoid timeout issues.
- 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.
Tip: Connect to Blnk Cloud to see your Core data.You can view your transactions, manage identities, create custom reports, invite other team members to collaborate, and perform operations on your Core — all in one dashboard.Check out Blnk Cloud →