# Detokenization Proxy

## [Overview](https://docs.forter.com/detokenization-proxy#overview) 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 you 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](https://docs.forter.com/detokenization-proxy#proxy-environments) Proxy Environments

**Sandbox**: https://pci-proxy-sandbox.checkouttools.com

**Production**: https://pci-proxy.checkouttools.com

## [Authentication](https://docs.forter.com/detokenization-proxy#authentication) Authentication

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

Node.js

```plaintext
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](https://docs.forter.com/detokenization-proxy#trusted-ca-certificate) Trusted CA Certificate

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

### [Sandbox Certificate](https://docs.forter.com/detokenization-proxy#sandbox-certificate) Sandbox Certificate

Text

```plaintext
-----BEGIN CERTIFICATE-----
MIICuDCCAaACCQDx1qoYa/sqhTANBgkqhkiG9w0BAQsFADAeMQswCQYDVQQGEwJJ
TDEPMA0GA1UECgwGRm9ydGVyMB4XDTIyMDgyNTEzMDMyMFoXDTMyMDgyMjEzMDMy
MFowHjELMAkGA1UEBhMCSUwxDzANBgNVBAoMBkZvcnRlcjCCASIwDQYJKoZIhvcN
AQEBBQADggEPADCCAQoCggEBAOSmh9WDhKaceirpwfVbfvpvHIQ0H5TmKZixjrzN
QVGpeXd+e65fPjnDZtXpT06aN2Dqimh9VlEf6WX9E6zxeQZzxkmwUU5rwjWx0HQ2
75RBh9LeRy0xlcF4rPDAaQd74eoQWPPJ+5GBtHjxWEiPAG0wB6yb++D1kDhvT5yXd
8qXqc9GL1HXex4OZexcTr5XJCPfRUZgC/78sF8H0Gg5vwOq8VprN0951TW7W1gHA4
9Hl51alZKv4VUCEhr1FDQfrW6N2IrahYhKYg38P3p+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](https://docs.forter.com/detokenization-proxy#production-certificate) Production Certificate

Text

```plaintext
-----BEGIN CERTIFICATE-----
MIICnjCCAYYCCQCqd/JdClQxIDANBgkqhkiG9w0BAQsFADARMQ8wDQYDVQQKDAZG
b3J0ZXIwHhcNMjIxMTIxMTMyNDQ4WhcNMjcxMTIwMTMyNDQ4WjARMQ8wDQYDVQQK
DAZGb3J0ZXIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC4NgIfmQm5
MkADTIxzOcKUAI4+XGBwmLobFQqtMluUn3pe4ChPFOURCbTxReSHZq0ywwFTUT51
ARMh+tsUw+DzbH35T0YTvMXBPFzhikg9uFXUhc9EOn/mFPZxYm15LH78NAKXumPT
+5r0+cg5TbJpPCnVZbXMTyQOcOQGGj4ZSZLF4IjGnQlKrvuA90UQL1PttUd8p6Vg
/8O8vO0IcrsA9QZ7vlJoVxi4JAI8GoMjC0b+8r+fihakQ146RPn9f5ZajpOu83btk
n59nJWjwBG7JQd0gTb+5McywoFSGR+EMAaiMVREK1bGftewjmzuZdxgSecguL/Xy
6qb3EJr8Mtj5AgMBAAEwDQYJKoZIhvcNAQELBQADggEBAGCmJlEiQEsBl5cud6I6
112PiJpA1ZK7cjZ+fMPSCH7bDA/gmdc5oNG4Gb4QkBAwsNXpPeySbtkyzCWsGo5iSR
12kfhxrCN/EGyDuwYzM1ceNFUUt+V7TzDnmSTAA5xHCEBuKUE3RQdy+QqlNEwL/faI
133P0TaiojiFypsz04tHAvXAGJzTETSZigzsexSamdUUyCcZIPgiJrXr/oNCKjapXz
14lirDWLLO5HU+wn+ZvOPrkUvRRHvrz/WQKMdqA2IU7OavI0MrRFt/wvw73wOZZhZo
15nWLGh2TlEk6wV+BT9qHZdMv045l9LG9PhnoPCt5k4RDGUs6pRYMzdZq870NHhO9p
16cCY=
-----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](https://docs.forter.com/detokenization-proxy#using-the-detokenization-proxy) 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](https://docs.forter.com/detokenization-proxy#token-types) 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](https://docs.forter.com/detokenization-proxy#required-headers) Required headers

**For Payment Method Tokens**

When using a **Payment Method Token** issued by Forter, you 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, you 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:
   - The primary Forter token string forter-token **OR** forter-token-alias-key and forter-token-alias-value
   - The CVC-specific token issued by Forter forter-cvc-token **OR** forter-cvc-token-alias-key and forter-cvc-token-alias-value

## [Request Placeholders](https://docs.forter.com/detokenization-proxy#request-placeholders) 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](https://docs.forter.com/detokenization-proxy#standard-placeholders) Standard Placeholders

| **Placeholder**           | **Description**                                                                                                     |
|---------------------------|---------------------------------------------------------------------------------------------------------------------|
| {{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](https://docs.forter.com/detokenization-proxy#network-tokenization-placeholders) Network Tokenization Placeholders

| **Placeholder**                     | **Description**                                                                                             |
|-------------------------------------|-------------------------------------------------------------------------------------------------------------|
| {{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](https://docs.forter.com/detokenization-proxy#custom-placeholder-fields) Custom Placeholder Fields

| **Placeholder**       | **Description**                                                                                                    |
|-----------------------|--------------------------------------------------------------------------------------------------------------------|
| {{ text_field }}      | Extra fields from the tokenization API can be included.<br>**Ensure the placeholder name must match the original casing and wording.** |

## [Handling Errors](https://docs.forter.com/detokenization-proxy#handling-errors) Handling Errors

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

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

## [HMAC Request Signing](https://docs.forter.com/detokenization-proxy#hmac-request-signing) HMAC Request Signing

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

**Supported HMAC Algorithms**

- sha256
- sha512
- sha1
- md5

**HMAC Headers**

| Header Name                          | Description                                                          |
|--------------------------------------|----------------------------------------------------------------------|
| forter-hmac-algo                     | HMAC algorithm (e.g., sha256)                                       |
| forter-hmac-target-header             | Name of the header storing the computed signature                    |
| forter-hmac-secret                   | Shared secret for signing                                            |
| forter-hmac-payload-template         | Template 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.

### Examples

### [Sending a request to Forter](https://docs.forter.com/detokenization-proxy#sending-a-request-to-forter) Sending a request to Forter

### [Forter's Order API](https://docs.forter.com/detokenization-proxy#forters-order-api) Forter's Order API

Curl

```plaintext
curl'https://api.forter-secure.com/v3/orders/{id}'\
-x https://SITE_ID:TOKENIZATION_SITE_SECRET@pci-proxy-sandbox.checkouttools.com \
 --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": "or.paul@gmail.com"
 },
 "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": "john_s@test.com"
 },
 "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](https://docs.forter.com/detokenization-proxy#sending-a-request-to-a-psp) Sending a request to a PSP

### [Stripe](https://docs.forter.com/detokenization-proxy#stripe) Stripe

Securely paying using a newly collected CVC token

```plaintext
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](https://docs.forter.com/detokenization-proxy#worldpay) Worldpay

Authorizing a transaction using authorizations API and a token alias

```plaintext
// 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",
 `{   
 "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](https://docs.forter.com/detokenization-proxy#fiserv) Fiserv

Calculate a SHA256 hash-based HMAC and store the result in a new header called message-signature:

```plaintext
curl 'https://prod.emea.api.fiservapps.com/sandbox/ipp/payments-gateway/v2/payments/' \
 -x 'https://SITE_ID:TOKENIZATION_SITE_SECRET@pci-proxy-sandbox.checkouttools.com'\
 --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 }}",
 }
'
```
