Skip to main content

Proxy Transforms

Pre-configured proxies support multiple transform types for processing requests and responses. Transforms are executed in the order specified in the array.

Transform Types

Request Transforms

  • code: Custom code executed in Basis Theory's serverless runtime environment for complex request processing, such as digital signature computation that relies on detokenized data
  • tokenize: Create tokens from request data using plaintext, encrypted JWE, or Liquid expressions

Response Transforms

  • code: Custom code executed in Basis Theory's serverless runtime environment for complex response processing, tokenization, or detokenization
  • mask: Pattern-based masking using regex or predefined matchers
  • tokenize: Create tokens from response data using Liquid expressions or plaintext
  • append_json: Add JSON properties to response payload
  • append_text: Append plain text to response body
  • append_header: Add HTTP headers to responses

Testing and Dependencies

Testing transforms works the same as testing Reactors. Available NPM modules are listed here.

Whitelisted npm modules

You can find a list of all whitelisted NPM modules here.

For node22, you can use any npm package by specifying it in runtime.dependencies.

Error Handling

For information on handling errors in proxy transforms, including error types, response formats, and best practices, see Error Handling.

Request Transforms

Request transforms process incoming HTTP requests before forwarding them to the destination. Available transform types:

  • code: Custom Node.js functions for complex request processing, header manipulation, or injecting proxy configuration secrets
  • tokenize: Create tokens from request data using plaintext values, encrypted expression, or Liquid expressions to extract data from the request

Code Request Transform

Code request transforms run in Basis Theory's serverless runtime environment. The runtime supports two images: node-bt and node22.

module.exports = async function (req) {
const { bt, args, configuration } = req;
const { body, headers, method, path, query } = args; // access properties of the http request
const { MY_CONFIG } = configuration; // access any static config defined on the Proxy

// do anything here!
const processedBody = ...; // do something with body
const processedHeaders = ...; // do something with headers

return {
body: processedBody, // transformed request body
headers: processedHeaders // transformed request headers
};
};

node-bt Code Contract

Request Object

The request transform function receives a request object containing the HTTP request properties and configuration:

