Post-fund your integration with Dynamic ReservesPrivate preview
Learn how to use dynamic reserves to post-fund card spend.
Caution
This API is currently in beta. Field names or high-level concepts might change with later releases. To get access to the Dynamic Reserves APIs, pass the following header in all API requests: Stripe-Version: <your stripe version>;issuing_
Dynamic reserves enable platforms to adjust their own credit limits in real-time to manage cash between Stripe and the funds available for authorization. This feature allows you to:
- Control capital usage and minimize funding costs
- Control limits that determine authorization availability
- Use Stripe to manage unexpected volatility Your connected accounts can accrue a negative Issuing balance on card spend and post-fund Stripe later. You can fund your Issuing balance after card the network captures authorizations (typically 1 day after the authorization is created) instead of pre-funding your Issuing balance before any card spend occurs. Each day, Stripe notifies you of how much you owe, and you can send a same-day wire to fund Stripe before the deadline. You must fund Stripe by the deadline (typically 20:00 UTC) to avoid late fees and additional penalties.
Connect
If you’re post-funding a Connect platform, your connected account behavior is the same as described in:
The relationship between your platform and your connected accounts doesn’t change. The primary difference is that instead of the need to pre-fund the aggregate spend of your connected accounts, you can post-fund spend.
Before you begin
- Establish a reserve, accessed only in the event of operational failure.
- Send wires from your bank.
Card program configuration
Stripe configures a CreditPolicy for your platform or direct card program, which contains information about your payment obligations and terms. Your card program CreditPolicy differs from the CreditPolicy that you set on your connected accounts. Stripe sets and controls your card program CreditPolicy, which defines the following fields:
current_: The maximum aggregate amount that can be spent across all of your connected accounts (or account, in the case of a Direct user). We calculate theexposure_ limit_ amount current_based on the combination ofexposure_ limit_ amount funded_andreserve_ amount reserve_values using the following equation: current_exposure_limit_amount = MIN [(funded_reserve_amount * reserve_multiplier), maximum_exposure_limit]multiplier reserve_: The amount that themultiplier_ decimal funded_is multiplied by to determine thereserve_ amount current_. Theexposure_ limit_ amount reserve_is determined at the start of the post-funding program.multiplier_ decimal max_: The maximum aggregate amount that can be spent across all of your connected accounts (or account, in the case of a Direct user). Your maximum exposure limit is equal to a fixed value, set by Stripe, and yourexposure_ limit_ amount funded_.reserve_ amount funded_: Corresponds to the total reserves you have posted with Stripe.reserve_ amount exposure_: The three-letter currency code for thelimit_ currency current_andexposure_ limit_ amount max_.exposure_ limit_ amount
Stripe charges a fee if you spend above your funded_, exceed your current_, or are late in paying a funding_. Although Stripe permits you to spend above your current_ up to your max_, this is emergency capital rather than funding that you use.
For example, if your funded_ is 1,000 USD, your reserve_ is 2.0x, your current_ is 2,000 USD, and your max_ is 3,000 USD:
- Stripe charges you a “credit usage” fee for spend between 1,000 USD and 2,000 USD.
- Stripe charges a higher “emergency capital” fee for spend between 2,000 USD and 3,000 USD.
- Stripe declines transactions above 3,000 USD.
To retrieve the details of your card program CreditPolicy, call the GET CreditPolicy API endpoint:
curl https://api.stripe.com/v1/issuing/credit_policy -u "sk_***:" -H "Stripe-Version: 2024-06-20; issuing_credit_beta=v2"
See the following example response:
{ "livemode": true, "current_exposure_limit_amount": 11359999920 , "reserve_multiplier_decimal": "2.4", "max_exposure_limit_amount": 13133333300, "funded_reserve_amount": 4733333300, // other fields }
Stripe applies any changes it makes to the CreditPolicy after T+2 business days at 20:00 UTC. The credit_ attribute represents this timestamp.
curl https://api.stripe.com/v1/issuing/credit_policy -u "sk_***:" -H "Stripe-Version: 2024-06-20; issuing_credit_beta=v2"
See the following example response:
{ "livemode": true, "upcoming_attributes": { "current_exposure_limit_amount": 11359999920, "reserve_multiplier_decimal": "2.4", "max_exposure_limit_amount": 13233333300, "funded_reserve_amount": 4733333300, "effective_at": 1729195200 // 2024-10-17 20:00:00 +0000 UTC } }
Only the fixed portion of the max_ is subject to a T+2 business day delay. The max_ isn’t a Stripe-initiated change and updates dynamically based on your funded reserve.
For example, if you request Stripe to increase the fixed portion of your max_ by 1,000 USD, this change takes effect after T+2 business days. However, if you increase your funded_ by 1,000 USD, your max_ changes dynamically in real-time.
Card program obligation
While your CreditPolicy defines the overall parameters of your postfunding program, your FundingObligation represents your current obligation to Stripe for card spend across all of your connected accounts, or your account if you’re a Direct user.
Every morning, Stripe sends an issuing_ webhook event containing the FundingObligation that you owe Stripe. For any given FundingObligation, the amount_ value represents the amount you owe that day.
{ "id": "icfo_123", "amount_total": 95000000, // minor units "amount_outstanding": 95000000, // minor units "amount_paid": 0, "currency": "usd", "status": "unpaid", "due_at": "timestamp_on_t1", "paid_at": "nil", "owed_to": "stripe", "finalized_at": "timestamp_on_t2", "grace_period_ends_at": "timestamp_on_t3", …, }
Late payments
Each FundingObligation contains a due_ field that indicates when the FundingObligation is due.
{ "id": "icfo_123", "amount_total": 95000000, // minor units "amount_outstanding": 95000000, // minor units "amount_paid": 0, "currency": "usd", "status": "unpaid", "due_at": "timestamp_on_t1", "paid_at": "nil", "owed_to": "stripe", "finalized_at": "timestamp_on_t2", "grace_period_ends_at": "timestamp_on_t3", …, }
If you fail to pay your FundingObligation when it’s due, the following occurs:
- Stripe withdraws from your reserve to cover the past-due amount.
- If you have a sufficient balance in your reserve, you receive a
FundingObligation.webhook showing the Funding Obligation’s status changed toupdated paid. If you have an insufficient reserve balance to fully cover theFundingObligation, you receive aFundingObligation.webhook showing the Funding Obligation’s status changed toupdated past_and adue grace_timestamp of 20:00 UTC on the next business day.period_ ends_ at - When a reserve pull occurs, the
credit_andpolicy. current_ exposure_ limit_ amount credit_reflect the updated exposure limit based on the new issuing credit reserve balance. You receive a webhook notifying you of the new exposure limits (current and max).policy. max_ exposure_ limit_ amount - You also receive an email notifying you of the reserve pull and
past_due FundingObligation. - If your
FundingObligationbecomes past due, Stripe charges a late payment fee as stated in your contract with Stripe. - It’s your responsibility to make sure your
current_is larger than your negative Issuing balance. Be prepared to initiate a reserve top-up if necessary after a withdrawal initiated by Stripe. Failure to do so results in authorization declines if your spend exceeds yourexposure_ limit max_.exposure_ limit
Multiple late payments over time can lead to additional penalties on your platform, such as a decrease in your card program exposure limit. You must remediate an unpaid FundingObligation within one additional business day, or Stripe might begin declining transactions.
Identify how much you owe Stripe
Stripe generates a FundingObligation for your card program every day, including weekends and holidays. To keep your account current and avoid late fees and penalties, calculate your total amount owed each day based on the amount_ value for all unpaid and past_ FundingObligations using a formula:
total_ = sum(unpaid FundingObligations)1 + sum(past_due FundingObligations)2 |
1sum(unpaid FundingObligations) is the total of all FundingObligations with status=unpaid.
2sum(past_due FundingObligations) is the total of all FundingObligations with status=past_.
Manage funding obligations and due dates
When Stripe generates a FundingObligation on a weekday, it’s due that same day. If Stripe generates a FundingObligation on a weekend or holiday, it’s due on the next business day. For a typical weekend, this means you’ll have three FundingObligations due on Monday. Make sure that you accurately aggregate your total amount owed to Stripe to make timely payments.
Fund Stripe to meet obligations
To fund Stripe daily based on the due_ timestamp for the total amount you owe, use any of the following methods:
- Same-day wires: Initiate a same-day wire from your bank to your Stripe Issuing balance to pay off a
FundingObligation. Use the FundingInstructions API to retrieve the account and routing number for your Issuing balance, and use that as the destination for the wire. - Balance transfers: In the US, you can move money instantly from your Stripe payments balance to your Issuing balance and use it to pay off your
FundingObligationthrough the Stripe Dashboard or the API (contact Stripe to gain access to the API). - Existing pre-funded Issuing balance: In the US, Stripe applies any pre-funded or over-funded amounts from the previous day to your next
FundingObligation. In EMEA, prefunding your Issuing balance isn’t allowed for charge card users; instead, any positive Issuing balance is transferred to your Issuing Reserve.
After Stripe receives the full amount owed on the FundingObligation, we update its status and amounts, and trigger an issuing_ webhook event.
{ "id": "icfo_123", "amount_total": 95000000, // minor units "amount_outstanding": 0, "amount_paid": 95000000, // minor units "currency": "usd", "status": "paid", "due_at": "timestamp_on_t1", "paid_at": "timestamp_of_payment", "owed_to": "stripe", "grace_period_ends_at": "timestamp_on_t2" …, }
If you pay only a portion of the total amount due, Stripe updates the amounts but keeps the status as unpaid. The issuing_ webhook event reflects this information.
{ "id": "icfo_123", "amount_total": 95000000, // minor units "amount_outstanding": 3000000, // minor units "amount_paid": 92000000, // minor units "currency": "usd", "status": "unpaid", "due_at": "timestamp_on_t1", "paid_at": "timestamp_of_payment", "owed_to": "stripe", "grace_period_ends_at": "timestamp_on_t2" …, }
If the balance remains unpaid past the due_ deadline, the status changes to past_, which triggers another issuing_ webhook event and initiates a reserve withdrawal.
Get transactions for a funding obligation
Retrieve the list of transactions that contribute to a FundingObligation by including one of the following parameters in the List all transactions API request:
- funding_obligation_for_account for Direct users.
- funding_obligation_for_platform for Platform users.
To retrieve transactions for direct charges:
See the following example response:
{ "object": "list", "url": "/v1/issuing/transactions", "has_more": false, "data": [ { "id": "ipi_123", "object": "issuing.transaction", // various other fields "funding_obligation_for_platform": null, "funding_obligation_for_account": "ifo_123", // various other fields }, { "id": "ipi_123", "object": "issuing.transaction", // various other fields "funding_obligation_for_platform": null, "funding_obligation_for_account": "ifo_123", // various other fields }, {...} ] }
Query funding obligations for connected accounts
Connect platforms must include the Stripe-Account header with a connected account ID. Use funding_obligation_for_platform to query by the platform’s FundingObligation, or use funding_obligation_for_account if you know a connected account’s FundingObligation.
See the following example response:
{ "object": "list", "url": "/v1/issuing/transactions", "has_more": false, "data": [ { "id": "ipi_123", "object": "issuing.transaction", // various other fields "funding_obligation_for_platform": "ifo_123", "funding_obligation_for_account": "ifo_456", // various other fields }, { "id": "ipi_123", "object": "issuing.transaction", // various other fields "funding_obligation_for_platform": "ifo_123", "funding_obligation_for_account": "ifo_789", // various other fields }, {...} ] }
Manage your reserve
You must post a reserve (referred to as “Collateral” in your program agreement) with Stripe to use capital-efficient post-funded card spend. Stripe holds the reserve in an account that it owns and controls as security against funds owed, drawing from it to pay off any late or unpaid FundingObligations. Stripe also uses the reserve amount as the basis for current_ and max_ calculations. You can dynamically adjust your reserve balance by adding more funds when you expect higher spend, such as before a long weekend, and reducing your reserve when your projected spend is lower.
You might incur a late fee if your funding obligation becomes past_ and your reserve isn’t sufficient to cover the amount. Additionally, a pattern of past_ funding obligations can result in Stripe reducing your platform’s reserve_ or the fixed portion of your max_. To avoid this, fund your Stripe Issuing balance through wires or balance transfers before the due_ timestamp on the FundingObligation for your credit integration.
Identify your reserve components
You can identify the reserve_, max_, funded_, and current_ in your CreditPolicy. Use these factors, along with your expected future spend, to determine the appropriate funded_.
curl https://api.stripe.com/v1/issuing/credit_policy -u "sk_***:" -H "Stripe-Version: 2024-06-20; issuing_credit_beta=v2"
See the following example response:
{ "current_exposure_limit_amount": 11359999920 , "reserve_multiplier_decimal": "2.4", "max_exposure_limit_amount": 13133333300, "funded_reserve_amount": 4733333300, // other fields }
Add funds to your reserve balance
Stripe supports pushing funds into the reserve balance. You might do this to increase your current_ ahead of increased spend or after Stripe withdraws from your reserve to pay a past_ FundingObligation. You can find the account details for your reserve in the FundingInstruction, which contains bank account and routing information for you to originate a funds transfer.
Caution
This is a different set of instructions than what Stripe uses to fund your Issuing balance. The destination_ for your reserve funding instructions are set as issuing_.
See the following example response:
{ "id": "fi_XYZ", "object": "funding_instruction", "livemode": "true", "currency": "usd", "bank_transfer": { "type": 'us_bank_account', "country": "US", "financial_addresses": [{ "supported_networks": ['ach', 'domestic_wire_us'], "type": 'aba', "aba": { "account_number": "546475644", "bank_name": "Wells Fargo", "routing_number": "123456" }, }] }, "destination_balance": "issuing_credit_reserved", "funding_type": "bank_transfer", }
Funds transferred through a wire or ACH credit to the bank account retrieved from the FundingInstructions are deposited into your reserve balance. When the funds arrive in your account, Stripe sends a topup. webhook notification along with an issuing_ webhook event that represents your updated exposure limit and funded reserve amount. Stripe doesn’t add additional delays to the wire, and generally follows standard wire timelines.
{ "id": "tu_XYZ", "object": "topup", "amount": 9000, "balance_transaction": "txn_123", "destination_balance": "issuing_credit_reserved" "created": 123456789, ... }
Check your reserve balance
You can use the Balance API to check your reserve balance at any time:
See the following example response:
{ "object": "balance", "available": [ ... ], "connect_reserved": [ ... ], "issuing": { ... }, "issuing_credit_reserved": [ { "amount": 9000, "currency": "usd" } ], "livemode": true, "pending": [ ... ] }
Manage past due funding obligations
If you have a FundingObligation that’s past_, Stripe first withdraws from your reserve to pay off the FundingObligation. Stripe uses the issuing_ webhook to notify you, and updates the FundingObligation object to show the amount paid off by your reserve. If your reserve can’t fully cover the amount_ on the FundingObligation, the FundingObligation remains past_. See Past Due Funding Obligations for more details and implications.
The following shows a FundingObligation that’s fully paid by the reserve:
{ "id": "icfo_123" "amount_total": 95000000, // minor units "amount_outstanding": 0, "amount_paid": 95000000, // minor units "amount_paid_from_reserve": 95000000, // minor units "currency": "usd", "status": "paid", "due_at": "timestamp_on_t1", "paid_at": "timestamp_of_payment_with_reserve", "owed_to": "stripe", "grace_period_ends_at": "timestamp_on_t2", …, }
Stripe provides a BalanceTransfer object and associated BalanceTransactions to represent the automated transfer of funds from your reserve balance to your Issuing balance.
See the following example response:
{ "id": "btr_1MinsBCq7itcH1tbDkk4sY8w", "object": "balance_transfer", "amount": 10000, "currency": "usd", "destination_balance": { "issuing": { "balance_transaction": "txn_123_inbound" }, "type": "issuing" }, ... "source_balance": { "issuing_credit_reserved": { "balance_transaction": "txn_123_outbound" }, "type": "issuing_credit_reserved" } }
See the following example response:
{ "id": "txn_123_outbound", "object": "balance_transaction", "amount": 100, "currency": "usd", ... "type": "balance_transfer_outbound", "balance_type": "issuing_credit_reserved", "reporting_category": "issuing_credit_reserved_funds" } { "id": "txn_123_inbound", "object": "balance_transaction", "amount": 100, "currency": "usd", ... "type": "balance_transfer_inbound", "balance_type": "issuing", "reporting_category": "issuing_credit_reserved_funds" }
Pay out funds from your reserve balance
Stripe supports paying out funds from your reserve balance. You might do this to lower your current_ ahead of decreased spend to be more capital efficient. You can use the v1/payout endpoint with source_ set to issuing_.
Caution
This is a different set of instructions than what Stripe uses to fund your Issuing balance. The destination_ for your reserve funding instructions are set as issuing_.
curl https://api.stripe.com/v1/payouts \ -u "sk_**:" \ -d amount=100000000 \ -d currency=usd \ -d source_type=issuing_credit_reserved
After you create a payout, Stripe immediately sends a webhook indicating that the issuing credit reserve balance reflects the payout created. See the following example response:
curl https://api.stripe.com/v1/balance -u "sk_**:" -H "Stripe-Version: 2024-06-20; issuing_credit_beta=v2" { // other fields, "issuing_credit_reserved": [ { "amount": 1233333300, "currency": "usd" } ], }
The credit policy object reflects the latest exposure limit, and you receive an issuing_ webhook informing you of the new exposure limits.
See the following example response:
curl https://api.stripe.com/v1/issuing/credit_policy -u "sk_***:" -H "Stripe-Version: 2024-06-20; issuing_credit_beta=v2" { "object": "issuing.credit_policy", "current_exposure_limit_amount": 11359999920 , "reserve_multiplier_decimal": "2.4", "max_exposure_limit_amount": 13133333300, "funded_reserve_amount": 4733333300, // other fields }
See the following example response:
{ "object": { "object": "issuing.credit_policy", "credit_period_ends_on_days": null, "credit_period_interval": "day", "credit_period_interval_count": 1, "current_exposure_limit_amount": 240, "days_until_due": 0, "exposure_limit_currency": "usd", "funded_reserve_amount": 200, "last_effective_attributes": { "credit_period_ends_on_days": null, "credit_period_interval": "day", "credit_period_interval_count": 1, "current_exposure_limit_amount": 103, "days_until_due": 0, "effective_until": 1728763199, "max_exposure_limit_amount": 103, "reserve_multiplier_decimal": "1.300", "status": "active" }}}
In the example above, if you submit your payout request from Tuesday through Friday before 10:00 UTC, the wire is disbursed by the end of the same business day. If you submit your payout request after that cutoff, it’s most likely disbursed by the end of the next business day. On Mondays or following a holiday weekend, an additional one-day delay occurs. Even if you initiate the payout before 10:00 UTC, the wire is disbursed by the end of the day after the next business day.
Card program available spend
To add a field or balance that shows the amount your card program has available to spend, use the following formula:
available credit = max_ + issuing balance (issuing balance might be negative because of additional spend allowed by the exposure limit) |
Authorization declines when post-funding
When post-funding, authorizations might be declined due to the following:
FundingObligationsispast_due - You exceed your
max_exposure_ limit_ amount
Declines for past due funding obligations
Stripe declines authorizations when a FundingObligation is past_ beyond the grace period defined in the grace_ timestamp of the FundingObligation. Refer to the following example to find the grace_:
{ "id": "icfo_123", "amount_total": 95000000, // minor units "amount_outstanding": 95000000, // minor units "amount_paid": 0, "currency": "usd", "status": "past_due", "due_at": "timestamp_on_t1", "paid_at": nil, "owed_to": "stripe", "grace_period_ends_at": "timestamp_on_t2", ..., }
If the grace period has passed, Stripe Issuing declines authorizations and sends issuing_ events with the following:
{ "id": "iauth_123", "object": "issuing_authorization", "approved": false, ..., "status": "closed", "request_history": [ { "amount": 100, // minor units "approved": false, "reason": "past_due_funding_obligation_to_stripe", ..., } ] }
Declines because of the maximum exposure limit
Stripe immediately begins declining authorizations when you meet or exceed your max_. You can add reserves to increase the limit and avoid declines.
If you exceed your max_, Stripe Issuing declines authorizations and sends issuing_ events with the following:
{ "id": "iauth_123", "object": "issuing_authorization", "approved": false, ..., "status": "closed", "request_history": [ { "amount": 100, // minor units "approved": false, "reason": "platform_exposure_limit_exceeded", ..., } ] }
Manage post-funding email notifications for your platform
Stripe sends several mandatory email notifications for post-funding. You can manage and set thresholds for the following email notifications in your Balance notification settings:
- Notification of a Stripe-initiated reserve withdrawal because of an unpaid
FundingObligation. - Notification of a
FundingObligationbecomingpast_if your reserve is insufficient to cover it.due - Notification that your negative Issuing balance exceeded 90% of your
max_.exposure_ limit_ amount
Optionally, you can configure the threshold in the Dashboard to receive notifications when your platform’s negative Issuing balance exceeds a percentage threshold of your current_.