HomeGuidesReference
Log In

Payments

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 and OrderPayment objects.

With the Forage Payments API, you can:

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

{
    "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"
}

When a Payment is initially created, the status value is always requires_confirmation, and the receipt value is always null.

🚧

If a Payment is not captured or canceled within 30 minutes of when it is created, then the Payment expires. Inspect the expires_at field to find a timestamp of the expiration.

Properties

PropertyTypeDescription
refstringA unique reference hash for the Forage Payment object.

You need to pass this value to the front-end SDK method that captures the payment.
merchantstringA string that represents either the merchant’s FNS number, or a unique merchant ID that Forage provides during onboarding.
funding_typestringA string that represents the type of tender. One of:

- ebt_snap
- ebt_cash
- credit_tpp
- benefit
amountstringA 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.
descriptionstringA string that describes the Payment.
metadataobjectA 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_methodstringThe unique reference hash for the existing Forage PaymentMethod that is to be charged in this transaction.
platform_feenumberAn 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_settlementnumberThe 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_settlementnumberThe 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_idstringAn 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_idstring⚠️ 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_idstringA 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_accountstringA 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_terminalobject⚠️ 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_addressobjectThe 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_deliverybooleanWhether the order is for delivery or pickup. This information is required per FNS regulations. Defaults to false if not provided.
createdISO 8601 date-time stringA UTC-8 timestamp of when the Payment was created.
updatedISO 8601 date-time stringA UTC-8 timestamp of when the Payment was last updated.
statusstringThe 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_errorobjectThe code and message values corresponding to the most recent Payments API error.
success_dateISO 8601 date-time stringA UTC-8 timestamp of when the status of the payment is succeeded.
receiptobjectThe 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.
refundsarrayAn array of the unique reference hashes for any PaymentRefunds associated with this Payment.
expires_atISO 8601 date-time stringA 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_idstringA 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.

delivery_address

PropertyTypeDescription
citystringThe name of the city.
countrystringThe constant string US.
line1stringThe first line of the street address.
line2stringThe second line of the street address.
statestringA two-letter abbreviation for the US state.
zipcodestringA zip or postal code.

receipt

🚧

The receipt value is null when the Payment is first created and until receipt data is available. Pass the ref returned in the response to create the Payment in periodic GET requests to /payments/{payment_ref}/ until the status of the Payment is succeeded. At that point, the receipt data, including the balance, is up-to-date.

PropertyTypeDescription
ref_numberstringThe unique reference hash of the Forage Payment.
is_voidedbooleanWhether 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_amountstringThe USD amount charged/refunded to the SNAP balance of the EBT Card, represented as a numeric string.
ebt_cash_amountstringThe USD amount charged/refunded to the EBT Cash balance of the EBT Card, represented as a numeric string.
other_amountstringThe USD amount charged/refunded to any payment method that is not an EBT Card, represented as a numeric string.
sales_tax_appliedstringThe USD amount of taxes charged to the customer’s non-EBT payment instrument, represented as a numeric string.
balanceobjectRefer to balance for details.
last_4stringThe last four digits of the EBT Card number.
messagestringA message from the EBT payment network that must be displayed to the customer.
transaction_typestringA constant string that is used to identify the transaction associated with the receipt. Always Payment in the case of payments.
createdISO 8601 date-time stringA UTC-8 timestamp of when the Payment was created.

balance

PropertyTypeDescription
snapstringThe available SNAP balance in USD on the customer’s EBT Card, represented as a numeric string.
non_snapstringThe available EBT Cash balance in USD on the EBT Card, represented as a numeric string.
updatedISO 8601 date-time stringA UTC-8 timestamp of when the funds in the account last changed.

Payment lifecycle

A 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.

A diagram of the Payment lifecyle as described in the text that follows

🔄 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

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. While customer_id is not technically a required parameter, if you omit it then requests to create the Payment could take longer to process.

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.

📘

POST /payments/ documentation

Retrieve a 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' 

📘

GET /payments/{payment_ref}/ documentation

Update a 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,
}
' 

📘

PATCH /payments/{payment_ref}/ documentation

Cancel a 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' 

📘

POST /payments/{payment_ref}/cancel/ documentation

Retrieve all Payments for a given merchant identifier

curl --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