HomeGuidesReferenceChangelog↗ Forage Dashboard
Log In
Guides

Quickstart

Create a session token

Your server must create a session token before your client app can initialize Forage Inline Checkout. Keep your Forage authentication token on your server and expose a backend route that your client app can call to request a session token.

A successful request to /session_token/ returns a temporary session token. Session tokens expire after 15 minutes, so create one shortly before rendering checkout.

Below is an example request and response with added context:

Server Request

curl --request POST \
     --url https://api.sandbox.joinforage.app/api/session_token/ \
     --header 'Accept: application/json' \
     --header 'Authorization: Bearer <authentication-token>' \
     --header 'Merchant-Account: <merchant-id>' \
     --header 'Content-Type: application/x-www-form-urlencoded'
import requests

response = requests.post(
    "https://api.sandbox.joinforage.app/api/session_token/",
    headers={
        "Accept": "application/json",
        "Authorization": "Bearer <authentication-token>",
        "Merchant-Account": "<merchant-id>",
        "Content-Type": "application/x-www-form-urlencoded",
    },
)
print(response.json())
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;

HttpClient client = HttpClient.newHttpClient();

HttpRequest request = HttpRequest.newBuilder()
    .uri(URI.create("https://api.sandbox.joinforage.app/api/session_token/"))
    .header("Accept", "application/json")
    .header("Authorization", "Bearer <authentication-token>")
    .header("Merchant-Account", "<merchant-id>")
    .header("Content-Type", "application/x-www-form-urlencoded")
    .POST(HttpRequest.BodyPublishers.noBody())
    .build();

