Working with balances and transactions
Financial accounts have their own balance separate from the balance of the account they’re attached to (platform account or connected account). Balance
objects record the amount of funds in a financial account and their state of availability. Transaction
and TransactionEntry
objects debit or credit the funds in that balance.
Balances
A financial account has a balance of funds. The sum total of the balance isn’t always available for spending, however, as it might include pending transactions into or out of the financial account. The financial account balance contains three properties that define the availability of its funds:
cash
—funds the user can spend right now.inbound_pending
—funds not spendable yet, but that will become available at a later time. Theinbound_pending
property is reserved for future functionality and always has a value of 0.outbound_pending
—funds in the account, but not spendable because they’re being held for pending outbound flows.
Use GET /v1/treasury/financial_accounts/{{FINANCIAL_ACCOUNT_ID}}
to retrieve the balance details of a financial account with the associated ID. Provide the Stripe-Account
header if the financial account is attached to one of your connected accounts. If the financial account is attached to your platform account, don’t include the Stripe-Account
header.
If successful, the response is a FinancialAccount
object with a balance
hash that details the funds and their availability.
{ "object": "treasury.financial_account", "id": "{{FINANCIAL_ACCOUNT_ID}}", ... "balance": { // $90 is currently available for use, // with an additional $10 held in the outbound_pending sub-balance "cash": {"usd": 9000}, "inbound_pending": {"usd": 0}, "outbound_pending": {"usd": 1000} } }
Negative balances and overdrafts
As stated in our custodial account agreement, Stripe doesn’t yet offer an overdraft feature on financial accounts. If your balance is insufficient to cover transactions, Stripe rejects transactions where possible—otherwise, the account moves to a negative balance, which you then need to remediate. In other words, a 100 USD issuing authorization fails with ‘insufficient funds’ if the balance of the account is less than 100 USD. However, if you have a 50 USD balance in your financial account and pay for a 50 USD meal, the issuing authorization succeeds. If you received good service and added a 15 USD tip, the 65 USD issuing over capture succeeds and results in a negative 15 USD available balance. In this case, you need to add funds to your financial account to avoid subsequent transactions being denied with insufficient funds. If a seller or service provider on your platform (connected account) fails to bring their financial account back to a non-negative balance, you’re responsible for covering the negative amount.
Stripe emails you a monthly reminder if your platform has any associated financial accounts that have had negative balances for more than 15 days. However, you need to regularly monitor account balances and take remediation steps as soon as possible when balances go negative—don’t wait for the reminder email to begin addressing negative balances.
Note
You can have Treasury financial accounts cover negative payment balances for connected accounts using automatic debits. Refer to the Negative balances on accounts section in the Connect documentation to learn more.
Transactions
All changes to a balance have a corresponding Transaction
object that details money movements. Transactions affect only one balance and are in only one currency (currently, Stripe Treasury supports only USD).
Each transaction points to the balance-affecting money movement object, such as an OutboundTransfer, ReceivedCredit, or ReceivedDebit.
Transaction state machine
Status | State applied | Description | Transitions to |
---|---|---|---|
open | initial | This is the initial state for all transactions. The transaction results in updates to the sub-balance amounts, but the current balance isn’t affected until the transaction posts. | posted or void |
posted | terminal | Funds have successfully entered or left the account. The current balance was affected. | N/A |
void | terminal | The transaction never impacted the balance. For example, a transaction enters this state if an outbound payment was initiated but then canceled before the funds left the account. | N/A |
The available Transaction
endpoints enable you to retrieve specific transactions and list or filter transactions affecting a financial account. There are no webhooks available for transactions, but webhooks are available for the associated money movement objects (for example, OutboundPayments
).
Retrieve a transaction
Use GET/v1/treasury/transactions/{{TRANSACTION_ID}}
to retrieve the transaction with the associated ID.
If successful, the response returns the Transaction
object.
List Transactions
Use GET /v1/treasury/transactions
to list transactions for a financial account. Set the required financial_account
parameter in the body to the value of the financial account ID to retrieve transactions for. Include additional parameters to filter the results returned.
In addition to the standard set of list parameters, you can filter transactions by the following.
status
flow
- Either
created
orposted_at
, but not both
{ // Standard list parameters limit, starting_after, ending_before, // Filter by FinancialAccount, required financial_account: "{{FINANCIAL_ACCOUNT_ID}}" // Filter by status status: "open" | "posted" | "void", // Filter by flow flow: "{{FLOW_OBJECT_ID}}", // Order the results by the created or posted_at timestamps, default is `created`. // For order_by=posted_at, setting status='posted' is required order_by: "created" | "posted_at", // created can only be specified with order_by = 'created' created: {gt, gte, lt, lte}, status_transitions: { // status_transitions.posted_at can only be specified with order_by = 'posted_at' and status = 'posted' posted_at: {gt, gte, lt, lte} } }
The following request retrieves the three most recent transactions created on the financial account that have a status
of posted
.
Webhooks
There are no webhooks for transactions because the various money movements that initiate a transaction have their own webhooks.
Transaction entries
TransactionEntry
objects are the most granular view of money movements that affect a financial account balance. A single flow of money comprises multiple individual money movements, each represented by a transaction. Transactions, in turn, are an aggregation of transaction entries. For example, when initiating an outbound payment of $10.00 at time T, funds are moved from the cash
sub-balance to the outbound_pending
sub-balance. The following Transaction
object response demonstrates this initial event.
{ "id": "{{TRANSACTION_ID}}", "object": "treasury.transaction", "created": "{{T}}", ... "flow": "{{OUTBOUND_PAYMENT_ID}}", "flow_type": "outbound_payment", "status": "open", "amount": -1000, "currency": "usd",
After the outbound payment posts at time T+1, the funds are deducted from outbound_pending
and a new transaction entry is added to the transaction. The following Transaction
response demonstrates this progression.
{ "id": "{{TRANSACTION_ID}}", "object": "treasury.transaction", "created": "{{T}}", ... "flow": "{{OUTBOUND_PAYMENT_ID}}", "flow_type": "outbound_payment", "status": "posted", "amount": -1000, "currency": "usd",
As the preceding responses show, a transaction can contain multiple transaction entries. The available TransactionEntry
endpoints enable you to retrieve specific transaction entries and list or filter them for a particular transaction.
A Transaction
in the void
status won’t have any new transaction entries added to it. A Transaction
in the posted
status where all balance_impact
is to the cash
sub-balance won’t have any new transaction entries added to it, either.
Retrieve transaction entries
Use GET /v1/treasury/transaction_entries/{{TRANSACTIONENTRY_ID}}
to retrieve details for the transaction entry with the associated ID.
If successful, the response returns a TransactionEntry
object with the following form.
{ "id": "{{TRANSACTION_ENTRY_ID}}", "object": "treasury.transaction_entry", "created": "{{Timestamp}}", "livemode": false, // The FinancialAccount this transaction entry impacts. "financial_account": "{{FINANCIAL_ACCOUNT_ID}}", // The transaction that this transaction entry belongs to. "transaction": "{{TRANSACTION_ID}}", // The flow responsible for this transaction entry.
List TransactionEntries
Use GET /v1/treasury/transaction_entries
to list the transaction entries for a financial account. Set the required financial_account
parameter in the body to the value of the financial account ID to retrieve transaction entries for. Include additional parameters if you want to filter the list.
In addition to the standard set of list parameters, you can filter transaction entries by:
transaction
- Either
created
oreffective_at
, but not both
{ // Standard list parameters limit, starting_after, ending_before, // Filter by FinancialAccount, required financial_account: "fa_123" // Filter by transaction transaction: 'trxn_123', // Order the results by the created or effective_at timestamps, default is `created`. order_by: "created" | "effective_at", // created can only be specified with order_by = 'created' created: {gt, gte, lt, lte}, // effective_at can only be specified with order_by = 'effective_at' effective_at: {gt, gte, lt, lte}, }
The following request retrieves the transaction entries created before {{Timestamp}}
and orders them by created
date.
Webhooks
There are no webhooks for transaction entries because the various money movements that initiate a transaction entry have their own webhooks.