---
updatedAt: 2026-05-07T18:17:26.000Z
agentTools:
  projectIndex: https://docs.joinforage.app/llms.txt
---

# Create a Payment

> ⚠️ Payment Creation Must Be Server-Side
>
> To keep your app secure, requests to create a Payment should only be generated on the server-side.

A `POST` request to `/payments/` tells Forage's servers how much to charge an existing `PaymentMethod`.

On success, the API responds with a Forage `Payment` object that represents the one-time charge. You need to pass the `ref` response value to an SDK function to authorize and capture the payment, one of:

- Forage JS: [`capturePayment()`](ref:capture-ebt-payment)
- Android: [`capturePayment()`](https://android.joinforage.app/forage-android/com.joinforage.forage.android.ecom.services/-forage-s-d-k/capture-payment)
- iOS: [`capturePayment()`](https://github.com/teamforage/forage-ios-sdk?tab=readme-ov-file#capture-an-ebt-payment)

> 📘 Use `customer_id` When Creating Payments
>
> Pass `customer_id` in the request to Create a `Payment`. `customer_id` helps Forage's servers more quickly identify and associate the correct customer with the `Payment`. While `customer_id` is not technically a required parameter, if you omit it then the request to create the `Payment` could take longer to process. **It is strongly recommended to pass `customer_id`.**
>
> Each customer should only have one unique `customer_id`. For example, if you create both a `Payment` and a `PaymentMethod` for the same customer, then the `customer_id` should be the same in both requests to ensure continuity of stored payment methods.

> ⚠️ Payments Expire After 30 Minutes
>
> `Payment` objects expire after 30 minutes. If a `Payment` is not captured or canceled within 30 minutes of when it's created, then it expires. To attempt the transaction again, create a new `Payment`.


# OpenAPI definition

```json
{
  "openapi": "3.0.0",
  "x-readme": {
    "explorer-enabled": false,
    "proxy-enabled": false
  },
  "info": {
    "title": "Forage Payments API",
    "description": "The Forage Payments API is a REST API for processing Electronic Benefits Transfer (EBT) payments (SNAP and EBT Cash) in your e-commerce or in-store application.\n\nProcessing any EBT payment, or checking an EBT card's balance, requires the cardholder's PIN. Federal regulations require all PIN entry to happen through a PCI-compliant, USDA-approved interface. Forage provides that interface, so EBT PIN collection always happens through a Forage-hosted surface (Forage Checkout or a Forage SDK), never directly in your own form. Some endpoints (for example, capture and balance) are only reachable through that surface because they require PIN data in the request.\n\nEBT rarely covers an entire order: items like delivery fees and non-eligible products can't be paid with SNAP or EBT Cash. You decide how to handle the remaining balance (split tender) and any credit or debit processing alongside the EBT portion.\n\nForage offers four integration options. Pick the one that fits your platform and engineering resources:\n\n1. **Fully Hosted Checkout.** Forage processes EBT and credit/debit through a Forage-hosted Checkout UI. Lowest engineering effort, and Forage absorbs most error handling. See the [Fully Hosted Checkout guide](https://docs.joinforage.app/docs/fully-hosted).\n2. **Custom Checkout.** Forage processes EBT; you handle split tender, taxes, and credit/debit in your own checkout flow. Best when you want minimal changes to your existing UX. See the [Custom Checkout guide](https://docs.joinforage.app/docs/custom).\n3. **Online SDKs.** Client-side SDKs for [web](https://docs.joinforage.app/docs/forage-js), [iOS](https://docs.joinforage.app/docs/ios), and [Android](https://docs.joinforage.app/docs/android) that collect EBT PINs in your app while keeping you out of PCI scope.\n4. **POS Terminal SDK.** Accept in-person EBT payments on an Android POS device. See the [POS Terminal guide](https://docs.joinforage.app/docs/forage-terminal-android).\n\nAs a general principle, any data created by your requests, or by your customers on a Forage-hosted surface, is retrievable through GET requests to the appropriate resource.\n\nHave more questions? Use our [contact form](https://www.joinforage.com/get-in-touch) to reach our sales and engineering support teams.\n",
    "contact": {
      "name": "API Support",
      "email": "engineering@joinforage.com"
    },
    "version": "2025-08-04"
  },
  "externalDocs": {
    "description": "Forage documentation",
    "url": "https://docs.joinforage.app/"
  },
  "servers": [
    {
      "url": "https://{environment}.joinforage.app",
      "variables": {
        "environment": {
          "default": "api.sandbox",
          "enum": [
            "api",
            "api.sandbox"
          ]
        }
      }
    }
  ],
  "security": [],
  "paths": {
    "/api/payments/": {
      "post": {
        "parameters": [
          {
            "$ref": "#/components/parameters/AuthenticationBearerTokenHeader"
          },
          {
            "$ref": "#/components/parameters/MerchantAccountHeader"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKeyHeader"
          },
          {
            "$ref": "#/components/parameters/APIVersionHeader"
          }
        ],
        "tags": [
          "Payments"
        ],
        "summary": "Create a Payment",
        "x-readme": {
          "code-samples": [
            {
              "language": "curl",
              "code": "curl --request POST \\\n    --url https://api.sandbox.joinforage.app/api/payments/ \\\n    --header 'Authorization: Bearer <api_key>' \\\n    --header 'Merchant-Account: <merchant-id>' \\\n    --header 'Idempotency-Key: <idempotency-key>' \\\n    --header 'accept: application/json' \\\n    --header 'content-type: application/json' \\\n    --data '\n{\n  \"amount\": 25.99,\n  \"funding_type\": \"ebt_snap\",\n  \"payment_method\": \"ac47392bb1\",\n  \"delivery_address\": {\n    \"city\": \"San Francisco\",\n    \"country\": \"US\",\n    \"line1\": \"1856 Market St.\",\n    \"zipcode\": \"94106\",\n    \"state\": \"CA\"\n  },\n  \"is_delivery\": true,\n  \"description\": \"An EBT payment\",\n  \"metadata\": {},\n  \"platform_fee\": 0.05,\n  \"platform_fixed_settlement\": 5.11,\n  \"merchant_fixed_settlement\": 5.95,\n  \"customer_id\": \"cus_1234567890\",\n  \"external_order_id\": \"<external-order-id>\",\n  \"merchant_destination_account\": \"1bdefaa456\",\n  \"pos_terminal\": {\n    \"provider_terminal_id\": \"tbd123\"\n  },\n  \"external_location_id\": \"6e3b2ff7-51c8-4c64-befa-2eac90f7c3e9\"\n}\n'\n"
            }
          ]
        },
        "description": "> ⚠️ Payment Creation Must Be Server-Side\n>\n> To keep your app secure, requests to create a Payment should only be generated on the server-side.\n\nA `POST` request to `/payments/` tells Forage’s servers how much to charge an existing `PaymentMethod`.\n\nOn success, the API responds with a Forage `Payment` object that represents the one-time charge. You need to pass the `ref` response value to an SDK function to authorize and capture the payment, one of:\n\n- Forage JS: [`capturePayment()`](https://docs.joinforage.app/reference/capture-ebt-payment)\n- Android: [`capturePayment()`](https://android.joinforage.app/forage-android/com.joinforage.forage.android.ecom.services/-forage-s-d-k/capture-payment)\n- iOS: [`capturePayment()`](https://github.com/teamforage/forage-ios-sdk?tab=readme-ov-file#capture-an-ebt-payment)\n\n> 📘 Use `customer_id` When Creating Payments\n>\n> Pass `customer_id` in the request to Create a `Payment`. `customer_id` helps Forage's servers more quickly identify and associate the correct customer with the `Payment`. While `customer_id` is not technically a required parameter, if you omit it then the request to create the `Payment` could take longer to process. **It is strongly recommended to pass `customer_id`.**\n>\n> Each customer should only have one unique `customer_id`. For example, if you create both a `Payment` and a `PaymentMethod` for the same customer, then the `customer_id` should be the same in both requests to ensure continuity of stored payment methods.\n\n> ⚠️ Payments Expire After 30 Minutes\n>\n> `Payment` objects expire after 30 minutes. If a `Payment` is not captured or canceled within 30 minutes of when it's created, then it expires. To attempt the transaction again, create a new `Payment`.\n",
        "operationId": "Create a payment (custom checkout)",
        "security": [
          {
            "OAuth2": [
              "pinpad_only"
            ]
          },
          {
            "BearerAuth": []
          }
        ],
        "requestBody": {
          "$ref": "#/components/requestBodies/CreatePayment"
        },
        "responses": {
          "200": {
            "description": "OK - Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PaymentResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponseObject"
                },
                "examples": {
                  "cannot_parse_request_body": {
                    "summary": "Cannot parse request body",
                    "value": {
                      "path": "/api/payments/",
                      "errors": [
                        {
                          "code": "cannot_parse_request_body",
                          "message": "Parsing payment_method field failed with message: Object with ref={payment_method_ref} does not exist.",
                          "source": {
                            "resource": "Payments"
                          }
                        }
                      ]
                    }
                  },
                  "amount_mismatch": {
                    "summary": "Amount mismatch",
                    "value": {
                      "path": "/api/payments/",
                      "errors": [
                        {
                          "code": "amount_mismatch",
                          "message": "Payment amount needs to equal to products amount. Payment amount: {payment_amount}, products amount: {products_amount}.",
                          "source": {
                            "resource": "Payments"
                          }
                        }
                      ]
                    }
                  },
                  "inconsistent_funding_and_payment_method": {
                    "summary": "Inconsistent funding and payment method",
                    "value": {
                      "path": "/api/payments/",
                      "errors": [
                        {
                          "code": "inconsistent_funding_and_payment_method",
                          "message": "Payment was posted with a funding_type of {funding_type}, but the payment_method is {card_type} card.",
                          "source": {
                            "resource": "Payments"
                          }
                        }
                      ]
                    }
                  },
                  "invalid_input_data": {
                    "summary": "Invalid input data",
                    "value": {
                      "path": "/api/payments/",
                      "errors": [
                        {
                          "code": "invalid_input_data",
                          "message": "Query parameter missing or incomplete.",
                          "source": {
                            "resource": "Payments"
                          }
                        }
                      ]
                    }
                  },
                  "card_not_reusable": {
                    "summary": "Card not reusable",
                    "value": {
                      "path": "/api/payments/",
                      "errors": [
                        {
                          "code": "card_not_reusable",
                          "message": "Payment method {payment_method_ref} is not reusable",
                          "source": {
                            "resource": "Payment_Methods",
                            "ref": "{payment_method_ref}"
                          }
                        }
                      ]
                    }
                  },
                  "different_ebt_card": {
                    "summary": "Different EBT Card",
                    "value": {
                      "path": "/api/payments/",
                      "errors": [
                        {
                          "code": "different_ebt_card",
                          "message": "Order {order_ref} already has EBT Payment {payment_ref} with payment_method {payment_method_ref}. Your request included payment_method {payment_method_ref}. You must use the same EBT payment_method for all EBT Payments on an Order",
                          "source": {
                            "resource": "Payment_Methods",
                            "ref": "{payment_method_ref}"
                          }
                        }
                      ]
                    }
                  },
                  "duplicate_funding_type": {
                    "summary": "Duplicate funding type",
                    "value": {
                      "path": "/api/payments/",
                      "errors": [
                        {
                          "code": "duplicate_funding_type",
                          "message": "Order {order_ref} already has payment {payment_ref} with funding_type {funding_type}. Please modify the existing payment object instead of adding new payments with the same funding_type",
                          "source": {
                            "resource": "Payments",
                            "ref": "{payment_ref}"
                          }
                        }
                      ]
                    }
                  },
                  "invalid_merchant_account": {
                    "summary": "Invalid merchant account",
                    "value": {
                      "path": "/api/payments/",
                      "errors": [
                        {
                          "code": "invalid_merchant_account",
                          "message": "Merchant account Merchant ID not valid.",
                          "source": {
                            "resource": "Merchants"
                          }
                        }
                      ]
                    }
                  },
                  "missing_idempotency_key": {
                    "summary": "Missing Idempotency Key",
                    "value": {
                      "path": "/api/payments/",
                      "errors": [
                        {
                          "code": "missing_idempotency_key",
                          "message": "You must include a value for the IDEMPOTENCY-KEY header in your requests to this endpoint.",
                          "source": {
                            "resource": "Idempotency_Key"
                          }
                        }
                      ]
                    }
                  },
                  "missing_merchant_account": {
                    "summary": "Missing Merchant Account",
                    "value": {
                      "path": "/api/payments/",
                      "errors": [
                        {
                          "code": "missing_merchant_account",
                          "message": "No merchant account was provided.",
                          "source": {
                            "resource": "Merchants"
                          }
                        }
                      ]
                    }
                  },
                  "settlement_greater_than_amount": {
                    "summary": "Settlement Greater Than Amount",
                    "value": {
                      "path": "/api/payments/",
                      "errors": [
                        {
                          "code": "settlement_greater_than_amount",
                          "message": "merchant_fixed_settlement + platform_fixed_settlement must be equal to or less than the amount charged. Fixed settlement charged of {settlement_amount} is greater than amount of {amount_charged}",
                          "source": {
                            "resource": "Payments"
                          }
                        }
                      ]
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponseObject"
                },
                "examples": {
                  "invalid_token": {
                    "summary": "Invalid token",
                    "value": {
                      "path": "/api/payments/",
                      "errors": [
                        {
                          "code": "invalid_token",
                          "message": "Incorrect authentication credentials.",
                          "source": {
                            "resource": "OAuth_Access_Tokens"
                          }
                        }
                      ]
                    }
                  }
                }
              }
            }
          },
          "409": {
            "description": "Conflict",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponseObject"
                },
                "examples": {
                  "cannot_change_request": {
                    "summary": "Cannot Change Request",
                    "value": {
                      "path": "/api/payments/",
                      "errors": [
                        {
                          "code": "cannot_change_request",
                          "message": "Two requests were submitted with the same idempotency key, but slightly different request bodies. Please use a new idempotency key if you intended to change the request body",
                          "source": {
                            "resource": "Idempotency_Key"
                          }
                        }
                      ]
                    }
                  }
                }
              }
            }
          },
          "423": {
            "$ref": "#/components/responses/Error423"
          },
          "429": {
            "description": "Too Many Requests",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponseObject"
                },
                "examples": {
                  "too_many_requests": {
                    "summary": "Too Many Requests",
                    "value": {
                      "path": "/api/payments/",
                      "errors": [
                        {
                          "code": "too_many_requests",
                          "message": "Request was throttled, please try again later.",
                          "source": {
                            "resource": "Payments"
                          }
                        }
                      ]
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponseObject"
                },
                "examples": {
                  "unknown_server_error": {
                    "summary": "Unknown Server Error",
                    "value": {
                      "path": "/api/payments/",
                      "errors": [
                        {
                          "code": "unknown_server_error",
                          "message": "Unknown exception from EBT network",
                          "source": {
                            "resource": "Unknown"
                          }
                        }
                      ]
                    }
                  }
                }
              }
            }
          },
          "503": {
            "description": "Service Unavailable",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponseObject"
                },
                "examples": {
                  "ebt_processor_timeout": {
                    "summary": "EBT processor timeout",
                    "value": {
                      "path": "/api/payments/",
                      "errors": [
                        {
                          "code": "ebt_processor_timeout",
                          "message": "Unable to contact EBT processor, please try again shortly.",
                          "source": {
                            "resource": "Payments",
                            "ref": ""
                          }
                        }
                      ]
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "ErrorsArray": {
        "type": "array",
        "description": "An array with information about the error.",
        "items": {
          "type": "object",
          "properties": {
            "code": {
              "type": "string",
              "description": "A short string that represents the error."
            },
            "message": {
              "type": "string",
              "description": "A developer-facing message with more details about the error, not to be displayed to customers."
            },
            "source": {
              "type": "object",
              "properties": {
                "resource": {
                  "type": "string",
                  "description": "The type of the Forage resource involved in the error."
                },
                "ref": {
                  "type": "string",
                  "description": "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": {
              "type": "object",
              "description": "Additional details about the error, if applicable."
            }
          }
        },
        "example": []
      },
      "ErrorResponseObject": {
        "type": "object",
        "description": "An object that includes details about the error.",
        "properties": {
          "path": {
            "type": "string",
            "description": "The requested endpoint."
          },
          "errors": {
            "$ref": "#/components/schemas/ErrorsArray"
          }
        }
      },
      "PaymentRequest": {
        "type": "object",
        "description": "This object represents a single payment. It is associated with a single payment method.",
        "properties": {
          "amount": {
            "type": "string",
            "format": "decimal",
            "description": "A positive decimal number that represents how much to charge the [`PaymentMethod`](https://docs.joinforage.app/reference/payment-methods) in USD. Precision is supported to the penny. 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."
          },
          "funding_type": {
            "type": "string",
            "description": "The payment instrument type. Use this field to differentiate between a SNAP (`ebt_snap`) and an EBT Cash (`ebt_cash`) charge on the same EBT Card. If you need to charge both funding types, then create a `Payment` for each charge. Use `credit_payfac` for all charges to HSA/FSA cards. `credit_tpp` is the funding type assigned to non-EBT payment objects created via a Fully Hosted Checkout integration.",
            "enum": [
              "ebt_snap",
              "ebt_cash",
              "credit_tpp",
              "credit_payfac",
              "benefit",
              "wic"
            ]
          },
          "payment_method": {
            "type": "string",
            "description": "The unique reference hash for the existing Forage [`PaymentMethod`](https://docs.joinforage.app/reference/payment-methods) that is to be charged in this transaction.\n\n⚠️ **Exception**: POS integrations do not need to provide a `payment_method` when creating a payment.\n"
          },
          "delivery_address": {
            "$ref": "#/components/schemas/DeliveryAddressData"
          },
          "is_delivery": {
            "type": "boolean",
            "description": "⚠️ **Exception**: If the purchase is made in-store via a POS Terminal, then a `is_delivery` is not required when creating a `Payment`.\n\nWhether the order is for delivery or pickup. This information is required per FNS regulations. Defaults to `false` if not provided.\n"
          },
          "description": {
            "type": "string",
            "description": "A description of the payment."
          },
          "metadata": {
            "$ref": "#/components/schemas/MetadataObject"
          },
          "platform_fee": {
            "type": "string",
            "format": "decimal",
            "description": "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": {
            "type": "string",
            "format": "decimal",
            "description": "The fixed amount in USD that a platform takes from EBT Cash payments prior to splitting by the `platform_fee`. Precision is supported to the penny."
          },
          "merchant_fixed_settlement": {
            "type": "string",
            "format": "decimal",
            "description": "The fixed amount in USD that should be restored to the merchant from EBT Cash payments prior to splitting by the `platform_fee`. Precision is supported to the penny."
          },
          "tpp_lookup_id": {
            "type": "string",
            "description": "An identifier for the credit/debit TPP.\n\nFor Stripe integrations, the client secret for a Stripe `PaymentIntent`.\n",
            "example": "pi_1DpdZq2eZvKYlo2CAYyzTr8j_secret_lxr4crBJP4txbrg7sqit0XQQO"
          },
          "customer_id": {
            "$ref": "#/components/schemas/CustomerIDField"
          },
          "external_order_id": {
            "$ref": "#/components/schemas/ExternalOrderIDField"
          },
          "merchant_destination_account": {
            "type": "string",
            "description": "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.\n\nDefaults to the hash for the default merchant bank account if not provided.\n"
          },
          "pos_terminal": {
            "type": "object",
            "description": "**⚠️  This param is only supported for POS Terminal integrations. Do not use this param for online transactions.**\n\nAn object that details information about the POS Terminal that processes the payment.\n",
            "properties": {
              "provider_terminal_id": {
                "type": "string",
                "description": "A unique string that identifies the POS Terminal."
              }
            }
          },
          "external_location_id": {
            "$ref": "#/components/schemas/ExternalLocationIDField"
          }
        },
        "required": [
          "funding_type"
        ]
      },
      "PaymentResponse": {
        "allOf": [
          {
            "$ref": "#/components/schemas/PaymentRequest"
          },
          {
            "type": "object",
            "properties": {
              "ref": {
                "type": "string",
                "description": "A unique reference hash for the Forage `Payment` object.\n\n_Note:_ `receipt.ref_number` equals `ref`.\n\nYou need to pass this value to the front-end SDK method that captures the payment.\n"
              },
              "merchant": {
                "type": "string",
                "description": "A string that represents a unique merchant ID that Forage provides during onboarding."
              },
              "status": {
                "type": "string",
                "description": "The status of the `Payment`. One of:\n\n- `canceled`: The `Payment`object can't be used.\n- `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.\n- `processing`: The outcome of the `Payment` is pending.\n- `requires_confirmation`: The `Payment` hasn't been submitted for processing.\n- `succeeded`: The `Payment` has been successfully processed and will be included in settlement. It can't be changed.\n- `authorized`: The `Payment` has been authorized, but not yet captured. Only applicable to HSA payments.\n",
                "enum": [
                  "requires_confirmation",
                  "processing",
                  "canceled",
                  "succeeded",
                  "failed",
                  "authorized"
                ]
              },
              "created": {
                "type": "string",
                "format": "date-time",
                "description": "A UTC timestamp of when the `Payment` was created, represented as an [ISO 8601 date-time](https://www.iso.org/iso-8601-date-and-time-format.html) string."
              },
              "updated": {
                "type": "string",
                "format": "date-time",
                "description": "A UTC timestamp of that indicates when the `Payment` was last modified, represented as an [ISO 8601 date-time](https://www.iso.org/iso-8601-date-and-time-format.html) string."
              },
              "expires_at": {
                "type": "string",
                "format": "date-time",
                "nullable": true,
                "description": "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.\n\nIf the `status` of the `Payment` is `succeeded` or `canceled`, then the `expires_at` value is `null`.\n"
              },
              "success_date": {
                "type": "string",
                "format": "date-time",
                "nullable": true,
                "description": "A UTC timestamp of when the `Payment` was successfully processed, represented as an [ISO 8601 date-time](https://www.iso.org/iso-8601-date-and-time-format.html) string. This value is `null` until the Payment enters the `succeeded` or `partial_capture` states."
              },
              "refunds": {
                "type": "array",
                "description": "References to the `Refund`s attached to this payment. The format depends on the `with_refunds` query parameter:\n\n- **Default behavior** (when `with_refunds` is `false` or omitted): Array of refund reference strings\n- **Expanded behavior** (when `with_refunds=true`): Array of full `Refund` objects with complete refund details\n",
                "items": {
                  "type": "string",
                  "description": "Refund reference string"
                }
              },
              "receipt": {
                "type": "object",
                "nullable": true,
                "description": "Most of the information that you're required to display to the customer, according to FNS regulations.\n\nThis field is `null` if the data that populates the receipt is not yet available.\n\nThe total amount paid by the customer is `snap_amount` + `ebt_cash_amount` + `other_amount`. This amount will be settled with the merchant after applying Forage's fees.\n"
              },
              "last_processing_error": {
                "type": "object",
                "nullable": true,
                "description": "The `code` and `message` values corresponding to the most recent [Payments API error](https://docs.joinforage.app/reference/errors#payments-api-errors). Always `null` when the `Payment` is created."
              },
              "previous_errors": {
                "$ref": "#/components/schemas/ErrorsArray"
              },
              "address_postal_code_check": {
                "type": "string",
                "nullable": true,
                "description": "The result of any check done on the delivery address zip code. One of:\n- `pass`: The provided information is correct and matches the data on file with the card issuer.\n- `fail`: The provided information is incorrect and does not match the data on file.\n- `unavailable`: The card issuer will not perform the check.\n- `unchecked`: The information was provided but has not yet been checked by the card issuer.\n",
                "enum": [
                  "pass",
                  "fail",
                  "unavailable",
                  "unchecked"
                ],
                "example": "pass"
              },
              "cvc_check": {
                "type": "string",
                "nullable": true,
                "description": "The result of any check done on the CVC. One of:\n- `pass`: The provided information is correct and matches the data on file with the card issuer.\n- `fail`: The provided information is incorrect and does not match the data on file.\n- `unavailable`: The card issuer will not perform the check.\n- `unchecked`: The information was provided but has not yet been checked by the card issuer.\n",
                "enum": [
                  "pass",
                  "fail",
                  "unavailable",
                  "unchecked"
                ],
                "example": "pass"
              },
              "delivery_address": {
                "type": "object",
                "nullable": true,
                "description": "The delivery or pickup address for the order, passed to the EBT network. Returns an address object with `line1`, `line2`, `city`, `state`, `zipcode`, and `country`. Null when no delivery address is set."
              },
              "is_delivery": {
                "type": "boolean",
                "nullable": true,
                "description": "Whether the order is for delivery or pickup. Null when not specified."
              }
            },
            "required": [
              "ref",
              "status",
              "created",
              "updated"
            ]
          }
        ],
        "example": {
          "amount": "25.99",
          "funding_type": "ebt_snap",
          "payment_method": "ac47392bb1",
          "delivery_address": {
            "city": "San Francisco",
            "country": "US",
            "line1": "1856 Market St.",
            "zipcode": "94106",
            "state": "CA"
          },
          "is_delivery": true,
          "description": "An EBT Payment",
          "metadata": {},
          "platform_fee": "0.05",
          "platform_fixed_settlement": "5.11",
          "merchant_fixed_settlement": "5.95",
          "customer_id": "cus_1234567890",
          "external_order_id": "1f2ee410-5b47-4130-aec2-40f5eb2108f5",
          "merchant_destination_account": "1bdefaa456",
          "pos_terminal": {
            "provider_terminal_id": "tbd123"
          },
          "external_location_id": "6e3b2ff7-51c8-4c64-befa-2eac90f7c3e9",
          "ref": "cc3175bfea",
          "merchant": "9000055",
          "status": "requires_confirmation",
          "created": "2021-06-16T00:11:50.000000Z",
          "updated": "2021-06-16T00:11:50.000000Z",
          "expires_at": "2021-06-16T00:41:50.000000Z",
          "success_date": "2021-06-16T00:11:50.000000Z",
          "refunds": [
            "ac47392bb1"
          ],
          "receipt": {
            "ref_number": "cc3175bfea",
            "is_voided": true,
            "snap_amount": "25.99",
            "ebt_cash_amount": "10.99",
            "other_amount": "5.99",
            "sales_tax_applied": "5.16",
            "balance": {
              "snap": "72.94",
              "non_snap": "32.16",
              "updated": "2021-06-16T00:11:50.000000Z"
            },
            "last_4": "3456",
            "message": "Approved",
            "transaction_type": "Payment",
            "created": "2021-06-16T00:11:50.000000Z"
          },
          "last_processing_error": null,
          "previous_errors": []
        }
      },
      "DeliveryAddressData": {
        "type": "object",
        "required": [
          "line1",
          "zipcode"
        ],
        "description": "⚠️ **Exception**: If the purchase is made in-store via a POS Terminal, then a `delivery_address` is not required when creating a `Payment`.\n\nThe 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.\n",
        "properties": {
          "city": {
            "type": "string",
            "description": "The name of the city."
          },
          "country": {
            "type": "string",
            "description": "Either `us` or `US`. Defaults to `US` if not provided."
          },
          "line1": {
            "type": "string",
            "description": "The first line of the street address."
          },
          "line2": {
            "type": "string",
            "nullable": true,
            "description": "The second line of the street address."
          },
          "zipcode": {
            "type": "string",
            "description": "The zip or postal code."
          },
          "state": {
            "type": "string",
            "description": "The two-letter abbreviation, can be upper or lowercase, for the US state."
          }
        }
      },
      "CustomerIDField": {
        "type": "string",
        "maxLength": 64,
        "description": "**⚠️ If you’re integrating Forage with a POS Terminal, then do not use this param. It is only supported for online transactions.**\n\nA unique identifier for the end customer making the payment.\n\nForage automatically adds the `customer_id` to the Session's corresponding `Order` and `OrderPayments`.\n\nThis 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. **It is strongly recommended to pass customer_id.**\n\nIf you're providing your internal customer ID, then we recommend that you hash the value before sending it on the payload.\n\nEach customer should only have one unique `customer_id`. For example, if you create both a `PaymentMethod` and a Forage `Session` (Fully Hosted or Custom) or `Payment` (SDK) for the same customer, then the `customer_id` should be the same in both requests to ensure continuity of stored payment methods.\n"
      },
      "ExternalOrderIDField": {
        "type": "string",
        "maxLength": 64,
        "description": "A unique identifier for the order as created by the merchant or platform (not Forage).\n\nWhen 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.\n\n**You must build with Forage Version `2023-05-15` or later to use `external_order_id`.** Either pass `2023-05-15` as the `API-Version` header on a per request basis, or set the version for all requests in the Forage dashboard.\n"
      },
      "ExternalLocationIDField": {
        "type": "string",
        "description": "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.\n",
        "example": "6e3b2ff7-51c8-4c64-befa-2eac90f7c3e9"
      },
      "MetadataObject": {
        "type": "object",
        "description": "A required object containing merchant-defined key-value pairs to provide additional context for the payment.\n\nMerchants should use this field to store **reference information** relevant to the transaction (for example, order details, system identifiers, or tracking data). This helps link the payment to records within their system.\n\nPass an empty object (`{}`) if no additional information is available.\n\n> ⚠️ Personally Identifiable Information\n>\n> **Do not include personally identifiable information (PII)** such as names, emails, or payment details.\n"
      }
    },
    "requestBodies": {
      "CreatePayment": {
        "content": {
          "application/json": {
            "schema": {
              "allOf": [
                {
                  "$ref": "#/components/schemas/PaymentRequest"
                },
                {
                  "required": [
                    "amount",
                    "funding_type",
                    "payment_method",
                    "delivery_address",
                    "is_delivery",
                    "description",
                    "metadata"
                  ]
                }
              ]
            }
          }
        }
      }
    },
    "responses": {
      "Error423": {
        "description": "__Locked__ - The request could not be completed because the target resource is currently locked.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponseObject"
            },
            "examples": {
              "resource_locked": {
                "summary": "Resource Locked",
                "value": {
                  "path": "/api/example_path/",
                  "errors": [
                    {
                      "code": "resource_locked",
                      "message": "Request could not be completed because the resource is currently locked. Please try again later.",
                      "source": {
                        "resource": "Idempotency_Key",
                        "ref": ""
                      }
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "parameters": {
      "AuthenticationBearerTokenHeader": {
        "name": "Authorization",
        "in": "header",
        "description": "An OAuth 2.0 [authentication token](https://docs.joinforage.app/docs/authentication#authentication-tokens) that validates the request. Send a `POST` to the [`/o/token/`](https://docs.joinforage.app/reference/create-authentication-token) endpoint to generate an authentication token. Pass the token in this header after the word `Bearer` and a whitespace, for example `Bearer <api_key>`.",
        "schema": {
          "type": "string"
        },
        "required": true
      },
      "MerchantAccountHeader": {
        "name": "Merchant-Account",
        "in": "header",
        "description": "A unique merchant ID that Forage provides during onboarding, as in `123ab45c67`. The Merchant ID can be found in the Forage [sandbox](https://dashboard.sandbox.joinforage.app/login/) or [production](https://dashboard.joinforage.app/login/) dashboard.",
        "schema": {
          "type": "string"
        },
        "required": true
      },
      "IdempotencyKeyHeader": {
        "name": "Idempotency-Key",
        "in": "header",
        "description": "An alphanumeric key that clients can use to identify repeated requests that are dropped in transit. Generate a distinct key for every unique request and only re-use keys for retries.",
        "schema": {
          "type": "string"
        },
        "required": true
      },
      "APIVersionHeader": {
        "name": "API-Version",
        "in": "header",
        "description": "The [Forage version](https://docs.joinforage.app/reference/version-history), represented as a string with the format of a `YYYY-MM-DD` date.\n\nIf not specified in the request header, then the version defaults to the value set in the Forage dashboard.\n",
        "schema": {
          "type": "string"
        },
        "required": false
      }
    },
    "securitySchemes": {
      "OAuth2": {
        "type": "oauth2",
        "description": "Pass the access token in the 'Authorization' header with the format \"Bearer ${token}\", i.e. the word \"Bearer\" and your access token from the /o/token/ API, separated by whitespace.\n",
        "flows": {
          "password": {
            "tokenUrl": "/o/token/",
            "scopes": {
              "hosted_checkout": "Scope for tokens used by merchant applications which allow Forage to manage split tender processing (i.e. EBT + Credit/Debit).\n",
              "pinpad_only": "Scope for tokens used by merchant applications which manage their own split tender (i.e. Forage Checkout is used only for EBT processing).\n"
            }
          },
          "clientCredentials": {
            "tokenUrl": "/o/token/",
            "scopes": {
              "internal": "Scope for tokens used by Forage internal applications.\n",
              "pin-protected": "Scope for tokens which can access secure storage.\n",
              "disbursement": "Scope for tokens which can disburse money to merchants.\n"
            }
          }
        }
      },
      "BearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "description": "Pass the access token in the 'Authorization' header with the format \"Bearer ${token}\", i.e. the word \"Bearer\" and your JWT bearer token from the /api/session_token/ end-point, separated by whitespace.\n"
      }
    }
  }
}
```

# Sibling pages

* [Retrieve all Payments for a merchant order ID](https://docs.joinforage.app/reference/retrieve-all-payments-for-merchant-order-id.md)
* [Retrieve a Payment](https://docs.joinforage.app/reference/get-payment-details.md)
* [Deferred Capture](https://docs.joinforage.app/reference/deferred-capture-1.md)
* [Update a Payment](https://docs.joinforage.app/reference/update-a-payment.md)
* [Testing](https://docs.joinforage.app/reference/testing-endpoints.md)
* [Cancel or Void a Payment](https://docs.joinforage.app/reference/cancel-a-payment.md)
* [Authorize a Payment](https://docs.joinforage.app/reference/authorize-a-payment.md)
* [Void a Payment](https://docs.joinforage.app/reference/void-a-payment-custom-checkout.md)