HttpResponse<String> response = client.send(
    request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
const response = await fetch(
  "https://api.sandbox.joinforage.app/api/session_token/",
  {
    method: "POST",
    headers: {
      Accept: "application/json",
      Authorization: "Bearer <authentication-token>",
      "Merchant-Account": "<merchant-id>",
      "Content-Type": "application/x-www-form-urlencoded",
    },
  }
);
const data = await response.json();
console.log(data);
require 'net/http'
require 'json'

uri = URI("https://api.sandbox.joinforage.app/api/session_token/")
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true

request = Net::HTTP::Post.new(uri.path)
request["Accept"] = "application/json"
request["Authorization"] = "Bearer <authentication-token>"
request["Merchant-Account"] = "<merchant-id>"
request["Content-Type"] = "application/x-www-form-urlencoded"

response = http.request(request)
puts JSON.parse(response.body)

Required Headers:

  • Authorization: A Forage authentication token prefixed with Bearer. Generate and store this token on your server; never expose it in client-side code.
  • Merchant-Account: The unique merchant ID that Forage provides during onboarding. Use the same merchant ID when you instantiate Checkout.

Response

{
  "token": "sandbox_eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}
  • token: Pass this value to the sessionToken property when you instantiate Checkout in your client app.

Add Checkout in your app

Add the Forage Checkout SDK for your client platform:

npm install @forage/checkout-sdk
// Package.swift
dependencies: [
  .package(
    url: "<Forage Checkout SDK package URL>",
    from: "<version>"
  )
]
// build.gradle.kts
dependencies {
    implementation("com.joinforage:checkout-sdk:<version>")
}

Initialize Checkout using the SDK for your client platform. Pass the order details through config.data, along with the session token returned by your server and the merchant ID used to create it.

import { Checkout } from "@forage/checkout-sdk";

<Checkout
  config={{
    action: "checkout",
    data: {
      {
        snapTotal: 25.99,
        ebtCashTotal: 5.99,
        remainingTotal: 10.99,
        platformFee: 0.05,
        productList: [
          {
            name: "Apple",
            upc: "033383087375",
            unitPrice: 1.99,
            quantity: 3,
            eligibility: "snap",
            taxesCharged: 3.33,
            taxesExempted: 0.00
          },
          {
            name: "Vitamin C",
            upc: "04126001300",
            unitPrice: 12.99,
            quantity: 1,
            eligibility: "non_ebt",
            taxesCharged: 1.83,
            taxesExempted: 0.50
          }
        ],
        deliveryAddress: {
          city: "Los Angeles",
          country: "US",
          line1: "4121 Santa Monica Blvd",
          line2: "Unit 513",
          zipcode: "90029",
          state: "CA"
        },
        isDelivery: true,
        supportedBenefits: [
          "snap",
          "ebt_cash",
          "non_ebt"
        ],
        customerId: "cus_AJ6yA7mRH34mJT"
      },
    },
    onInit={(data) => {
    	// Send data.ref to your server for verification.
		}}
		onComplete={(data) => {
    	// Send data.ref to your server for verification, then update your UI.
    }}
    onCancel={(data) => {
      // Send data.ref to your server for verification, then update your UI.
    }}
  }}
  sessionToken="sandbox_..."
  merchantId="abc123"
/>
import ForageCheckoutSDK

let checkout = Checkout(
  config: CheckoutConfig(
    action: "checkout",
    data: CheckoutData(
      snapTotal: 25.99,
      ebtCashTotal: 5.99,
      remainingTotal: 10.99,
      platformFee: 0.05,
      productList: [
        CheckoutProduct(
          name: "Apple",
          upc: "033383087375",
          unitPrice: 1.99,
          quantity: 3,
          eligibility: "snap",
          taxesCharged: 3.33,
          taxesExempted: 0.00
        ),
        CheckoutProduct(
          name: "Vitamin C",
          upc: "04126001300",
          unitPrice: 12.99,
          quantity: 1,
          eligibility: "non_ebt",
          taxesCharged: 1.83,
          taxesExempted: 0.50
        )
      ],
      deliveryAddress: DeliveryAddress(
        city: "Los Angeles",
        country: "US",
        line1: "4121 Santa Monica Blvd",
        line2: "Unit 513",
        zipcode: "90029",
        state: "CA"
      ),
      isDelivery: true,
      supportedBenefits: ["snap", "ebt_cash", "non_ebt"],
      customerID: "cus_AJ6yA7mRH34mJT"
    ),
    onInit: { data in
			// Send data.ref to your server for verification.
		},
		onComplete: { data in
      // Send data.ref to your server for verification, then update your UI.
    },
    onCancel: { data in
      // Send data.ref to your server for verification, then update your UI.
    }
  ),
  sessionToken: "sandbox_...",
  merchantID: "abc123",
)
import com.joinforage.checkout.Checkout
import com.joinforage.checkout.CheckoutAddress
import com.joinforage.checkout.CheckoutConfig
import com.joinforage.checkout.CheckoutData
import com.joinforage.checkout.CheckoutProduct

val checkout = Checkout(
    config = CheckoutConfig(
        action = "checkout",
        data = CheckoutData(
            snapTotal = 25.99,
            ebtCashTotal = 5.99,
            remainingTotal = 10.99,
            platformFee = 0.05,
            productList = listOf(
                CheckoutProduct(
                    name = "Apple",
                    upc = "033383087375",
                    unitPrice = 1.99,
                    quantity = 3,
                    eligibility = "snap",
                    taxesCharged = 3.33,
                    taxesExempted = 0.00
                ),
                CheckoutProduct(
                    name = "Vitamin C",
                    upc = "04126001300",
                    unitPrice = 12.99,
                    quantity = 1,
                    eligibility = "non_ebt",
                    taxesCharged = 1.83,
                    taxesExempted = 0.50
                )
            ),
            deliveryAddress = CheckoutAddress(
                city = "Los Angeles",
                country = "US",
                line1 = "4121 Santa Monica Blvd",
                line2 = "Unit 513",
                zipcode = "90029",
                state = "CA"
            ),
            isDelivery = true,
            supportedBenefits = listOf("snap", "ebt_cash", "non_ebt"),
            customerId = "cus_AJ6yA7mRH34mJT"
        ),
	      onInit = { data ->
					// Send data.ref to your server for verification.
				},
				onComplete = { data ->
            // Send data.ref to your server for verification, then update your UI.
        },
        onCancel = { data ->
            // Send data.ref to your server for verification, then update your UI.
        }
    ),
    sessionToken = "sandbox_...",
    merchantId = "abc123",
)
  • config.action: The Checkout operation to perform. Pass checkout to start an inline checkout flow.
  • config.data: The order details that Forage uses to create and process the Order.
  • sessionToken: The temporary token returned by your server's request to /session_token/.
  • merchantId (merchantID on iOS): The merchant ID used to create the session token.
  • onInit: Called after the checkout session is created. The callback receives the created Order object, consistent with the response from POST /sessions.
  • onComplete: Called after the customer successfully completes checkout. The callback receives the completed Order object.
  • onCancel: Called after checkout is canceled. The callback receives the canceled Order object, consistent with the response from POST /orders/{order_ref}/cancel/.

The properties in config.data correspond to the request body properties used to create an order. Web uses the API's snake_case field names; the native SDKs expose the same fields with platform-standard casing:

  • snapTotal: The portion of the order total that the customer can pay with SNAP.
  • ebtCashTotal: The portion of the order total that the customer can pay with EBT Cash.
  • remainingTotal: The portion of the order total that the customer must pay with a non-EBT payment method.
  • platformFee: The percentage of each payment charged as a platform fee, when applicable.
  • productList: The products included in the order, including their prices, quantities, eligibility, and tax details.
  • deliveryAddress: The address where the order will be delivered or picked up. Required by FNS.
  • isDelivery: Whether the order will be delivered or picked up. Required by FNS.
  • supportedBenefits: The payment method types available during checkout.
  • customerID (iOS) / customerId (Web and Android): Your identifier for the customer.

onInit response

After the checkout session is created, Forage calls onInit with the created Order object:

{
  "snap_total": 25.99,
  "ebt_cash_total": 5.99,
  "remaining_total": 10.99,
  "platform_fee": 0.05,
  "product_list": [
    {
      "name": "Apple",
      "upc": "033383087375",
      "unit_price": 1.99,
      "quantity": 3,
      "eligibility": "snap",
      "taxes_charged": 3.33,
      "taxes_exempted": 0.00
    },
    {
      "name": "Vitamin C",
      "upc": "04126001300",
      "unit_price": 12.99,
      "quantity": 1,
      "eligibility": "non_ebt",
      "taxes_charged": 1.83,
      "taxes_exempted": 0.50
    }
  ],
  "delivery_address": {
    "city": "Los Angeles",
    "country": "US",
    "line1": "4121 Santa Monica Blvd",
    "line2": "Unit 513",
    "zipcode": "90029",
    "state": "CA"
  },
  "is_delivery": true,
  "supported_benefits": [
    "snap",
    "ebt_cash",
    "non_ebt"
  ],
  "customer_id": "cus_AJ6yA7mRH34mJT",
  "ref": "93410bcaff",
  "status": "draft",
  "payments": [],
  "refunds": [],
  "receipt": null
}
  • ref: Store a reference to this Order object for your records and send it to your server for verification.
  • status: The current state of the order. A newly created order has a status of draft.

onComplete response

After the customer successfully completes checkout, Forage calls onComplete with the completed Order object:

{
  "snap_total": 25.99,
  "ebt_cash_total": 5.99,
  "remaining_total": 10.99,
  "platform_fee": 0.05,
  "product_list": [
    {
      "name": "Apple",
      "upc": "033383087375",
      "unit_price": 1.99,
      "quantity": 3,
      "eligibility": "snap",
      "taxes_charged": 3.33,
      "taxes_exempted": 0.00
    },
    {
      "name": "Vitamin C",
      "upc": "04126001300",
      "unit_price": 12.99,
      "quantity": 1,
      "eligibility": "non_ebt",
      "taxes_charged": 1.83,
      "taxes_exempted": 0.50
    }
  ],
  "delivery_address": {
    "city": "Los Angeles",
    "country": "US",
    "line1": "4121 Santa Monica Blvd",
    "line2": "Unit 513",
    "zipcode": "90029",
    "state": "CA"
  },
  "is_delivery": true,
  "supported_benefits": [
    "snap",
    "ebt_cash",
    "non_ebt"
  ],
  "customer_id": "cus_AJ6yA7mRH34mJT",
  "ref": "93410bcaff",
  "status": "succeeded",
  "payments": [],
  "refunds": [],
  "receipt": {
    "ref_number": "93410bcaff",
    "snap_amount": "25.99",
    "ebt_cash_amount": "5.99",
    "other_amount": "10.99",
    "sales_tax_applied": "5.16",
    "balance": {
      "snap": "25.99",
      "non_snap": "10.99",
      "updated": "2021-06-16T00:11:50.000000Z-07:00"
    },
    "last_4": "3456",
    "message": "Approved",
    "transaction_type": "Purchase",
    "created": "2021-06-16T00:11:50.000000Z-07:00"
  }
}
  • ref: Store a reference to this Order object for your records and send it to your server for verification.
  • status: The current state of the order. A successfully completed order has a status of succeeded.
  • receipt: The transaction details required to build your receipt or confirmation screen.

onCancel response

If the customer cancels checkout before the order is completed, Forage calls onCancel with the canceled Order object:

{
  "snap_total": 25.99,
  "ebt_cash_total": 5.99,
  "remaining_total": 10.99,
  "platform_fee": 0.05,
  "product_list": [
    {
      "name": "Apple",
      "upc": "033383087375",
      "unit_price": 1.99,
      "quantity": 3,
      "eligibility": "snap",
      "taxes_charged": 3.33,
      "taxes_exempted": 0.00
    },
    {
      "name": "Vitamin C",
      "upc": "04126001300",
      "unit_price": 12.99,
      "quantity": 1,
      "eligibility": "non_ebt",
      "taxes_charged": 1.83,
      "taxes_exempted": 0.50
    }
  ],
  "delivery_address": {
    "city": "Los Angeles",
    "country": "US",
    "line1": "4121 Santa Monica Blvd",
    "line2": "Unit 513",
    "zipcode": "90029",
    "state": "CA"
  },
  "is_delivery": true,
  "supported_benefits": [
    "snap",
    "ebt_cash",
    "non_ebt"
  ],
  "customer_id": "cus_AJ6yA7mRH34mJT",
  "ref": "93410bcaff",
  "status": "canceled",
  "payments": [],
  "refunds": [],
  "receipt": null
}
  • ref: Store a reference to this Order object for your records and send it to your server for verification.
  • status: A canceled order has a status of canceled.

How to initialize Checkout with a saved payment method

If you recognize a customer, you can initialize Checkout with an EBT payment method that the customer saved during a previous checkout. Pass the payment method reference as ebt_payment_method on Web or ebtPaymentMethod on iOS and Android.

import { Checkout } from "@forage/checkout-sdk";

<Checkout
  config={{
    action: "checkout",
    data: {
      {
        deliveryAddress: {
          country: "US",
          line1: "4121 Santa Monica Blvd",
          city: "Los Angeles",
          zipcode: "90029",
         	state: "CA"
        },
        productList: [],
        isDelivery: true,
        supportedBenefits: [
          "snap",
          "ebt_cash",
          "non_ebt"
        ],
        ebtPaymentMethod: "f629aa1bf3"
      },
    },
    onInit={(data) => {
			// Send data.ref to your server for verification.
		}},
		onComplete={(data) => {
      // Send data.ref to your server for verification, then update your UI.
    }},
    onCancel={(data) => {
      // Send data.ref to your server for verification, then update your UI.
    }}
  }}
  sessionToken="sandbox_..."
  merchantId="abc123"
/>
import ForageCheckoutSDK

let checkout = Checkout(
  config: CheckoutConfig(
    action: "checkout",
    data: CheckoutData(
      deliveryAddress: DeliveryAddress(
        country: "US",
        line1: "4121 Santa Monica Blvd",
        city: "Los Angeles",
        zipcode: "90029",
        state: "CA"
      ),
      productList: [],
      isDelivery: true,
      supportedBenefits: ["snap", "ebt_cash", "non_ebt"],
      ebtPaymentMethod: "f629aa1bf3"
    ),
		onInit: { data in
      // Send data.ref to your server for verification.
    },
		onComplete: { data in
      // Send data.ref to your server for verification, then update your UI.
    },
    onCancel: { data in
      // Send data.ref to your server for verification, then update your UI.
    }
  ),
  sessionToken: "sandbox_...",
  merchantID: "abc123",
)
import com.joinforage.checkout.Checkout
import com.joinforage.checkout.CheckoutAddress
import com.joinforage.checkout.CheckoutConfig
import com.joinforage.checkout.CheckoutData

val checkout = Checkout(
    config = CheckoutConfig(
        action = "checkout",
        data = CheckoutData(
            deliveryAddress = CheckoutAddress(
                country = "US",
                line1 = "4121 Santa Monica Blvd",
                city = "Los Angeles",
                zipcode = "90029",
                state = "CA"
            ),
            productList = emptyList(),
            isDelivery = true,
            supportedBenefits = listOf("snap", "ebt_cash", "non_ebt"),
            ebtPaymentMethod = "f629aa1bf3"
        ),
				onInit = { data ->
            // Send data.ref to your server for verification.
        },
				onComplete = { data ->
            // Send data.ref to your server for verification, then update your UI.
        },
        onCancel = { data ->
            // Send data.ref to your server for verification, then update your UI.
        }
    ),
    sessionToken = "sandbox_...",
    merchantId = "abc123",
)

The onComplete and onCancel callbacks return the same Order objects described above. Verify the final outcome on your server with GET /orders/{ref} (/get-order) or through a verified webhook event.


Did this page help you?