Plan for insufficient EBT funds errors
Learn about FNS requirements and Forage guidelines for handling insufficient EBT funds errors.
At the beginning of every month, an EBT customer receives a set amount of EBT funds. They can check their EBT Card balance at any time via digital wallets, state websites, or receipts from EBT purchases. However, not all customers confirm their EBT balance before shopping. 10-20% of EBT transactions return insufficient funds errors.
This document outlines both FNS requirements and Forage guidelines for handling insufficient funds errors. It also includes example code for catching and handling insufficient funds errors.
If you’re building a Fully Hosted integration, then you don’t need to read this guide. The Forage Checkout UI comes with prebuilt insufficient funds error handling.
FNS requirements for insufficient funds errors
For documented requirements, the relevant FNS Online EBT Pilot Request for Volunteers (RfV) reference is noted.
- SNAP customers must be able to set the SNAP amount that they want to apply to a purchase (RfV 2.4.2.4, RfV 2.4.2.7).
- If the customer does not have enough EBT funds to complete a purchase, then the website or app must display a message that alerts the customer that the attempted amount exceeds the available card balance.
- EBT customers must be able to check their EBT Card balance somewhere on the website or app. The balance inquiry does not necessarily have to be a part of the checkout flow.
- If a customer opts to check their EBT balance before authorizing a purchase, then they need to enter their EBT Card PIN twice.
- PINs cannot be stored for future use, and FNS mandates that a customer enters their PIN for every transaction. A balance inquiry and a charge count as two distinct transactions (RfV 2.4.1.1).
Forage guidelines for insufficient funds errors
After meeting mandatory, nonnegotiable FNS requirements, consider the following design principles when planning how to handle insufficient funds errors.
Minimize friction for 80% of customers that aren’t affected. If you require a balance inquiry before checkout, for example, then even customers with enough funds have to enter their PIN twice (once for the balance inquiry, and again to authorize the purchase). Aim for solutions that reduce disruptions to your checkout flow for most customers.
Decrease the likelihood of an insufficient funds error as early in the shopping journey as possible. Offer a balance inquiry option before checkout, or from a customer’s account settings page. Building a separate flow for balance inquiries can be more engineering intensive, so balance this principle with your goal timeline and available developer resources.
Reduce upfront development effort. Define an MVP, collect data, and iterate.
The recommend user experience (UX) below strikes the optimal balance of these principles for most merchants.
Recommended UX
Flow for optional balance inquiry
- A customer arrives at checkout. They add their EBT Card as a payment method.
- The merchant sets an initial SNAP amount to apply to the cart, based on the value of the SNAP eligible items.
- The customer can change the SNAP amount, if they like. The amount can range between $0 and the total SNAP value of the cart (the initial amount).
- The customer can check their EBT Card balance, if they like. If they opt to check their account balance, then:
- They need to enter their PIN to authorize the balance inquiry.
- The merchant can choose to set the SNAP amount to apply to equal the EBT Card balance, if the cart total exceeds the available funds.
- The customer enters their EBT Card PIN to authorize the charge.
Flow for insufficient funds errors
- The Forage API returns an error in the case of insufficient funds.
- The merchant alerts the customer of the error.
- The merchant sets the SNAP amount to apply based on the remaining balance.
- The merchant sends a server-side GET to
/payment_methods/{payment_method_ref}/
to retrieve the available balance. - The customer is able to change the amount, if they like.
- The merchant sends a server-side GET to
- The customer reenters their PIN to authorize the transaction.
Note that there is no need to create a new Payment
object in the case of insufficient funds errors. Apply the customer's authorization to the original payment_ref
.
Insufficient funds errors and split tender
If you’re handling split tender, then consider whether to structure your implementation to minimize payment processing time or costs in the case of insufficient funds.
To minimize payment processing time, charge EBT Cards and other payment methods at the same time. Then, if one fails, reverse all payments, even the ones that succeeded.
To minimize costs, charge payments like EBT that do not have an associated auth fee first. If EBT fails, then you avoid the credit card auth fee. If EBT succeeds, then continue to authorize the other payment methods.
Alternative UX
Require all customers to check their EBT Card balance at checkout.
This minimizes insufficient funds errors, but creates a lot of friction for the 80% of customers that have enough EBT funds to complete their purchase.
Offer a balance check in a customer’s account settings instead of at checkout.
This is the quickest implementation option from an engineering perspective, but might bury the feature for customers who want to check their balance before checkout.
Example code
If a customer’s available EBT Card balance is insufficient to complete a purchase, then the call to the Forage capturePayment
method fails. The complete error object takes the following shape:
{
httpStatusCode: 400,
code: 'ebt_error_51',
message: 'Insufficient funds - Insufficient Funds. Remaining balances are SNAP: 1.23, EBT Cash: 4.56',
details: {
snapBalance: 1.23,
cashBalance: 4.56
}
}
The message in the case of an unavailable account balance looks like:
{
httpStatusCode: 400,
code: 'ebt_error_51',
message: 'Insufficient funds - Insufficient Funds. Remaining balances are SNAP: null, EBT Cash: null',
details: {
snapBalance: null,
cashBalance: null
}
}
You can catch the ebt_error_51
and handle the error in the function call, as in the following examples:
try {
const ebtPaymentCaptureResult = await forage.capturePayment(
ebtPaymentCaptureElement,
paymentRef
)
// handle successful ebtPaymentCaptureResult
} catch (forageErr) {
const { httpStatusCode, message, code, details } = forageErr ?? {}
switch (code) {
case 'ebt_error_51':
console.log(details.snapBalance) // '1.23' | null
console.log(details.cashBalance) // '4.56' | null
// handle insufficient funds!
break
case 'ebt_error_55':
// entered the wrong PIN!
break
default:
// handle unexpected errors
}
}
when (response) {
...
is ForageApiResponse.Failure -> {
val error = response.errors.first()
// handle Insufficient Funds error
if (error.code == "ebt_error_51") {
val details = error.details as ForageErrorDetails.EbtError51Details
val (snapBalance, cashBalance) = details
}
}
}
Updated 8 months ago