Skip to main content
A payment intent represents an intended money movement for an EBT transaction. Your server creates a payment intent with the amount and fulfillment details, then the mobile SDK collects the customer’s PIN to authorize it.
Payment intents expire after one hour. Create them close to the time of checkout.

Payment flow

Tender types

EBT payments support two tender types:
Tender typeDescription
SNAPSupplemental Nutrition Assistance Program benefits. Only SNAP-eligible items qualify.
EBT_CASHEBT cash benefits. Covers a broader range of items.
Each payment intent covers a single tender type. To split a payment across SNAP and EBT cash, create separate payment intents for each.

Fulfillment types

Every payment intent requires a fulfillment type and address:
Fulfillment typeDescription
DELIVERYBenny delivers the order to the customer.
PICKUPThe customer picks up the order.
The fulfillmentAddress must include address1, city, state, and postalCode.

Create a payment intent

Call POST /v1/payment/intent from your server to create a new payment intent.

Request

FieldTypeRequiredDescription
amountintegerYesAmount in cents.
tenderTypestringYesSNAP or EBT_CASH.
fulfillmentTypestringYesDELIVERY or PICKUP.
fulfillmentAddressobjectYesThe delivery or pickup address.
paymentMethodIdstringYesThe payment method to charge.
externalUserIdstringYesYour identifier for the customer.
orderIdstringNoYour identifier for the order.

Response

FieldTypeDescription
paymentIntentIdstringPass this to the mobile SDK to authorize the payment.
const intent = await client.payment.createIntent({
  amount: 2500,
  tenderType: "SNAP",
  fulfillmentType: "DELIVERY",
  fulfillmentAddress: {
    address1: "123 Main St",
    city: "New York",
    state: "NY",
    postalCode: "10001",
  },
  paymentMethodId: "pm_12345",
  externalUserId: "user_12345",
  orderId: "order_67890",
});

// Pass intent.paymentIntentId to the mobile app
console.log(intent.paymentIntentId);

Authorize the payment

Once your mobile app receives the paymentIntentId, use the PinInput component to collect the customer’s PIN and submit the payment.
val controller = rememberPinInputController(sessionToken = sessionToken)

PinInput(
    controller = controller,
    onSuccess = { ebtResult ->
        when (ebtResult) {
            is EbtResult.Payment -> {
                // Payment authorized
            }
            else -> {}
        }
    },
)

Button(onClick = {
    controller.submit(
        panTokenId = panTokenId,
        operation = EbtOperation.Payment(paymentIntentId = "pi_xxx"),
    )
}) {
    Text("Pay")
}
For the complete component API, see the Android SDK or iOS SDK reference.

Update a payment intent

Call PATCH /v1/payment/intent to update the fulfillment details of a pending payment intent. You can only change the fulfillment type and address.

Request

FieldTypeRequiredDescription
paymentIntentIdstringYesThe payment intent to update.
fulfillmentTypestringYesDELIVERY or PICKUP.
fulfillmentAddressobjectYesThe updated address.
await client.payment.updateIntent({
  paymentIntentId: "pi_xxx",
  fulfillmentType: "PICKUP",
  fulfillmentAddress: {
    address1: "456 Oak Ave",
    city: "Brooklyn",
    state: "NY",
    postalCode: "11201",
  },
});

Delete a payment intent

Call DELETE /v1/payment/intent to cancel a pending payment intent. You can only delete intents that haven’t yet gone through authorization.
await client.payment.deleteIntent("pi_xxx");

Balance checks

You can check a customer’s EBT balance without creating a payment intent. Use the PinInput component with EbtOperation.BalanceCheck:
controller.submit(
    panTokenId = panTokenId,
    operation = EbtOperation.BalanceCheck,
)
The onSuccess callback receives an EbtResult.Balance with SNAP and EBT cash balances in cents.