AttributeTypeDescription
argsobjectHTTP request properties (see below)
configurationmap<string, string>Configuration values defined on the proxy
btobjectPre-configured Basis Theory SDK instance for token operations (if application.id is set)
applicationOptionsobjectConfiguration information about the associated application (if application.id is set)
applicationOptions.apiKeystringThe API key of the associated application
applicationOptions.environmentstringThe Basis Theory API URL (e.g., https://api.basistheory.com)

The args object contains the HTTP request properties:

AttributeTypeDescription
bodyobject or stringThe request body parsed as a JavaScript object when Content-Type is application/json, or string for other content types.
headersobjectA JavaScript object containing the headers received on the proxy request
methodstringThe HTTP method of the proxy request (e.g., "GET", "POST", "PUT", "PATCH", "DELETE")
pathstringThe path suffix received on the proxy request after /proxy (e.g., a request to /proxy/sub/path?param=value would result in a path of /sub/path)
querystringThe unparsed query string that was received on the proxy request (e.g., a request to /proxy/sub/path?param=value would result in a query of ?param=value)

Response Object

An object of the following type must be returned by the request transform function:

AttributeTypeDescription
bodyobjectThe transformed request body to forward to the destination
headersobjectThe transformed request headers to forward to the destination

node22 Code Contract

Request Object

The request transform function receives a request object containing the HTTP request properties and configuration:

AttributeTypeDescription
reqobjectHTTP request properties (see below)
configurationmap<string, string>Configuration values defined on the proxy
loggerobjectLogger instance with info(), warn(), error() methods
applicationOptionsobjectConfiguration information about the associated application (if application.id is set)
applicationOptions.apiKeystringThe API key of the associated application
applicationOptions.environmentstringThe Basis Theory API URL (e.g., https://api.basistheory.com)

The req object contains the HTTP request properties:

AttributeTypeDescription
bodyobject or stringThe request body parsed as a JavaScript object when Content-Type is application/json, or string for other content types.
headersobjectA JavaScript object containing the headers received on the proxy request
methodstringThe HTTP method of the proxy request (e.g., "GET", "POST", "PUT", "PATCH", "DELETE")
pathstringThe path suffix received on the proxy request after /proxy (e.g., a request to /proxy/sub/path?param=value would result in a path of /sub/path)
querystringThe unparsed query string that was received on the proxy request (e.g., a request to /proxy/sub/path?param=value would result in a query of ?param=value)

Response Object

An object of the following type must be returned by the request transform function:

AttributeTypeDescription
req.bodyobjectThe transformed request body to forward to the destination
req.headersobjectThe transformed request headers to forward to the destination

Skip Proxy Request

Request transforms can skip forwarding the request to the destination and return a response directly from the transform. This is useful for caching, rate limiting, early validation, or authentication checks. When a request transform returns a response directly, the proxy will not forward the request to the destination URL.

The examples below demonstrate success responses (such as returning cached data). You can also use this approach to return error responses. For error handling examples, see Proxy Transform Error Handling.

Use CustomHttpResponseError to skip proxying and return a custom response:

const { CustomHttpResponseError } = require('@basis-theory/basis-theory-reactor-formulas-sdk-js');

module.exports = async function (req) {
const { args, configuration } = req;
const cacheKey = args.path;

// Check cache (pseudo-code)
const cachedData = getFromCache(cacheKey);

if (cachedData) {
throw new CustomHttpResponseError({
status: 200,
headers: {
'X-Cache': 'HIT',
'Content-Type': 'application/json'
},
body: cachedData
});
}

// Continue with normal proxy flow
return {
body: args.body,
headers: args.headers
};
};

Tokenize Request Transform

Creates tokens from request data and makes them available for subsequent transforms via identifiers.

Basic Configuration:

{
"type": "tokenize",
"options": {
"token": {
"type": "token",
"data": "sensitive_value"
},
"identifier": "my_token"
}
}

Data Sources for token.data:

  • Plaintext: Static string values
  • Encrypted expression: "{{ encrypted | json: '$.data' }}" - Extract data from the header BT-ENCRYPTED
  • Request expressions: "{{ req.card_number }}" - Extract data from request properties

Token References: Created tokens can be referenced in subsequent transforms or the request body using:

  • "{{ transform_identifier: 'my_token' }}" - Full token data
  • "{{ transform_identifier: 'my_token' | json: '$.path' }}" - Extract specific data with JSONPath

Response Transforms

Response transforms process HTTP responses from the destination before returning them to the client.

Response transforms will only be executed when the destination returns a 2xx status code, and other non-2xx statuses will result in an immediate response from the proxy.

Code Response Transform

Code Response Transform can be used to:

  • Transform the body or headers on the HTTP response received from the destination before returning a response from the proxy
  • Tokenize sensitive values returned by a third party destination API
  • For inbound HTTP requests, tokens returned in responses from your system can be detokenized before sending the response to the third party caller

Code response transforms run in Basis Theory's serverless runtime environment:

module.exports = async function (req) {
const { bt, args, configuration } = req;
const { body, headers } = args; // access properties of the http response
const { MY_CONFIG } = configuration; // access any static config defined on the Proxy

// do anything here!
const processedBody = ...; // do something to build a transformed body
const processedHeaders = ...; // do something to build transformed headers

return {
body: processedBody, // transformed response body
headers: processedHeaders // transformed request headers
};
};

node-bt Code Contract

Request Object

The response transform function receives a request object containing the HTTP response properties and configuration:

AttributeTypeDescription
argsobjectHTTP response properties (see below)
configurationmap<string, string>Configuration values defined on the proxy
btobjectPre-configured Basis Theory SDK instance for token operations (if application.id is set)
applicationOptionsobjectConfiguration information about the associated application (if application.id is set)
applicationOptions.apiKeystringThe API key of the associated application
applicationOptions.environmentstringThe Basis Theory API URL (e.g., https://api.basistheory.com)

The args object contains the HTTP response properties:

AttributeTypeDescription
bodyobject or stringThe response body returned from the destination endpoint, parsed as a JavaScript object when Content-Type is application/json, or string for other content types.
headersobjectA JavaScript object containing the response headers returned from the destination endpoint
Request header names are case-sensitive and can only contain alphanumeric characters, hyphens, and underscores. Headers names containing other characters will be discarded from the request. Response headers are unrestricted. If you must forward a restricted header to the proxy destination, as a workaround, you may add this header manually from within the request transform.

Response Object

An object of the following type must be returned by the response transform function:

AttributeTypeDescription
bodyobjectThe transformed response body to return from the proxy
headersobjectThe transformed response headers to return from the proxy

node22 Code Contract

Request Object

The response transform function receives a request object containing the HTTP response properties and configuration:

AttributeTypeDescription
resobjectHTTP response properties (see below)
configurationmap<string, string>Configuration values defined on the proxy
loggerobjectLogger instance with info(), warn(), error() methods
applicationOptionsobjectConfiguration information about the associated application (if application.id is set)
applicationOptions.apiKeystringThe API key of the associated application
applicationOptions.environmentstringThe Basis Theory API URL (e.g., https://api.basistheory.com)

The res object contains the HTTP response properties:

AttributeTypeDescription
bodyobject or stringThe response body returned from the destination endpoint, parsed as a JavaScript object when Content-Type is application/json, or string for other content types.
headersobjectA JavaScript object containing the response headers returned from the destination endpoint

Response Object

An object of the following type must be returned by the response transform function:

AttributeTypeDescription
res.bodyobjectThe transformed response body to return from the proxy
res.headersobjectThe transformed response headers to return from the proxy

Mask Response Transform

Mask response transform can be used to transform the body of the response received from the destination before returning a response from the proxy. The mask transform has two available matcher types, regex and chase_stratus_pan.

Regex Matcher

Mask response transform using the regex matcher is defined using regular expressions and a replacement character.

{
"name": "My masked proxy",
"destination_url": "https://echo.basistheory.com/anything",
"require_auth": false,
"response_transforms": [
{
"type": "mask",
"matcher": "regex",
"replacement": "*",
"expression": "\"accountNumber\":\\s*\"(.*?)\""
}
]
}

The regular expression must contain at least one capture group. In the example above, the expression will capture the value of an accountNumber attribute of a JSON payload. Given the proxied service responds with a JSON similar to the following:

Original Response

{
"username": "bsmith1486",
"accountNumber": "56834512"
}

Then the sample proxy will mask the response as:

Transformed Response

{
"username": "bsmith1486",
"accountNumber": "********"
}

When a response body matches the given expression, the matched part of the body will be processed. During processing, any portion of the matched body section that is equivalent to any value of a capture group defined in the regex will be replaced. In this case, the matched body section is "accountNumber": "56834512".

The best practice is to limit the match scope to be as narrow as possible. There could be unintended or unexpected side effects if the match string is larger than necessary.

For example, given a regex defined as ^(aa).*?$, a match will occur when the line starts with "aa". However, since the regular expression uses the beginning, ^, and end $ syntax, the whole string will be matched and eligible for replacements. Given a response body of aabbccaabbccaa, the entire body will processed during masking. ALL values that match the capture group value, in this case aa, will be replaced. The response body will then be masked as **bbcc**bbcc**.

Chase Stratus PAN Matcher

If your proxy is interfacing with the Chase Stratus service, you may be able to take advantage of a default mask. The chase_stratus_pan matcher will automatically mask PANs from the Chase Stratus Account Verification and Tokenize responses.

{
"name": "My Chase Stratus proxy",
"destination_url": "<REPLACE WITH CHASE STATUS URL>",
"require_auth": false,
"response_transforms": [
{
"type": "mask",
"matcher": "chase_stratus_pan",
"replacement": "*"
}
]
}

This mask will return responses as follows:

Account Verification

T74VKiwuJZ7TYGXD4navTHDLZG104240726tst844   *******************0929VI   000000000000CT01USANNXNNNXY\r

Tokenize

T74VEqMOciR1n8le3BhTVvl3zJ104240726         *******************0329DI   000000000000TI6559909009126557    \r

Tokenize Response Transform

Creates tokens from response data and makes them available for subsequent transforms via identifiers.

Basic Configuration:

{
"type": "tokenize",
"options": {
"token": {
"type": "token",
"data": "{{ res.card_number }}"
},
"identifier": "response_token"
}
}

Data Sources for token.data:

  • Plaintext: Static string values
  • Encrypted expression: "{{ encrypted | json: '$.data' }}" - Extract data from the header BT-ENCRYPTED
  • Response expressions: "{{ res.card_number }}" - Extract data from response properties

Append JSON Response Transform

Add JSON properties to response payload at specified locations using JSONPath expressions.

Basic Configuration:

{
"type": "append_json",
"options": {
"value": "{{ transform_identifier: 'response_token' | json: '$.id' }}",
"location": "$.created_token_id"
}
}

Append Text Response Transform

Appends plain text content to the end of response body.

Basic Configuration:

{
"type": "append_text",
"options": {
"value": "Token ID: {{ transform_identifier: 'response_token' | json: '$.id' }}"
}
}

Append Header Response Transform

Add HTTP headers to response with values that can reference tokens from previous transforms.

Basic Configuration:

{
"type": "append_header",
"options": {
"value": "{{ transform_identifier: 'response_token' | json: '$.id' }}",
"location": "X-Token-ID"
}
}

Token References in Response Transforms: All append transforms support referencing tokens created by previous transforms using:

  • "{{ transform_identifier: 'identifier' }}" - Full token data
  • "{{ transform_identifier: 'identifier' | json: '$.path' }}" - Extract specific data with JSONPath

Tokenizing or Detokenizing

In some situations, you may want to tokenize or detokenize data with Code Request Transform or Code Response Transform. In order to do this, set the application.id property when creating your Proxy with the id of an Application that has been granted the desired permissions. This will inject a Basis Theory JS instance into the transform request that is pre-configured for this application. For example:

module.exports = async function (req) {
const token = await req.bt.tokenize({
type: "token",
data: req.args.body.sensitive_value,
});

req.args.body.sensitive_value = token.id;

return {
body: req.args.body,
headers: req.args.headers,
};
};

In the above example, we utilized the injected Basis Theory JS instance to tokenize a property called sensitive_value on our request body and passed the token back as the updated sensitive_value to be forwarded to the configured destination_url on our Proxy.

API Reference

For complete API documentation including all parameters and SDK examples: