Detokenization Proxy

The Forter Detokenization Proxy allows merchants to pass Forter PCI tokenized payloads to any PSP.

Overview

The Forter Detokenization Proxy is a forward HTTP proxy designed to facilitate detokenization for merchants interacting with third-party APIs that require sensitive PCI data. This enables merchants to process transactions securely without handling or storing sensitive cardholder information.

Key Benefits

✅ Securely retrieve tokenized PCI data

✅ Avoid direct PCI data handling

✅ Compatible with standard HTTP libraries and tools

✅ Pass PCI tokenized authorization payloads to any PSP from a single card vault vendor

Proxy Environments

Authentication

The Forter Detokenization Proxy requires HTTP Basic Authentication using the proxy-authorization header in the following format:

proxy-authorization: Basic TO_BASE64(site_id:site_secret)

📘

The same credentials are used for both the Detokenization Proxy and the Tokenization API.

Trusted CA Certificate

To establish a secure connection, merchants must trust Forter’s CA root certificate.

Sandbox Certificate
  -----BEGIN CERTIFICATE-----  
MIICuDCCAaACCQDx1qoYa/sqhTANBgkqhkiG9w0BAQsFADAeMQswCQYDVQQGEwJJ  
TDEPMA0GA1UECgwGRm9ydGVyMB4XDTIyMDgyNTEzMDMyMFoXDTMyMDgyMjEzMDMy  
MFowHjELMAkGA1UEBhMCSUwxDzANBgNVBAoMBkZvcnRlcjCCASIwDQYJKoZIhvcN  
AQEBBQADggEPADCCAQoCggEBAOSmh9WDhKaceirpwfVbfvpvHIQ0H5TmKZixjrzN  
QVGpeXd+e65fPjnDZtXpT06aN2Dqimh9VlEf6WX9E6zxeQZzxkmwUU5rwjWx0HQ2  
5RBh9LeRy0xlcF4rPDAaQd74eoQWPPJ+5GBtHjxWEiPAG0wB6yb++D1kDhvT5yXd  
qXqc9GL1HXex4OZexcTr5XJCPfRUZgC/78sF8H0Gg5vwOq8VprN0951TW7W1gHA4  
Hl51alZKv4VUCEhr1FDQfrW6N2IrahYhKYg38P3p+1KfT9N01/qa3yAp2JuDM4Md  
EWy/rOCZAVRREGXeH0xrhW5PzUbAD4wMK1zfqKbwa0b2WWsCAwEAATANBgkqhkiG  
9w0BAQsFAAOCAQEAqjx8Oas5GLqFH/vb9Hk2Zr9kCxgXm+66wdE+cdfILpFx8J9P  
J15aB37SgWk1V+6Ov29Z2znqJx4GOOnJlWLBAZhR9DSJDoDysJtRbrshXbY5U/YS  
bh0ESSuAfBiUzQu2cE2DhuLUABvzC789HeFyof16vdNtFIkxPvSJ/aHqemaWHbtO  
uS8/RYGmXH0N655p7TZor8FotfVYwqw8iE6Zt/8sUsd6DmBYsgxn3q6HwfzIAc2K  
f5vp/750ylKw2Dv2SWJO7OUZ20qIThq6+cJdbvTvrVlEQGVtzEVPKiDgw5dxMPNt  
3b8bjmIovuECw7123hwDQRhT2ccqr9Pv+cqZxw==  
-----END CERTIFICATE-----
Production Certificate
-----BEGIN CERTIFICATE-----  
MIICnjCCAYYCCQCqd/JdClQxIDANBgkqhkiG9w0BAQsFADARMQ8wDQYDVQQKDAZG  
b3J0ZXIwHhcNMjIxMTIxMTMyNDQ4WhcNMjcxMTIwMTMyNDQ4WjARMQ8wDQYDVQQK  
DAZGb3J0ZXIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC4NgIfmQm5  
MkADTIxzOcKUAI4+XGBwmLobFQqtMluUn3pe4ChPFOURCbTxReSHZq0ywwFTUT51  
ARMh+tsUw+DzbH35T0YTvMXBPFzhikg9uFXUhc9EOn/mFPZxYm15LH78NAKXumPT  
+5r0+cg5TbJpPCnVZbXMTyQOcOQGGj4ZSZLF4IjGnQlKrvuA90UQL1PttUd8p6Vg  
/O8vO0IcrsA9QZ7vlJoVxi4JAI8GoMjC0b+8r+fihakQ146RPn9f5ZajpOu83btk  
n59nJWjwBG7JQd0gTb+5McywoFSGR+EMAaiMVREK1bGftewjmzuZdxgSecguL/Xy  
6qb3EJr8Mtj5AgMBAAEwDQYJKoZIhvcNAQELBQADggEBAGCmJlEiQEsBl5cud6I6  
2PiJpA1ZK7cjZ+fMPSCH7bDA/gmdc5oNG4Gb4QkBAwsNXpPeySbtkyzCWsGo5iSR  
kfhxrCN/EGyDuwYzM1ceNFUUt+V7TzDnmSTAA5xHCEBuKUE3RQdy+QqlNEwL/faI  
3P0TaiojiFypsz04tHAvXAGJzTETSZigzsexSamdUUyCcZIPgiJrXr/oNCKjapXz  
lirDWLLO5HU+wn+ZvOPrkUvRRHvrz/WQKMdqA2IU7OavI0MrRFt/wvw73wOZZhZo  
nWLGh2TlEk6wV+BT9qHZdMv045l9LG9PhnoPCt5k4RDGUs6pRYMzdZq870NHhO9p  
cCY=  
-----END CERTIFICATE-----

Setup

  1. Download and store the certificate.
  2. In your HTTP framework, add it as a trusted CA without overriding the default CA list.

Using the Detokenization Proxy

To use the proxy, replace sensitive PCI data in the request payload with placeholders, and include the Forter token in the request header.

Token Types

  1. Payment Method Token - A Forter-issued PCI token for payment credentials.
  2. CVC-Only Token - A specialized token for periodic CVC authentication.

Required headers

For Payment Method Tokens

When using a Payment Method Token issued by Forter, merchants have two integration options:

  1. Using the Forter Token Directly – This requires including the forter-token header with the token string.
  2. Using a Token Alias – If a token alias was previously specified in a /tokenize request to the Forter Tokenization API, merchants must provide the alias information via the following headers:
    • forter-token-alias-key – The alias key assigned in the tokenization request.
    • forter-token-alias-value – The corresponding alias value.

For CVC-Only Tokens

When using the CVC-Only Token, the following headers must be included:

  • forter-token – The primary Forter token string.
  • forter-cvc-token – The CVC-specific token issued by Forter.

Request Placeholders

Placeholders are strings enclosed in double curly brackets ({{ }}). These placeholders should be inserted into the request payload sent to the Detokenization Proxy to ensure the correct request body format for the final third-party target.

Standard Placeholders

PlaceholderDescription
{{card_number}}The full credit card Primary Account Number (PAN).
{{expiration_m}}The expiration month as a single-digit number (e.g., 8).
{{expiration_mm}}The expiration month as a two-digit number (e.g., 08).
{{expiration_yy}}The expiration year as a two-digit number (e.g., 28).
{{expiration_yyyy}}The expiration year as a four-digit number (e.g., 2028).
{{cvc}}The card’s security code (CVV/CVC). Note: The CVC is only available when using a single-use token.
{{card_holder_name}}The name of the cardholder.
{{card_bin}}The card’s Bank Identification Number (BIN).
{{card_last_four}}The last four digits of the card number.

Network Tokenization Placeholders

PlaceholderDescription
{{network_token}}The PAN's associated network token.
{{network_token_cryptogram}}A one-time cryptogram used with the network token.
{{network_token_eci}}The network token’s Electronic Commerce Indicator (ECI).
{{network_token_par}}The Payment Account Reference (PAR) associated with the network token.
{{network_token_expiration_m}}The expiration month of the network token as a single-digit number (e.g., 8).
{{network_token_expiration_mm}}The expiration month of the network token as a two-digit number (e.g., 08).
{{network_token_expiration_yy}}The expiration year of the network token as a two-digit number (e.g., 28).
{{network_token_expiration_yyyy}}The expiration year of the network token as a four-digit number (e.g., 2028).

Custom Placeholder Fields

Placeholder

Description

{{ text_field }}

Extra fields from the tokenization API can be included. Ensure the placeholder name must match the original casing and wording.


Handling Errors

The Detokenization Proxy uses special status codes to distinguish its own errors from third-party API responses.

HTTP Status CodeDescription
407Proxy authentication error (check credentials)
502Network error while reaching the third-party API
555Token not found
556Validation error (check inputs)
565Unexpected internal error
Other CodesRelayed directly from the third-party API

HMAC Request Signing

Some Payment Service Providers (PSPs) require HMAC signing to verify request integrity. Forter supports multiple hashing algorithms and allows merchants to sign requests seamlessly.

Supported HMAC Algorithms

  • sha256
  • sha512
  • sha1
  • md5

HMAC Headers

