HomeGuidesReference↗ Forage Dashboard
Log In
Guides

Authenticate with Forage

Generate authentication and session tokens for Forage API requests.

To authenticate requests to the Forage API, you need bearer tokens: either an authentication token for server-side requests or a session token for client-side requests. Before you begin, register a Forage app to get your Client ID and Client Secret.

Not sure which token type you need? See Understanding Forage Authentication. For the full list of endpoints and SDK methods that require each type, see Authentication Token Reference.

Generate an authentication token

⚠️

Server-side only

Generate authentication tokens server-side only. Never expose your Client ID or Client Secret to the client.

To generate an authentication token:

  1. Retrieve your app's Client ID and Client Secret from the Forage dashboard (sandbox, production). If you need help finding these credentials, then refer to the Register an app guide.
  2. Send a POST request to the /o/token endpoint.

Encode your credentials:

Pass the Client ID and Client Secret separated by a colon, as in <client_id>:<client_secret>, through a base64 encoding function:

$ node
> btoa('<client-id>:<client-secret>')
import base64

def encode_to_base64(input_string):
    encoded_bytes = base64.b64encode(input_string.encode('utf-8'))
    encoded_string = encoded_bytes.decode('utf-8')
    return encoded_string

encoded_string = encode_to_base64('<client-id>:<client-secret>')
print(encoded_string)

Send the request:

Pass the encoded result in the Authorization header after the word Basic, like Basic <encoded_credentials>:

📘

Choosing a scope

The scope parameter controls what the token can access. Use pinpad_only for SDK-based integrations (most integrations). Use hosted_checkout for Fully Hosted Checkout integrations. Use reporting to query /reporting/ endpoints. You can combine scopes with a space, for example hosted_checkout reporting.

curl --request POST \
     --url https://api.sandbox.joinforage.app/o/token/ \
     --header 'Accept: application/json' \
     --header 'Authorization: Basic <base64-encoded-client-id-secret-pair>' \
     --header 'Content-Type: application/x-www-form-urlencoded' \
     --data-urlencode 'grant_type=client_credentials' \
     --data-urlencode 'scope=pinpad_only' \
     --data-urlencode 'expiration_time=1728000'
import requests

response = requests.post(
    "https://api.sandbox.joinforage.app/o/token/",
    headers={
        "Accept": "application/json",
        "Authorization": "Basic <base64-encoded-client-id-secret-pair>",
        "Content-Type": "application/x-www-form-urlencoded",
    },
    data={
        "grant_type": "client_credentials",
        "scope": "pinpad_only",
        "expiration_time": "1728000",
    },
)
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/o/token/"))
    .header("Accept", "application/json")
    .header("Authorization", "Basic <base64-encoded-client-id-secret-pair>")
    .header("Content-Type", "application/x-www-form-urlencoded")
    .POST(HttpRequest.BodyPublishers.ofString(
        "grant_type=client_credentials&scope=pinpad_only&expiration_time=1728000"))
    .build();

HttpResponse<String> response = client.send(
    request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
const response = await fetch(
  "https://api.sandbox.joinforage.app/o/token/",
  {
    method: "POST",
    headers: {
      Accept: "application/json",
      Authorization: "Basic <base64-encoded-client-id-secret-pair>",
      "Content-Type": "application/x-www-form-urlencoded",
    },
    body: new URLSearchParams({
      grant_type: "client_credentials",
      scope: "pinpad_only",
      expiration_time: "1728000",
    }),
  }
);
const data = await response.json();
console.log(data);
require 'net/http'
require 'json'

uri = URI("https://api.sandbox.joinforage.app/o/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"] = "Basic <base64-encoded-client-id-secret-pair>"
request["Content-Type"] = "application/x-www-form-urlencoded"
request.set_form_data(
  "grant_type" => "client_credentials",
  "scope" => "pinpad_only",
  "expiration_time" => "1728000"
)

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

curl shorthand

If you're using curl, you can alternatively add the flag -u <client_id>:<client_secret> to your request instead of passing the Authorization header.

curl --request POST \
     --url https://api.sandbox.joinforage.app/o/token/ \
     --header 'Accept: application/json' \
     -u '<client_id>:<client_secret>' \
     --header 'Content-Type: application/x-www-form-urlencoded' \
     --data-urlencode 'grant_type=client_credentials' \
     --data-urlencode 'scope=pinpad_only' \
     --data-urlencode 'expiration_time=1728000'
  1. Retrieve the access_token value from the response.
{
  "access_token": "sandbox_uXpcGMAMs7hhbw9JifUuJlzUZS3zWD",
  "expires_in": 1728000,
  "token_type": "Bearer",
  "scope": "pinpad_only"
}

The access_token value is your authentication token. Pass it as the bearer token in requests. Your Authorization header would be Bearer <authentication_token>.

Refer to the /o/token reference documentation for endpoint details.

Generate a session token

To generate a session token:

  1. Generate a Forage authentication token.
  2. Send a POST request to the /session_token/ endpoint:
    1. Pass the authentication token in the Authorization header.
    2. Pass the merchant's FNS number in the Merchant-Account header. Ask the merchant for their FNS number if you don't already have it handy.

Send the 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)
  1. Retrieve the token value from the response.
{
    "token": "sandbox_eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c"
}

The token value is your session token. Pass it as the bearer token in API requests and as a parameter in SDK methods. Your Authorization header would be Bearer <session_token>.

Refer to the /session_token/ reference documentation for endpoint details.

Next steps