Balance transfers
The Balance Transfers API moves funds between two accounts on your platform in a single, atomic operation. Every transfer is bilateral: one account is debited (the source) and one is credited (the destination).
Use it whenever value moves between accounts that already hold a balance with Rootline, without touching an external bank: charging your SaaS subscription fee, paying a referral bonus to a partner, or paying a supplier.
Use cases
A transfer is directional: money flows from the debited account to the credited account. The use case is simply which account sits on which side.
| Use case | Money flows | Debited (source) | Credited (destination) |
|---|---|---|---|
| Subscription | Merchant to platform | The merchant | The platform |
| Incentive or cashback | Platform to merchant | The platform | The merchant |
| Referral bonus | Platform to reseller | The platform | The reseller |
| Merchant to merchant sale | Merchant to merchant | Merchant A | Merchant B |
| Manual correction | Either direction | The charged account | The credited account |
Any movement between two accounts on your platform fits this shape.
Operations
Balance transfers live under the accounting service.
Endpoints
| Environment | Base URL |
|---|---|
| Staging | https://accounting-api.staging.rootline.com/v1/balance-transfers |
| Production | https://accounting-api.rootline.com/v1/balance-transfers |
Create a balance transfer
Send an Idempotency-Key header with a unique value per transfer so a retry never creates a duplicate.
A successful create returns 200 OK with the transfer and its two lines:
The debit line is -40.00 and the credit line is +40.00. Charging a fee on a transfer is covered in Fees.
Retrieve a balance transfer
Returns the same shape as create, including both lines.
List balance transfers
Newest first, paginated:
Walk forward by passing the previous response's next_page_token back as ?page_token=<token>. Treat the token as opaque: pass it back unchanged, do not parse it.
How a balance transfer is structured
A balance transfer is one parent object with two lines on it. The parent (id prefixed btr_) records the overall transfer. The two lines, exposed as the debit and credit objects, record the movement against each account: the debit line is negative (funds leaving) and the credit line is positive (funds arriving).
You describe the transfer once, with a debit and a credit instruction, and Rootline produces the matching pair of lines. Because each line is its own object with its own id (prefixed btrline_), you can scope access to it independently: a merchant can be granted access to just its own line, without seeing the counterparty's line or the parent object.
Balance transfer
| Property | Type | Description |
|---|---|---|
id | string | Unique identifier, prefixed btr_. |
status | string | Lifecycle state of the transfer, for example succeeded. |
account_id | string | The account that initiates the transfer, almost always your platform account. It must be permitted to initiate balance transfers; a regular merchant account cannot. Rootline's processing fee is booked here, and when both sides are named this account is only the requestor, not a party to the movement. |
amount | money | The transfer magnitude, as a positive value. See Amounts and currency. |
reference | string | Your own reference for the transfer. |
description | string, optional | Free text description. |
debit | object | The debit line, the account funds are taken from. See Balance transfer line. |
credit | object | The credit line, the account funds are paid to. See Balance transfer line. |
created_at | string | Creation timestamp (ISO 8601, UTC). |
On create you may omit one of debit or credit. The missing side defaults to the initiating account_id: omit credit and the platform is credited (the merchant on debit pays the platform), omit debit and the platform is debited (the platform pays the merchant on credit). That defaulted line also inherits the transfer's reference.
Balance transfer line
Each line is returned inside the debit or credit property. On create you supply account_id, and optionally reference and fees; Rootline fills in the id, the signed amount, and the status.
| Property | Type | Description |
|---|---|---|
id | string | Unique identifier, prefixed btrline_. |
account_id | string | The account this line books against. It cannot equal the other side's account_id. |
amount | money | The gross movement for this line, signed: negative on the debit line, positive on the credit line. The net effect on the account is the gross minus any fees on the line. |
reference | string, optional | Your own reference for this side. Left empty it stays empty; only a defaulted side inherits the transfer's reference. |
fees | array, optional | Platform fees charged on this line, always expressed as positive amounts. Allowed only when account_id is not the initiating account. See Fees. |
status | string | Lifecycle state of the line, for example succeeded. |
Amounts and currency
Amounts are an object with a string quantity and an ISO 4217 currency:
The quantity is a string to preserve exact decimal precision, and must be a whole number of minor units. For EUR that is at most two decimals; "9.999" is rejected.
Validation and errors
Validation is synchronous. A rejected request returns a 4xx with a flat error object: an error_type, a machine readable error_code, a human readable error_message, and the field that failed.
Branch on error_code and field rather than the error_message, which is written for humans and may change. Common rejections:
field | Reason |
|---|---|
account_id | The debit and credit accounts are the same. A transfer cannot be to and from one account. |
fees | A fee was placed on the initiating account's own side. The owner cannot charge itself a fee. |
account | An account in the transfer has no balance transfer service configured. The message names the account. |
Amounts with more decimal places than the currency allows, for example "9.999" in EUR, are also rejected.
Examples
Each example is a create request. The initiating account_id is the platform.
Subscription (merchant pays the platform)
Debit the merchant; omit credit so the platform is credited.
Incentive or cashback (platform pays a merchant)
Omit debit so the platform is debited; credit the merchant.
Merchant to merchant sale
Both sides named, so the platform is only the requestor.
Fees
Your platform can charge a fee on either side of a transfer. The fees charged are your revenue.
A fee goes in a fees array inside the debit or credit object. Each entry has a reference you choose and a rate:
A fee can only sit on a side whose account_id is not the initiating account_id. The platform cannot charge itself.
How fees affect balances
The balance transfer object carries only revenue; its own principal movement is always 0.00. The two lines carry the money movement.
The signs matter. A line's amount is the gross figure, negative on the debit line and positive on the credit line. Fees, by contrast, are always positive, even though a fee always works against the account: each fee is subtracted from its line's gross to give the net. So a fee reduces what a credited account receives and increases what a debited account pays.
The total platform revenue is summarised on the parent object; each individual fee is also reported on the line it came from.
Both sides are merchants. A platform initiated transfer of 100.00 from merchant B to merchant A, with a 1.00 fee on each side:
| Booking | Gross | Fees | Net |
|---|---|---|---|
| Balance transfer (platform) | 0.00 | 2.00 revenue | +2.00 |
| Line, merchant A (credited) | +100.00 | 1.00 | +99.00 |
| Line, merchant B (debited) | -100.00 | 1.00 | -101.00 |
Merchant A receives 100.00 less a 1.00 fee, merchant B sends 100.00 plus a 1.00 fee, and the platform keeps 2.00 of revenue while moving no principal. The net figures sum to 0.00.
The platform is one of the two sides. A 40.00 transfer where the platform is credited and the debited merchant pays a 2.00 fee:
| Booking | Gross | Fees | Net |
|---|---|---|---|
| Balance transfer (platform) | 0.00 | 2.00 revenue | +2.00 |
| Line, merchant (debited) | -40.00 | 2.00 | -42.00 |
| Line, platform (credited) | +40.00 | none | +40.00 |
The platform appears twice: as the object, recording only its 2.00 of revenue, and as the credited line, recording the 40.00 it receives. Its own line carries no fee, because it cannot charge itself. The net figures again sum to 0.00.
Rootline's fee
Separately from your platform fees, Rootline charges a fee for each balance transfer, booked against the initiating account. It appears in your settlement reporting with a fee_type of balance_transfer_fee, linked by balance_transfer_id.