Header NameDescription
forter-hmac-algoHMAC algorithm (e.g., sha256)
forter-hmac-target-headerName of the header storing the computed signature
forter-hmac-secretShared secret for signing
forter-hmac-payload-templateTemplate for the signed payload.

For the forter-hmac-payload-template special placeholder values denoted in curly braces are supported:

  • {{ request-body }} - The full outgoing request body, after detokenization, as a single string.
  • {{ http-method }} - The HTTP method used in the request
  • {{ http-path }} - The relative path used in the request
  • {{ header-name }} - Any header sent along the request can be used to construct the signing payload. The header name must be converted to lowercase.

PSP specific signing methods

Disclaimer: Payment Service Providers (PSPs) employ various signing algorithms, and we can support a range of them. For assistance with your specific requirements, please reach out to us.

To implement signing for Ixopay, include the following header: Forter-Ixopay-Signature: SHARED_IXOPAY_KEY This will generate X-Signature and Date headers in the proxied request to Ixopay.


Examples

Sending a request to Forter

Forter's Order API Integration

orders API
  curl 'https://api.forter-secure.com/v3/orders/{id}' \
 -x https://SITE_ID:[email protected] \
 --proxy-header 'forter-token: ftr1df95272f9e204c5791427722cc4ef407' \
 --cacert [your CA certificate file path] \
 -X POST \
 -H 'Content-type: application/json' \
 -H 'x-forter-siteid: SITE_ID' \
 -H 'api-version: API_VERSION' \
 -H 'authorization: Basic dGVzdDo=' \
 --data '
{
  "orderId": "2356fdse0rr489",
  "orderType": "WEB",
  "authorizationStep": "PRE_AUTHORIZATION",
  "totalAmount": {
    "amountUSD": "99.95",
    "amountLocalCurrency": "105.55",
    "currency": "CAD",
    "amountMerchantMainCurrency": "125.95",
    "merchantMainCurrency": "EUR"
  },
  "totalDiscount": {
    "couponCodeUsed": "FATHERSDAY2015",
    "discountType": "COUPON"
  },
  "payment": [
   {
     "creditCard": {
         "nameOnCard": "{{ card_holder_name }}",
         "bin": "{{ card_bin }}",
         "lastFourDigits": "{{ card_last_four }}",
         "cardType": "credit",
         "expirationMonth": "{{ expiration_mm }}",
         "expirationYear": "{{ expiration_year }}"
         "fullCreditCard": "{{ card_number }}"
     },
     "billingDetails": {
        "personalDetails": {
            "fullName": "Or Paul",
            "email": "[email protected]"
        },
        "phone": [],
        "address": {
            "zip": "90043", 
            "address1": "123 17th St",
            "city": "Santa Monica", 
            "region": "CA", 
            "country": "US"
        }
     },
     "amount": {
        "currency": "EUR",
        "amountLocalCurrency": "90.00",
        "amountUSD": "100.00"
     }
  },
  "primaryRecipient": {
    "personalDetails": {
      "firstName": "John",
      "lastName": "Smith",
      "gender": "MALE",
      "birthdate": "1987-05-22",
      "email": "[email protected]"
    },
    "address": {
      "address1": "235 Montgomery st.",
      "address2": "Ste. 1110",
      "zip": "94104",
      "city": "San Francisco",
      "region": "CA",
      "country": "US",
      "company": "Generic Corp. ltd.",
      "savedData": {
        "usedSavedData": true,
        "choseToSaveData": false
      }
    },
    "comments": {
      "userCommentsToMerchant": "Please wrap with care!!",
      "messageToBeneficiary": "Enjoy the gift John!",
      "merchantComments": "Shipping delayed"
    }
  },
  "phoneOrderInformation": {
    "customerWebId": "123456789",
    "callerFirstName": "John",
    "callerLastName": "Smith",
    "callerId": "2121234567",
    "callStartTime": 1412345911,
    "callDuration": 4,
    "remarks": "The customer is buying the product for a friend",
    "merchantAgentData": {
      "merchantAgentName": "John Smith",
      "merchantAgentId": "HG36885TZ"
    }
  },
  "historicalData": {
    "orderStatus": "COMPLETED",
    "merchantOrderStatus": "Shipped",
    "fraud": "FRAUD_CHARGEBACK"
  }
}
'

Sending a request to a PSP

Stripe

Securely paying using a newly collected CVC token(Node.js)
  // NOTE: We must trust the require proxy CA certificate. In NodeJS, this can be done in one of two ways:  
  // 1. Saving the CA certificate to a file, and using the NODE_EXTRA_CA_CERTS environment variable  
  // e.g.: export NODE_EXTRA_CA_CERTS=[your CA certificate file path]
  // 2. Extending NodeJS list of trusted CAs (shown below)

  import {HttpsProxyAgent} from "https-proxy-agent";  
  import url from "url";  
  import Stripe from "stripe";  
  import tls from 'tls';

  const stripe = Stripe("sk_test_********************");

  const secureProxyHttpsAgent = new HttpsProxyAgent("https://pci-proxy-sandbox.checkouttools.com",{  
  // Passing the "ca" option will override the default Mozilla trusted CA bundle, so we need to specify it explicitly again.
    ca: [...tls.rootCertificates, await fs.readFile('./forter-proxy-ca.pem')],
    headers: {  
      "proxy-authorization": `Basic ${btoa('site_id:site_secret')}`,  
      "forter-token": "ftr1df95272f9e204c5791427722cc4ef407",  
    },  
  });

  stripe.setHttpAgent(secureProxyHttpsAgent);

  const cvcToken = await stripe.tokens.create({  
    cvc_update: { cvc: "{{ cvc }}" },  
  });

  const paymentIntent = await stripe.paymentIntents.create({  
    payment_method: 'abcd',  
    customer: '1234',  
    amount: 1099,  
    currency: 'usd',  
    confirmation_method: 'manual',  
    confirm: true,  
    payment_method_options: {card: {cvc_token: cvcToken}},  
  });

Worldpay

Authorizing a transaction using authorizations api and a token alias(Node.js)
  // NOTE: We must trust the require proxy CA certificate. In NodeJS, this can be done in one of two ways:  
  // 1. Saving the CA certificate to a file, and using the NODE_EXTRA_CA_CERTS environment variable  
  // e.g.: export NODE_EXTRA_CA_CERTS=[your CA certificate file path]
  // 2. Extending NodeJS list of trusted CAs (shown below)

  import {HttpsProxyAgent} from "https-proxy-agent";  
  import url from "url";  
  import axios from "axios";  
  import fs from "fs/promises";
  import tls from 'tls';

  const secureProxyHttpsAgent = new HttpsProxyAgent("https://pci-proxy-sandbox.checkouttools.com", {  
    // Passing the "ca" option will override the default Mozilla trusted CA bundle, so we need
    // to specify it explicitly again.
    ca: [...tls.rootCertificates, await fs.readFile('./forter-proxy-ca.pem')], // Contains Forter's custom CA certificate  
    headers: {  
      "proxy-authorization": `Basic ${btoa('site_id:site_secret')}`,  
      "forter-token-alias-key": "zooz",  
      "forter-token-alias-value": "ABCABC123",  
    },  
  });

  // Securely calling worldpay's authorizations API  
  axios.post(  
   "https://try.access.worldpay.com/payments/authorizations",

    // Note: we are using a stringified payload as worldpay uses integers to represent dates which becomes  
    // invalid JSON when replaced with our placeholders  
    `{
      "transactionReference": "Memory265-13/08/1876",
      "merchant": {
        "entity": "MindPalaceLtd"
      },
      "instruction": {
        "narrative": {
          "line1": "Mind Palace"
        },
        "value": {
          "currency": "GBP",
          "amount": 250
        },
        "paymentInstrument": {
          "type": "card/plain",
          "cardNumber": "{{ card_number }}",
          "cardExpiryDate": {
            "month": {{ expiration_month }},
            "year": {{ expiration_year }}
          }
        }
      }
    }`,  
    { httpsAgent: secureProxyHttpsAgent }  
  );

Fiserv

Calculate a SHA256 hash based HMAC and store the result in a new header called message-signature:(cURL)
  curl 'https://prod.emea.api.fiservapps.com/sandbox/ipp/payments-gateway/v2/payments/' \
 -x 'https://SITE_ID:[email protected]' \
 --proxy-header 'forter-token: ftr1df95272f9e204c5791427722cc4ef407' \
 -X POST \
 -H 'Content-type: application/json' \
 -H 'client-request-id: 123456' \
 -H 'api-key: FISERV_API_KEY' \
 -H 'timestamp: 655846200000' \
 -H 'forter-hmac-target-header: message-signature' \
 -H 'forter-hmac-algo: sha256' \
 -H 'forter-hmac-secret: signing-secret' \
 -H 'forter-hmac-payload-template: {{ api-key }}{{ client-request-id }}{{ timestamp }}{{ request-body }}' \
 -d '
   {
     fullCreditCard: "{{ card_number }}",
     nameOnCard: "{{ card_holder_name }}",
     expirationMM: "{{ expiration_mm }}",
     expirationYY: "{{ expiration_yy }}",
   }'