# Reference: Webhook Events
Complete specifications for all Forage webhook events, payload schemas, and IP addresses
## Example webhook payload
```json
{
"created": "2023-10-05T17:38:26.698516-07:00",
"data": {
"ebt_cash_total": "10.00",
"external_order_id": "58503b96-5111-495b-b13b-d9247be12e75",
"merchant_fns": "121212",
"merchant_id": "2fb3asdz40",
"order_ref": "3ee466e0ef",
"payments": [
{
"amount": "10.00",
"funding_type": "ebt_snap",
"merchant_fns": "0256679",
"merchant_id": "07839ae280",
"order_ref": "3ee466e0ef",
"payment_ref": "5fa6e45620",
"status": "succeeded"
},
{
"amount": "10.00",
"funding_type": "ebt_cash",
"merchant_fns": "0256679",
"merchant_id": "07839ae280",
"order_ref": "3ee466e0ef",
"payment_ref": "sd7v223HsA",
"status": "succeeded"
}
],
"remaining_total": "0.00",
"snap_total": "10.00",
"status": "succeeded"
},
"ref": "72672bab12",
"type": "ORDER_STATUS_UPDATED"
}
```
> ⚠️ **Some numeric values are represented as strings**
>
> The decimal values in webhook payloads are returned as strings. Refer to the [API introduction](https://docs.joinforage.app/reference/introduction#some-numeric-values-are-returned-as-strings) for details on how to parse the data.
### Common payload fields
All webhooks, no matter the `type`, return the following properties:
| | Type | Description | Example value |
| --------- | --------- | --------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------- |
| `created` | date-time | The timestamp of event creation, represented as an [ISO-8601 date-time](https://www.iso.org/iso-8601-date-and-time-format.html) string. | `2023-10-05T17:38:26.698516-07:00` |
| `data` | object | An object including event-specific information. | Refer to the event sections below for example values corresponding to each event type. |
| `ref` | string | A unique string identifier for the event. | `72672bcxgq` |
| `type` | string | A string representing the type of the event. Refer to the event sections below for available types. | `ORDER_STATUS_UPDATED` |
## Onboarding events
If you're using the the Forage Merchant Onboarding UI, then you can listen for webhooks that indicate when a merchant enters a different stage of the onboarding lifecycle. These webhooks include:
* [`MERCHANT_ONBOARDING_SUBMITTED`](https://docs.joinforage.app/docs/configure-webhooks#merchant_onboarding_submitted)
* [`MERCHANT_ONBOARDING_VERIFICATION_FAILED`](https://docs.joinforage.app/docs/configure-webhooks#merchant_onboarding_verification_failed)
* [`MERCHANT_ONBOARDING_LIVE`](https://docs.joinforage.app/docs/configure-webhooks#merchant_onboarding_live)
```mermaid
stateDiagram-v2
[*] --> Submitted : Merchant completes Onboarding UI
Submitted --> VerificationFailed : FNS cannot be validated
Submitted --> Live : FNS verified
VerificationFailed --> [*] : No automatic retry
Live --> [*]
note right of Submitted : SUBMITTED fires
note right of VerificationFailed : VERIFICATION_FAILED fires
note right of Live : LIVE fires
```
In addition to the common payload fields that all webhooks return, every onboarding event webhook details the following attributes:
| | Type | Description | Example value |
| ----------------------------- | --------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------- |
| `merchant_ref` | string | The unique merchant ID that Forage provides during onboarding. | `36e7fcecbb` |
| `merchant_fns` | string | The merchant's unique FNS number. | `121212` |
| `name` | string | The name of the merchant. | `MerchantName` |
| `store_number` | string | A unique number provided by the platform (not Forage) to identify the merchant. | `123456` |
| `address` | object | The merchant's physical address. | `{ "line1": "1856 Market St.", "line2": null, "city": "San Francisco", "state": "CA", "zipcode": "94102", "country": "US" }` |
| `timezone_offset` | number | The number of hours between UTC and the merchant's timezone. For example, if a merchant is based in EST, then the timezone\_offset is `-4`. If based in PST, then the value is `-7`. | `-7` |
| `is_physical_store` | boolean | Whether this onboarded merchant represents a physical store location. | `true` |
| `contact_email` | string | An email address that can be used to contact the merchant. | `hello@merchantname.com` |
| `chargeback_email` | string | The email address that Forage uses to contact the merchant in case of chargebacks. | `finance@merchantname.com` |
| `agreed_to_tos` | date-time | A timestamp of when the merchant signed the platform's terms of service, represented as an [ISO-8601 date-time](https://www.iso.org/iso-8601-date-and-time-format.html) string. | `2023-10-05T17:38:26.698516-07:00` |
| `customer_merchant_reference` | string | A unique reference hash identifier for the onboarding merchant provided by the platform (not Forage). | `987xy12z34` |
| `go_live_date` | date-time | A timestamp of when a merchant is live with Forage and can begin processing EBT, represented as an [ISO-8601 date-time](https://www.iso.org/iso-8601-date-and-time-format.html) string. The actual live date may differ depending on the parent platform. | `2023-11-05T17:38:26.698516-07:00` |
### MERCHANT\_ONBOARDING\_SUBMITTED
The `MERCHANT_ONBOARDING_SUBMITTED` webhook fires when an onboarding merchant has completed the Onboarding UI and submitted the information to Forage.
```json
{
"created": "2023-10-05T17:38:26.698516-07:00",
"data": {
"merchant_ref": "36e7fcecbb",
"fns_number": "121212",
"name": "MerchantName",
"store_number": "123456",
"address": {
"line1": "1856 Market St.",
"city": "San Francisco",
"state": "CA",
"zipcode": "94102",
"country": "US"
},
"timezone_offset": -7,
"is_physical_store": true,
"contact_email": "hello@merchantname.com",
"chargeback_email": "finance@merchantname.com",
"agreed_to_tos": "2023-10-05T17:38:26.698516-07:00",
"customer_merchant_reference": "987xy12z34",
"go_live_date": "2023-11-05T17:38:26.698516-07:00",
},
"ref": "72672b13bb",
"type": "MERCHANT_ONBOARDING_SUBMITTED",
}
```
### MERCHANT\_ONBOARDING\_VERIFICATION\_FAILED
Forage sends a `MERCHANT_ONBOARDING_VERIFICATION_FAILED` webhook if the FNS number that the merchant submitted through the Onboarding UI is unable to be validated.
```json
{
"created": "2023-10-05T17:38:26.698516-07:00",
"data": {
"merchant_ref": "36e7fcecbb",
"fns_number": "121212",
"name": "MerchantName",
"store_number": "123456",
"address": {
"line1": "1856 Market St.",
"city": "San Francisco",
"state": "CA",
"zipcode": "94102",
"country": "US"
},
"timezone_offset": -7,
"is_physical_store": true,
"contact_email": "hello@merchantname.com",
"chargeback_email": "finance@merchantname.com",
"agreed_to_tos": "2023-10-05T17:38:26.698516-07:00",
"customer_merchant_reference": "987xy12z34",
"go_live_date": "2023-11-05T17:38:26.698516-07:00",
},
"ref": "72672b13bb",
"type": "MERCHANT_ONBOARDING_VERIFICATION_FAILED",
}
```
### MERCHANT\_ONBOARDING\_LIVE
The `MERCHANT_ONBOARDING_LIVE` webhook fires when Forage has successfully verified and onboarded the merchant.
```json
{
"created": "2023-10-05T17:38:26.698516-07:00",
"data": {
"merchant_ref": "36e7fcecbb",
"fns_number": "121212",
"name": "MerchantName",
"store_number": "123456",
"address": {
"line1": "1856 Market St.",
"city": "San Francisco",
"state": "CA",
"zipcode": "94102",
"country": "US"
},
"timezone_offset": -7,
"is_physical_store": true,
"contact_email": "hello@merchantname.com",
"chargeback_email": "finance@merchantname.com",
"agreed_to_tos": "2023-10-05T17:38:26.698516-07:00",
"customer_merchant_reference": "987xy12z34",
"go_live_date": "2023-11-05T17:38:26.698516-07:00",
},
"ref": "72672b13bb",
"type": "MERCHANT_ONBOARDING_LIVE",
}
```
## SDK integrations
SDK integrations interact with Forage `Payment` and `PaymentRefund` resources. The following webhooks are relevant to SDK integrations.
### PAYMENT\_STATUS\_UPDATED
The `PAYMENT_STATUS_UPDATED` webhook fires when the status of an EBT SNAP or EBT Cash payment is updated.
The webhook `data.status` attribute is always one of `succeeded`, `failed`, or `canceled`.
`data.status == succeeded` when:
* The EBT [state processor](https://docs.joinforage.app/docs/ebt-online-101#state-processor) completes the payment and sends Forage a success response
`succeeded` is a terminal state.
`data.status == failed` when:
* The state processor cannot complete the payment and sends Forage a failure response, like if a customer doesn't have sufficient funds on their EBT card
* Forage is unable to contact the state processor
`failed` is not a terminal state.
`data.status == canceled` when:
* You manually cancel a payment via a `POST` to [`/payments/{payment_ref}/cancel/`](https://docs.joinforage.app/reference/cancel-a-payment)
`canceled` is a terminal state.
For guidance on using this event to trigger internal processes, see [How Forage Webhooks Work](./webhooks-concepts.md).
```json
{
"created": "2023-10-05T17:38:26.698516-07:00",
"data": {
"amount": "10.00",
"external_order_id": "a238d043-5d88-4bd8-bdf5-769c83e2482e",
"funding_type": "ebt_snap",
"merchant_fns": "121212",
"merchant_id": "2fb3asd",
"payment_ref": "3a16426601",
"status": "succeeded",
},
"ref": "72672b13bb",
"type": "PAYMENT_STATUS_UPDATED",
}
```
```json
{
"ref": "cd9e3b2c83",
"created": "2024-05-21T14:50:57.861207+00:00",
"type": "PAYMENT_STATUS_UPDATED",
"data": {
"payment_ref": "2a629162f4",
"status": "failed",
"amount": "20.00",
"merchant_fns": "1234567",
"merchant_id": "4f984ec909",
"failure_reason": {
"code": "ebt_error_51",
"message": "Insufficient funds - Insufficient Funds. Remaining balances are SNAP: $100.00, EBT Cash: $100.00"
},
"funding_type": "ebt_cash",
"previous_errors": [
{
"code": "ebt_error_51",
"message": "Insufficient funds - Insufficient Funds. Remaining balances are SNAP: $100.00, EBT Cash: $100.00",
"details": {
"cash_balance": "100.00",
"snap_balance": "100.00"
},
"source": {
"resource": "Payments",
"ref": "2a629162f4"
}
}
]
}
}
```
#### PAYMENT\_STATUS\_UPDATED `data` attributes
| | Type | Description | Example value |
| --------------------------------- | ------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------- |
| `amount` | string | The amount charged to the payment method. | `10.00` |
| `external_order_id` | string | A unique identifier for the order as created by the merchant or platform (not Forage). | `a238d043-5d88-4bd8-bdf5-769c83e2482e` |
| `funding_type` | string | A string that represents the type of tender. One of: `benefit`, `ebt_cash`, `ebt_snap` | `ebt_snap` |
| `merchant_fns` | string | The merchant's unique [FNS](https://docs.joinforage.app/docs/ebt-online-101#food-and-nutrition-service-fns) number. | `121212` |
| `merchant_id` | string | A 10-character unique hash identifying the merchant associated with this transaction. | `gxe37pc24y` |
| `payment_ref` | string | A unique reference identifier for the payment. | `3a16426601` |
| `status` | string | A string representing the payment's state in the processing cycle. | `succeeded` |
| `failure_reason` *(failure only)* | object | An object with the following keys: `code`: A short string that helps identify the cause of the error. For example, `"55"` indicates that a customer entered an invalid EBT Card PIN. `message`: A developer-facing description of the error. Refer to the [errors reference](https://docs.joinforage.app/reference/errors#code-and-message-pairs-1) for common `code` and `message` pairs. | `55` `Invalid PIN or PIN not selected - Invalid PIN` |
| `previous_errors` | array | An array of objects that include the `code`, `message` and `source` values corresponding to the most recent EBT network-related error associated with a canceled or failed `Payment`. This field is only returned when the `data.status` of the webhook is `canceled` or `failed`. | Refer to the complete Failed example above. |
### REFUND\_STATUS\_UPDATED
The `REFUND_STATUS_UPDATED` webhook fires when the status of a refund is updated.
The webhook `data.status` attribute is always one of `succeeded`, `failed`, or `canceled`.
`data.status == succeeded` when:
* The EBT [state processor](https://docs.joinforage.app/docs/ebt-online-101#state-processor) completes the refund and sends Forage a success response
`succeeded` is a terminal state.
`data.status == failed` when:
* The EBT [state processor](https://docs.joinforage.app/docs/ebt-online-101#state-processor) cannot complete the refund and sends Forage a failure response
* Forage is unable to contact the state processor
`failed` is not a terminal state.
`data.status == canceled` when:
* A refund is voided. In this rare case, the financial effect of the refund is reversed
`canceled` is a terminal state.
For guidance on using this event to trigger internal processes, see [How Forage Webhooks Work](./webhooks-concepts.md).
```json
{
"ref": "72672bc724",
"created": "2023-10-05T17:38:26.698516-07:00",
"type": "REFUND_STATUS_UPDATED",
"data": {
"refund_ref": "87432dehkk",
"external_order_id": "a238d043-5d88-4bd8-bdf5-769c83e2482e",
"status": "succeeded",
"amount": "25.99",
"merchant_fns": "121212",
"merchant_id": "2fb3asd",
"payment_ref": "8e3c6a9d07"
}
}
```
```json
{
"ref": "e1ecf255f4",
"created": "2024-01-31T19:50:10.065453+00:00",
"type": "REFUND_STATUS_UPDATED",
"data": {
"refund_ref": "60ddf6e386",
"external_order_id": "a238d043-5d88-4bd8-bdf5-769c83e2482e",
"status": "failed",
"amount": "20.00",
"merchant_fns": "9000012",
"merchant_id": "bacb08ea2a",
"payment_ref": "234ccb21d6",
"failure_reason": {
"code": "55",
"message": "Invalid PIN or PIN not selected - Invalid PIN"
}
}
}
```
#### REFUND\_STATUS\_UPDATED `data` attributes
| | Type | Description | Example value |
| --------------------------------- | ------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------- |
| `refund_ref` | string | A unique identifier for the refund. | `87432dehkk` |
| `status` | string | A string representing the refund's state in the processing cycle. | `succeeded` |
| `external_order_id` | string | A unique identifier for the order as created by the merchant or platform (not Forage). | `a238d043-5d88-4bd8-bdf5-769c83e2482e` |
| `amount` | string | The amount charged to be refunded to the payment method. | `25.99` |
| `merchant_fns` | string | The merchant's unique [FNS](https://docs.joinforage.app/docs/ebt-online-101#food-and-nutrition-service-fns) number. | `121212` |
| `merchant_id` | string | A 10-character unique hash identifying the merchant associated with this transaction. | `gxe37pc24y` |
| `payment_ref` | string | The ref of the payment associated with this refund | `8e3c6a9d07` |
| `failure_reason` *(failure only)* | object | An object with the following keys: `code`: A short string that helps identify the cause of the error. For example, `"55"` indicates that a customer entered an invalid EBT Card PIN. `message`: A developer-facing description of the error. Refer to the [errors reference](https://docs.joinforage.app/reference/errors#code-and-message-pairs-1) for common `code` and `message` pairs. | `55` `Invalid PIN or PIN not selected - Invalid PIN` |
## Fully Hosted and Custom integrations
Fully Hosted and Custom integrations interact with Forage `Order`, `OrderPayment`, and `OrderRefund` resources.
You can use Forage webhooks to track the entire order status, in addition to individual payments and refunds associated with the order. Webhooks for order-related payments and refunds include an `order_ref` in the `data` field.
### ORDER\_STATUS\_UPDATED
> 📘 **Integration type**
>
> `ORDER_STATUS_UPDATED` is only available to [Fully Hosted](https://docs.joinforage.app/docs/fully-hosted) and [Custom](https://docs.joinforage.app/docs/custom) integrations.
>
> If you're building with a Forage SDK, use the [`PAYMENT_STATUS_UPDATED`](#payment_status_updated) or [`REFUND_STATUS_UPDATED`](#refund_status_updated) webhooks instead.
The `ORDER_STATUS_UPDATED` webhook fires when the status of an order is updated. An order can contain multiple payments (for example, one SNAP payment and one EBT Cash payment), and the `Order` status reflects the outcome of all associated payments.
The webhook `data.status` attribute is one of `succeeded`, `canceled`, or `failed`.
`data.status == succeeded` when:
* All of the payments associated with an Order have successfully processed
`succeeded` is a terminal state.
`data.status == failed` when:
* The EBT [state processor](https://docs.joinforage.app/docs/ebt-online-101#state-processor) cannot complete the order and sends Forage a failure response
* Forage is unable to contact the state processor
* A credit card refund for a Fully Hosted Checkout session fails
`failed` is not a terminal state.
`data.status == canceled` when:
* You manually cancel an order via a `POST` to [`/orders/{ref}/cancel/`](https://docs.joinforage.app/reference/cancel-order)
* Forage cancels the order due to an associated payment failure or a 30-minute timeout (for example, if the order is still in draft status)
`canceled` is a terminal state.
For guidance on using this event, see [How Forage Webhooks Work](./webhooks-concepts.md).
> ⚠️ **Creation events not included**
>
> `ORDER_STATUS_UPDATED` only fires on updates to an existing order. It is not triggered when an order is created.
```json
{
"created": "2023-10-05T17:38:26.698516-07:00",
"data": {
"ebt_cash_total": "10.00",
"external_order_id": "58503b96-5111-495b-b13b-d9247be12e75",
"merchant_fns": "121212",
"merchant_id": "2fb3asd",
"order_ref": "3ee466e0ef",
"payments": [
{
"amount": "10.00",
"funding_type": "ebt_snap",
"merchant_fns": "0256679",
"merchant_id": "07839ae280",
"order_ref": "3ee466e0ef",
"payment_ref": "5fa6e45620",
"status": "succeeded"
},
{
"amount": "10.00",
"funding_type": "ebt_cash",
"merchant_fns": "0256679",
"merchant_id": "07839ae280",
"order_ref": "3ee466e0ef",
"payment_ref": "sd7v223HsA",
"status": "succeeded"
}
],
"remaining_total": "0.00",
"snap_total": "10.00",
"status": "succeeded"
},
"ref": "72672bab12",
"type": "ORDER_STATUS_UPDATED"
}
```
```json
{
"ref": "d700e94235",
"created": "2024-05-21T14:50:57.852878+00:00",
"type": "ORDER_STATUS_UPDATED",
"data": {
"order_ref": "c8ac066123",
"status": "failed",
"snap_total": "0.00",
"ebt_cash_total": "20.00",
"remaining_total": "0.00",
"merchant_fns": "1234789",
"merchant_id": "4f984ec818",
"failure_reason": {
"code": "ebt_error_51",
"message": "Insufficient funds - Insufficient Funds. Remaining balances are SNAP: $100.00, EBT Cash: $100.00"
},
"payments": [
{
"payment_ref": "2a629165G6",
"status": "failed",
"amount": "20.00",
"merchant_fns": "1234567",
"merchant_id": "4f984ec909",
"order_ref": "c8ac066123",
"failure_reason": {
"code": "ebt_error_51",
"message": "Insufficient funds - Insufficient Funds. Remaining balances are SNAP: $100.00, EBT Cash: $100.00"
},
"funding_type": "ebt_cash"
}
],
"previous_errors": [
{
"code": "ebt_error_51",
"message": "Insufficient funds - Insufficient Funds. Remaining balances are SNAP: $100.00, EBT Cash: $100.00",
"details": {
"cash_balance": "100.00",
"snap_balance": "100.00"
},
"source": {
"resource": "Payments",
"ref": "2a629162f4"
}
}
]
}
}
```
#### ORDER\_STATUS\_UPDATED `data` attributes
| | Type | Description | Example value |
| ------------------- | ------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------- |
| `ebt_cash_total` | string | The amount charged to the customer's EBT Cash balance. | `10.00` |
| `external_order_id` | string | A unique identifier for the order as created by the merchant or platform (not Forage). | `58503b96-5111-495b-b13b-d9247be12e75` |
| `merchant_fns` | string | The merchant's unique [FNS](https://docs.joinforage.app/docs/ebt-online-101#food-and-nutrition-service-fns) number. | `121212` |
| `merchant_id` | string | The unique merchant ID that Forage provides during onboarding. | `2fb3asd` |
| `order_ref` | string | A unique identifier for the order. | `93410bcaff` |
| `payments` | array | An array of objects that detail information about each payment associated with the order. | Refer to [`payments`](#payments). |
| `remaining_total` | string | The amount charged to the customer's non-EBT Card payment method. | `0.00` |
| `snap_total` | string | The amount charged to the customer's SNAP balance. | `10.00` |
| `status` | string | A string representing the order's state in the processing cycle. | `succeeded` |
| `previous_errors` | array | An array of objects that include the `code`, `message` and `source` values corresponding to the most recent EBT network-related error associated with a canceled or failed `Order`. This field is only returned when the `data.status` of the webhook is `canceled` or `failed`. | Refer to the complete Failed example above. |
#### `payments`
Each object in the `payments` array contains the following information about an associated payment:
| | Type | Description | Example value |
| ---------------- | ------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------- |
| `amount` | string | A positive decimal number that represents how the [`PaymentMethod`](https://docs.joinforage.app/reference/payment-methods) was charged in USD. | `10.00` |
| `funding_type` | string | A string that represents the type of tender. One of: `benefit`, `ebt_cash`, `ebt_snap` | `ebt_snap` |
| `merchant_fns` | string | The merchant's unique [FNS](https://docs.joinforage.app/docs/ebt-online-101#food-and-nutrition-service-fns) number. | `025667` |
| `merchant_id` | string | The unique merchant ID that Forage provides during onboarding. | `07839ae280` |
| `order_ref` | string | A unique identifier for the order. | `3ee466e0ef` |
| `payment_ref` | string | A unique identifier for the payment. | `5fa6e45620` |
| `status` | string | A string representing the payment's state in the processing cycle. | `succeeded` |
| `failure_reason` | object | An object with the following keys: `code`: A short string that helps identify the cause of the error. For example, `"55"` indicates that a customer entered an invalid EBT Card PIN. `message`: A developer-facing description of the error. Refer to the [errors reference](https://docs.joinforage.app/reference/errors#code-and-message-pairs-1) for common `code` and `message` pairs. | `55` `Invalid PIN or PIN not selected - Invalid PIN` |
### PAYMENT\_STATUS\_UPDATED
The `PAYMENT_STATUS_UPDATED` webhook for Fully Hosted and Custom integrations is almost identical to the webhook for SDK integrations, with two differences:
* The `data` field includes an `order_ref` that links the payment to its parent order
* This webhook also fires for credit/debit payment updates (not just EBT)
```json
{
"created": "2023-10-05T17:38:26.698516-07:00",
"data": {
"amount": "10.00",
"external_order_id": "a238d043-5d88-4bd8-bdf5-769c83e2482e",
"funding_type": "ebt_snap",
"merchant_fns": "121212",
"merchant_id": "2fb3asd",
"payment_ref": "3a16426601",
"status": "succeeded",
"order_ref": "3a16426601"
},
"ref": "72672b13bb",
"type": "PAYMENT_STATUS_UPDATED",
}
```
```json
{
"ref": "cd9e3b2c83",
"created": "2024-05-21T14:50:57.861207+00:00",
"type": "PAYMENT_STATUS_UPDATED",
"data": {
"payment_ref": "2a629162f4",
"status": "failed",
"amount": "20.00",
"merchant_fns": "1234567",
"merchant_id": "4f984ec909",
"order_ref": "c8ac066560",
"failure_reason": {
"code": "ebt_error_51",
"message": "Insufficient funds - Insufficient Funds. Remaining balances are SNAP: $100.00, EBT Cash: $100.00"
},
"funding_type": "ebt_cash",
"previous_errors": [
{
"code": "ebt_error_51",
"message": "Insufficient funds - Insufficient Funds. Remaining balances are SNAP: $100.00, EBT Cash: $100.00",
"details": {
"cash_balance": "100.00",
"snap_balance": "100.00"
},
"source": {
"resource": "Payments",
"ref": "2a629162f4"
}
}
]
}
}
```
The `order_ref` is a unique identifier for the parent `Order` that the `Payment` is attached to. For details on the other fields, refer to [PAYMENT\_STATUS\_UPDATED data attributes](https://docs.joinforage.app/docs/configure-webhooks#payment_status_updated-data-attributes).
### REFUND\_STATUS\_UPDATED
The `REFUND_STATUS_UPDATED` webhook for Fully Hosted and Custom integrations is almost identical to the webhook for SDK integrations. The only difference is the addition of an `order_ref` in the `data` field, as in the following example:
```json
{
"ref": "72672bc724",
"created": "2023-10-05T17:38:26.698516-07:00",
"type": "REFUND_STATUS_UPDATED",
"data": {
"refund_ref": "87432dehkk",
"external_order_id": "a238d043-5d88-4bd8-bdf5-769c83e2482e",
"status": "succeeded",
"amount": "25.99",
"merchant_fns": "121212",
"merchant_id": "2fb3asd",
"payment_ref": "8e3c6a9d07",
"order_ref": "3a16426601"
}
}
```
```json
{
"ref": "e1ecf255f4",
"created": "2024-01-31T19:50:10.065453+00:00",
"type": "REFUND_STATUS_UPDATED",
"data": {
"refund_ref": "60ddf6e386",
"external_order_id": "a238d043-5d88-4bd8-bdf5-769c83e2482e",
"status": "failed",
"amount": "20.00",
"merchant_fns": "9000012",
"merchant_id": "bacb08ea2a",
"payment_ref": "234ccb21d6",
"order_ref": "3a16426601",
"failure_reason": {
"code": "55",
"message": "Invalid PIN or PIN not selected - Invalid PIN"
}
}
}
```
The `order_ref` is a unique identifier for the parent `Order` that the `Refund` is attached to. For details on the other fields, refer to [REFUND\_STATUS\_UPDATED attributes](https://docs.joinforage.app/docs/configure-webhooks#refund_status_updated-data-attributes).
## IP Addresses
Webhook notifications may originate from any of the following IP addresses:
| Environment | IP Address |
| -------------- | ---------------- |
| **Production** | `54.71.62.121` |
| | `35.81.99.127` |
| **Sandbox** | `35.84.122.17` |
| | `44.232.107.207` |
## Related documentation
* [How Forage Webhooks Work](./webhooks-concepts.md). What webhooks are, when events fire, and how Forage delivers them.
* [How to Configure Webhooks](./webhooks-configure.md). Set up an endpoint, register it in the dashboard, and verify signatures.
* [Errors (API Reference)](https://docs.joinforage.app/reference/errors). Full error response schema and error code/message pairs.
* [Endpoint and SDK method errors](https://docs.joinforage.app/docs/sdk-errors#endpoint-and-sdk-method-errors). EBT-specific error codes returned by Forage endpoints.