A Payment
object represents a one-time charge to an existing PaymentMethod
.
Payment objects are only relevant to SDK integrations.
If you’re building with the Fully Hosted or Custom Forage Checkout UI, then use the
Order
andOrderPayment
objects.
With the Forage Payments API, you can:
- Create a Payment: POST
/payments/
- Retrieve a Payment: GET
/payments/{payment_ref}/
- Update a Payment: POST
/payments/{payment_ref}/
- Cancel a Payment: POST
/payments/{payment_ref}/cancel/
- Retrieve all Payments for a given merchant identifier: GET
/payments/
You need a ref
to a Payment
object to complete a transaction. All front-end SDK methods that authorize a payment require the ref
as a parameter, for example:
Payment
object
Payment
object{
"ref": "0ddbcda871",
"merchant": "2222222",
"funding_type": "ebt_snap",
"amount": "20.00",
"description": "An EBT payment",
"metadata": {
"psp_customer_id": "cus_1234567890"
},
"payment_method": "8ef9edff51",
"customer_id": "abc123",
"delivery_address": {
"city": "San Francisco",
"country": "US",
"line1": "1856 Market St.",
"line2": null,
"state": "CA",
"zipcode": "94106"
},
"is_delivery": false,
"created": "2023-09-18T11:38:29.279185-07:00",
"updated": "2023-09-18T11:38:29.279209-07:00",
"status": "requires_confirmation",
"last_processing_error": null,
"success_date": null,
"receipt": null,
"refunds": [],
"expires_at": "2023-09-18T12:08:29.279209-07:00",
"previous_errors": []
}
When a
Payment
is initially created, thestatus
value is alwaysrequires_confirmation
, and thereceipt
value is alwaysnull
.
If a
Payment
is not captured or canceled within 30 minutes of when it is created, then thePayment
expires. Inspect theexpires_at
field to find a timestamp of the expiration.
Properties
Property | Type | Description |
---|---|---|
ref | string | A unique reference hash for the Forage Payment object.You need to pass this value to the front-end SDK method that captures the payment. |
merchant | string | A string that represents either the merchant’s FNS number, or a unique merchant ID that Forage provides during onboarding. |
funding_type | string | A string that represents the type of tender. One of: - ebt_snap - ebt_cash - credit_tpp - benefit |
amount | string | A positive decimal number representing how much to charge the PaymentMethod in USD. Precision to the penny is supported. The minimum amount that can be charged is 0.01 . To differentiate between a SNAP and an EBT Cash charge on the same EBT card, use the funding_type field. If you need to charge both funding types, then create a Payment for each charge. |
description | string | A string that describes the Payment . |
metadata | object | A set of optional, merchant-defined key-value pairs that can be added to an object. For example, some merchants attach their credit card processor’s ID for the customer making the payment. If there’s no additional information that you’d like to add, then pass an empty object as the value. |
payment_method | string | The unique reference hash for the existing Forage PaymentMethod that is to be charged in this transaction. |
platform_fee | number | An optional field, for use by a platform supporting multiple merchants, that indicates the percentage cut of each payment that the platform charges as a fee. |
platform_fixed_settlement | number | The fixed amount in USD that a platform takes from EBT Cash payments prior to splitting by the platform_fee . Precision to the penny is supported. |
merchant_fixed_settlement | number | The fixed amount in USD that should be restored to the merchant from EBT Cash payments prior to splitting by the platform_fee . Precision to the penny is supported. |
tpp_lookup_id | string | An identifier for the credit/debit TPP. For Stripe integrations, the client secret for a Stripe PaymentIntent. For Authorize.net integrations, the transactionId of the payment capture event. |
customer_id | string | ⚠️ If you’re integrating Forage with a POS Terminal, then do not use this param. It is only supported for online transactions. A unique identifier for the end customer making the payment. This field helps Forage's servers more quickly identify the customer associated with the request. While customer_id is not technically required, if you omit it then requests could take longer to process.If you're providing your internal customer ID, then we recommend that you hash the value before sending it on the payload. Each customer should only have one unique customer_id . For example, if you create both a PaymentMethod and a Payment for the same customer, then the customer_id should be the same in both requests. |
external_order_id | string | A unique identifier for the order as created by the merchant or platform (not Forage). When a merchant or platform passes this order ID to Forage, it persists in each Forage transaction related to the Order. This field enables merchants to map order IDs in their system to corresponding Forage Order IDs. |
merchant_destination_account | string | A unique reference hash for the bank account that is to receive funds settlement for this payment. Use this field if you're settling funds across multiple merchant bank accounts. Reach out to your Forage account manager for details on generating a hash. Defaults to the hash for the default merchant bank account if not provided. |
pos_terminal | object | ⚠️ This param is only supported for POS Terminal integrations. Do not use this param for online transactions. An object that details information about the POS Terminal that processes the payment. Currently a provider_terminal_id key with a value that is a unique string identifying the Terminal. |
delivery_address | object | The address for delivery or pickup of the order. Per FNS regulations, this value must always be provided. If the order is for pickup, then use the merchant address. Refer to delivery address for details. |
is_delivery | boolean | Whether the order is for delivery or pickup. This information is required per FNS regulations. Defaults to false if not provided. |
created | ISO 8601 date-time string | A UTC-8 timestamp of when the Payment was created. |
updated | ISO 8601 date-time string | A UTC-8 timestamp of when the Payment was last updated. |
status | string | The status of the Payment . One of:- canceled : The Payment object can't be used.- failed : If the error is temporary, then this Payment can be resubmitted for capture without modification. Check the receipt.message field for a description of the error.- processing : The outcome of the Payment is pending.- requires_confirmation : The Payment hasn't been submitted for processing.- succeeded : The Payment has been successfully processed and will be included in settlement. It can't be changed. |
last_processing_error | object | The code and message values corresponding to the most recent Payments API error. |
success_date | ISO 8601 date-time string | A UTC-8 timestamp of when the status of the payment is succeeded . |
receipt | object | The information that you're required to display to the customer after the Payment status is succeeded , according to FNS regulations.This field is null if receipt data is not yet available for the Payment . Refer to receipt for details. |
refunds | array | An array of the unique reference hashes for any PaymentRefunds associated with this Payment . |
expires_at | ISO 8601 date-time string | A UTC timestamp of when the Payment will expire if it is not captured or canceled, set to 30 minutes from when the Payment is created. |
external_location_id | string | A unique identifier, provided by the merchant or platform (not Forage), that indicates the physical fulfillment location for the order. For example, this field could specify which location of a grocery store chain fulfilled an order. |
previous_errors | array | An array of objects that detail information about any errors triggered by the request. If the request was successful and without errors, then the field is returned as an empty array. Refer to previous_errors for details. |
delivery_address
delivery_address
Property | Type | Description |
---|---|---|
city | string | The name of the city. |
country | string | The constant string US . |
line1 | string | The first line of the street address. |
line2 | string | The second line of the street address. |
state | string | A two-letter abbreviation for the US state. |
zipcode | string | A zip or postal code. |
receipt
receipt
The
receipt
value is null when thePayment
is first created and until receipt data is available. Pass theref
returned in the response to create thePayment
in periodic GET requests to/payments/{payment_ref}/
until thestatus
of thePayment
issucceeded
. At that point, the receipt data, including the balance, is up-to-date.
Property | Type | Description |
---|---|---|
ref_number | string | The unique reference hash of the Forage Payment . |
is_voided | boolean | Whether the Payment has been voided. If false , then the Payment amount has been charged as expected. In the rare case of true , the charge has been refunded. |
snap_amount | string | The USD amount charged/refunded to the SNAP balance of the EBT Card, represented as a numeric string. |
ebt_cash_amount | string | The USD amount charged/refunded to the EBT Cash balance of the EBT Card, represented as a numeric string. |
other_amount | string | The USD amount charged/refunded to any payment method that is not an EBT Card, represented as a numeric string. |
sales_tax_applied | string | The USD amount of taxes charged to the customer’s non-EBT payment instrument, represented as a numeric string. |
balance | object | Refer to balance for details. |
last_4 | string | The last four digits of the EBT Card number. |
message | string | A message from the EBT payment network that must be displayed to the customer. |
transaction_type | string | A constant string that is used to identify the transaction associated with the receipt. Always Payment in the case of payments. |
created | ISO 8601 date-time string | A UTC-8 timestamp of when the Payment was created. |
balance
balance
Property | Type | Description |
---|---|---|
snap | string | The available SNAP balance in USD on the customer’s EBT Card, represented as a numeric string. |
non_snap | string | The available EBT Cash balance in USD on the EBT Card, represented as a numeric string. |
updated | ISO 8601 date-time string | A UTC-8 timestamp of when the funds in the account last changed. |
previous_errors
previous_errors
Each object in the previous_errors
array includes the following fields:
Property | Type | Description |
---|---|---|
code | string | A short string that represents the error. |
message | string | A developer-facing message with more details about the error, not to be displayed to customers. |
source | object | An object that details the specific source of the Forage error, including two keys: - resource : The type of the Forage resource involved in the error.- ref : If applicable, the ten character reference hash of the Forage resource that caused the error. An empty string if no specific individual resource was involved. |
details | object | Additional details about the error, if applicable. |
Payment
lifecycle
Payment
lifecycleA Forage Payment
enters different lifecycle stages depending on a customer’s checkout interactions. You can track a Payment
's stage in the lifecycle via its status
attribute.
🔄 requires_confirmation
A Payment
has been created and is pending further action. It has not yet been submitted for processing, so you can still update the Payment
.
From a UX perspective, Forage recommends creating a Payment
after a customer inputs the SNAP and/or EBT Cash amount to apply to the cart and completes an action like clicking "Place Order".
From requires_confirmation
, a Payment
can move to either processing
or canceled
.
🔄 processing
As soon as an attempt is made to capture a Payment
, its status moves to processing
.
You can no longer modify the Payment
.
Forage is waiting on a response from the upstream EBT benefits networks.
From a UX perspective, a capture attempt begins when an SDK customer completes an action, like clicking "Submit Payment", that calls the Forage method that captures the payment.
From processing
, a Payment
can move to either succeeded
or failed
.
✅ succeeded
The Payment
has been successfully captured.
The merchant can expect to receive the funds.
The customer can expect the payment amount to be debited from their account balance.
succeeded
is a terminal state. You can no longer modify the Payment
or resubmit it for capture. The Payment
lifecycle is complete.
❌ failed
The Payment
capture failed.
You can modify the Payment
, or reattempt capture.
Forage automatically moves the Payment
to the canceled
stage after 30 minutes.
✖️ canceled
There are many reasons to cancel a Payment
. For example, a merchant might discover that they’re out of stock of a particular item, or a customer might notice a mistake in their cart.
A Payment
can only be canceled if it is at the requires_confirmation
or failed
state.
Forage automatically cancels a Payment
after 30 minutes of inactivity.
canceled
is a terminal state. You can no longer modify the Payment
or resubmit it for capture. The Payment
lifecycle is complete.
Examples
Create a Payment
Payment
curl --request POST \
--url https://api.sandbox.joinforage.app/api/payments/ \
--header 'Authorization: Bearer <authentication-token>' \
--header 'Idempotency-Key: 123e4567e8' \
--header 'Merchant-Account: 9000055' \
--header 'accept: application/json' \
--header 'content-type: application/json' \
--data '
{
"delivery_address": {
"city": "San Francisco",
"country": "US",
"line1": "1856 Market St.",
"line2": "Unit 3",
"zipcode": "94106",
"state": "CA"
},
"customer_id": "abc123",
"is_delivery": false,
"amount": 20.00,
"funding_type": "ebt_snap",
"description": "An EBT payment"
"metadata": {},
"payment_method": "<payment-method-ref>"
}
'
Pass
customer_id
in the request body
customer_id
helps Forage's servers more quickly identify and associate the correct customer with the Session. Whilecustomer_id
is not technically a required parameter, if you omit it then requests to create thePayment
could take longer to process.Each customer should only have one unique
customer_id
. For example, if you create both aPaymentMethod
and aPayment
for the same customer, then thecustomer_id
should be the same in both requests.
Retrieve a Payment
Payment
curl --request GET \
--url https://api.sandbox.joinforage.app/api/payments/{payment_ref}/ \
--header 'Authorization: Bearer <authentication-token>' \
--header 'Merchant-Account: 9000055' \
--header 'accept: application/json' \
--header 'content-type: application/json'
Update a Payment
Payment
curl --request PATCH \
--url https://api.sandbox.joinforage.app/api/payments/{payment_ref}/ \
--header 'Authorization: Bearer <authentication-token>' \
--header 'Idempotency-Key: 123e4567e8' \
--header 'Merchant-Account: 9000055' \
--header 'accept: application/json' \
--header 'content-type: application/json'\
--data '
{
"is_delivery": true,
}
'
Cancel a Payment
Payment
curl --request POST \
--url https://api.sandbox.joinforage.app/api/payments/{payment_ref}/cancel/ \
--header 'Authorization: Bearer <authentication-token>' \
--header 'Merchant-Account: 9000055' \
--header 'accept: application/json' \
--header 'content-type: application/json'
Retrieve all Payment
s for a given merchant identifier
Payment
s for a given merchant identifiercurl --request GET \
--url https://api.sandbox.joinforage.app/api/payments/?external_order_id={external_order_id}} \
--header 'Authorization: Bearer <authentication-token>' \
--header 'Merchant-Account: 9000055' \
--header 'accept: application/json' \
GET
/payments/?external_order_id=<external-order-id>/
documentation