Skip to main content

Pre-Configured Proxies

Pre-Configured Proxies differ from the Ephemeral Proxy by requiring setup beforehand. You define a proxy instance with a unique URL and fixed settings, which can be reused across requests or shared with third parties for inbound HTTP requests (e.g., providing an integrator with a proxy URL). This approach suits scenarios needing consistent configurations or stricter controls, such as whitelisting destinations in production environments.

Additional options for Pre-Configured Proxies include:

  • Request and response transforms: Optionally use custom Node.js code to alter requests or responses—useful for specific cases, but not mandatory.
  • Configuration map: Store proxy-specific secrets, like API keys, securely.
  • Anonymous access: Permit requests without authentication if needed.

In production, Pre-Configured Proxies are often preferred for their ability to enforce defined settings. Transforms are available but not required—standard setups work just as well without them.

Create a Proxy

Creates a new Proxy for the Tenant.

POST
https://api.basistheory.com/proxies
Copy

Permissions

proxy:create

Request

transform='module.exports = async function (req) {
// Do something with req.configuration.SERVICE_API_KEY

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

curl "https://api.basistheory.com/proxies" \
-H "BT-API-KEY: <MANAGEMENT_API_KEY>" \
-H "Content-Type: application/json" \
-X "POST" \
-d '{
"name": "My Proxy",
"destination_url": "https://example.com/api",
"request_transform": {
"code": '"$(echo $transform | jq -Rsa .)"',
},
"response_transform": {
"code": '"$(echo $transform | jq -Rsa .)"',
},
"configuration": {
"SERVICE_API_KEY": "key_abcd1234"
},
"application": {
"id": "45c124e7-6ab2-4899-b4d9-1388b0ba9d04"
},
"require_auth": true
}'

Request Parameters

AttributeRequiredTypeDefaultDescription
nametruestringnullThe name of the Proxy. Has a maximum length of 200
destination_urltruestringnullThe URL to which requests will be proxied
request_transformfalseProxy Request TransformnullRequest Transform which will be executed against the proxy request before sending to the destination.
response_transformfalseProxy Response TransformnullResponse Transform which will be executed against the destination's response before returning the proxy response.
applicationfalseApplicationnullThis Application's API key is injected into a pre-configured BasisTheory JS SDK instance passed into the transform. Must be a public or private Application Type.
configurationfalsemap<string, string>nullA string key and string value map of all configuration name and values for a Proxy Transform
require_authfalsebooleantrueRequire a BT-API-KEY request header for authentication and authorization

Response

Returns a Proxy if the Proxy was created. Returns an error if there were validation errors, or the Proxy failed to create.

{
"id": "433013a6-a614-4e1e-b2aa-5fba67aa85e6",
"tenant_id": "77cb0024-123e-41a8-8ff8-a3d5a0fa8a08",
"name": "My Proxy",
"key": "e29a50980ca5",
"destination_url": "https://example.com/api",
"request_transform": {
"code": "
module.exports = async function (req) {
// Do something with req.configuration.SERVICE_API_KEY

return {
headers: req.args.headers,
body: req.args.body
};
};
"
},
"response_transform": {
"code": "
module.exports = async function (req) {
// Do something with req.configuration.SERVICE_API_KEY

return {
headers: req.args.headers,
body: req.args.body
};
};
"
},
"configuration": {
"SERVICE_API_KEY": "key_abcd1234"
},
"application_id": "45c124e7-6ab2-4899-b4d9-1388b0ba9d04",
"require_auth": true,
"created_by": "3ce0dceb-fd0b-4471-8006-c51243c9ef7a",
"created_at": "2020-09-15T15:53:00+00:00"
}

List Proxies

Get a list of proxies for the Tenant.

GET
https://api.basistheory.com/proxies
Copy

Permissions

proxy:read

Request

curl "https://api.basistheory.com/proxies" \
-H "BT-API-KEY: <MANAGEMENT_API_KEY>"

Query Parameters

ParameterRequiredTypeDefaultDescription
idfalsearray[]An optional list of Proxy ID's to filter the list of proxies by
namefalsestringnullWildcard search of proxies by name

Response

Returns a paginated object with the data property containing an array of proxies. Providing any query parameters will filter the results. Returns an error if proxies could not be retrieved.

{
"pagination": {...}
"data": [
{
"id": "433013a6-a614-4e1e-b2aa-5fba67aa85e6",
"tenant_id": "77cb0024-123e-41a8-8ff8-a3d5a0fa8a08",
"name": "My Proxy",
"key": "e29a50980ca5",
"destination_url": "https://example.com/api",
"request_transform": {
"code": "
module.exports = async function (req) {
// Do something with req.configuration.SERVICE_API_KEY

return {
headers: req.args.headers,
body: req.args.body
};
};
"
},
"response_transform": {
"code": "
module.exports = async function (req) {
// Do something with req.configuration.SERVICE_API_KEY

return {
headers: req.args.headers,
body: req.args.body
};
};
"
},
"configuration": {
"SERVICE_API_KEY": "key_abcd1234"
},
"application_id": "45c124e7-6ab2-4899-b4d9-1388b0ba9d04",
"require_auth": true,
"created_by": "fb124bba-f90d-45f0-9a59-5edca27b3b4a",
"created_at": "2020-09-15T15:53:00+00:00",
"modified_by": "fb124bba-f90d-45f0-9a59-5edca27b3b4a",
"modified_at": "2021-03-01T08:23:14+00:00"
},
{...},
{...}
]
}

Get a Proxy

Get a Proxy by ID in the Tenant.

GET
https://api.basistheory.com/proxies/{id}
Copy

Permissions

proxy:read

Request

curl "https://api.basistheory.com/proxies/5b493235-6917-4307-906a-2cd6f1a90b13" \
-H "BT-API-KEY: <MANAGEMENT_API_KEY>"

URI Parameters

ParameterRequiredTypeDefaultDescription
idtrueuuidnullThe ID of the proxy

Response

Returns a Proxy with the id provided. Returns an error if the Proxy could not be retrieved.

{
"id": "433013a6-a614-4e1e-b2aa-5fba67aa85e6",
"tenant_id": "77cb0024-123e-41a8-8ff8-a3d5a0fa8a08",
"name": "My Proxy",
"key": "e29a50980ca5",
"destination_url": "https://example.com/api",
"request_transform": {
"code": "
module.exports = async function (req) {
// Do something with req.configuration.SERVICE_API_KEY

return {
headers: req.args.headers,
body: req.args.body
};
};
"
},
"response_transform": {
"code": "
module.exports = async function (req) {
// Do something with req.configuration.SERVICE_API_KEY

return {
headers: req.args.headers,
body: req.args.body
};
};
"
},
"configuration": {
"SERVICE_API_KEY": "key_abcd1234"
},
"application_id": "45c124e7-6ab2-4899-b4d9-1388b0ba9d04",
"require_auth": true,
"created_by": "fb124bba-f90d-45f0-9a59-5edca27b3b4a",
"created_at": "2020-09-15T15:53:00+00:00",
"modified_by": "fb124bba-f90d-45f0-9a59-5edca27b3b4a",
"modified_at": "2021-03-01T08:23:14+00:00"
}

Update Proxy

Update a Proxy by ID in the Tenant.

PUT
https://api.basistheory.com/proxies/{id}
Copy

Permissions

proxy:update

Request

transform='module.exports = async function (req) {
// Do something with req.configuration.SERVICE_API_KEY

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

curl "https://api.basistheory.com/proxies/433013a6-a614-4e1e-b2aa-5fba67aa85e6" \
-H "BT-API-KEY: <MANAGEMENT_API_KEY>" \
-H "Content-Type: application/json" \
-X "PUT" \
-d '{
"name": "My Proxy",
"destination_url": "https://example.com/api",
"request_transform": {
"code": '"$(echo $transform | jq -Rsa .)"',
},
"response_transform": {
"code": '"$(echo $transform | jq -Rsa .)"',
},
"configuration": {
"SERVICE_API_KEY": "key_abcd1234"
},
"application": {
"id": "45c124e7-6ab2-4899-b4d9-1388b0ba9d04"
},
"require_auth": true
}'

URI Parameters

ParameterRequiredTypeDefaultDescription
idtrueuuidnullThe ID of the proxy

Request Parameters

AttributeRequiredTypeDefaultDescription
nametruestringnullThe name of the Proxy. Has a maximum length of 200
destination_urltruestringnullThe URL to which requests will be proxied
request_transformfalseProxy Request TransformnullRequest Transform which will be executed against the proxy request before sending to the destination.
response_transformfalseProxy Response TransformnullResponse Transform which will be executed against the destination's response before returning the proxy response.
applicationfalseApplicationnullThis Application's API key is injected into a pre-configured BasisTheory JS SDK instance passed into the transform. Must be a public or private Application Type.
configurationfalsemap<string, string>nullA string key and string value map of all configuration name and values for a Proxy Transform
require_authfalsebooleantrueRequire a BT-API-KEY request header for authentication and authorization

Response

Returns a Proxy if the Proxy was updated. Returns an error if there were validation errors, or the Proxy failed to update.

{

"id": "433013a6-a614-4e1e-b2aa-5fba67aa85e6",
"tenant_id": "77cb0024-123e-41a8-8ff8-a3d5a0fa8a08",
"name": "My Proxy",
"key": "e29a50980ca5",
"destination_url": "https://example.com/api",
"request_transform": {
"code": "
module.exports = async function (req) {
// Do something with req.configuration.SERVICE_API_KEY

return {
headers: req.args.headers,
body: req.args.body
};
};
"
},
"response_transform": {
"code": "
module.exports = async function (req) {
// Do something with req.configuration.SERVICE_API_KEY

return {
headers: req.args.headers,
body: req.args.body
};
};
"
},
"configuration": {
"SERVICE_API_KEY": "key_abcd1234"
},
"application_id": "45c124e7-6ab2-4899-b4d9-1388b0ba9d04",
"require_auth": true,
"created_by": "3ce0dceb-fd0b-4471-8006-c51243c9ef7a",
"created_at": "2020-09-15T15:53:00+00:00",
"modified_by": "34053374-d721-43d8-921c-5ee1d337ef21",
"modified_at": "2021-03-01T08:23:14+00:00"
}

Patch Proxy

Patch a Proxy by ID in the Tenant.

PATCH
https://api.basistheory.com/proxies/{id}
Copy

Permissions

proxy:update
The Patch Proxies endpoint uses a different content-type to support merge-patch operations. Requests need the Content-Type header to be set to application/merge-patch+json. Requests made with a different Content-Type header value will receive a 415 Unsupported Media Type response code. For more information on merge-patch, see RFC 7386.

Request

transform='module.exports = async function (req) {
// Do something with req.configuration.SERVICE_API_KEY

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

curl "https://api.basistheory.com/proxies/433013a6-a614-4e1e-b2aa-5fba67aa85e6" \
-H "BT-API-KEY: <MANAGEMENT_API_KEY>" \
-H "Content-Type: application/merge-patch+json" \
-X "PATCH" \
-d '{
"name": "My Proxy",
"destination_url": "https://example.com/api",
"configuration": {
"SERVICE_API_KEY": "key_abcd1234"
}
}'

URI Parameters

ParameterRequiredTypeDefaultDescription
idtrueuuidnullThe ID of the proxy

Request Parameters

AttributeRequiredTypeDefaultDescription
namefalsestringnullThe name of the Proxy. Has a maximum length of 200
destination_urlfalsestringnullThe URL to which requests will be proxied
request_transformfalseProxy Request TransformnullRequest Transform which will be executed against the proxy request before sending to the destination.
response_transformfalseProxy Response TransformnullResponse Transform which will be executed against the destination's response before returning the proxy response.
applicationfalseApplicationnullThis Application's API key is injected into a pre-configured BasisTheory JS SDK instance passed into the transform. Must be a public or private Application Type.
configurationfalsemap<string, string>nullA string key and string value map of all configuration name and values for a Proxy Transform
require_authfalsebooleantrueRequire a BT-API-KEY request header for authentication and authorization

Response

Returns 204 if successful. Returns an error if there were validation errors, or the operation failed.

Delete Proxy

Delete a Proxy by ID in the Tenant.

DELETE
https://api.basistheory.com/proxies/{id}
Copy

Permissions

proxy:delete

Request

curl "https://api.basistheory.com/proxies/433013a6-a614-4e1e-b2aa-5fba67aa85e6" \
-H "BT-API-KEY: <MANAGEMENT_API_KEY>" \
-X "DELETE"

URI Parameters

ParameterRequiredTypeDefaultDescription
idtrueuuidnullThe ID of the proxy

Response

Returns an error if the Proxy failed to delete.

Proxy Object

AttributeTypeDescription
iduuidUnique identifier of the Proxy which can be used to get a Proxy
keystringAuto-generated key used to invoke this Proxy
namestringThe name of the Proxy
destination_urlstringThe URL to which requests will be proxied
tenant_iduuidThe Tenant ID which owns the Proxy
require_authbooleanRequire a BT-API-KEY request header for authentication and authorization
request_transformProxy Request Transform(Optional) Request Transform which will be executed against the proxy request before sending to the destination.
response_transformProxy Response Transform(Optional) Response Transform which will be executed against the destination's response before returning the proxy response.
application_idstring(Optional) This Application's API key is injected into a pre-configured BasisTheory JS SDK instance passed into the transform. Must be a public or private Application Type.
configurationmap<string, string>(Optional) A string key and string value map of all configuration name and values for a Proxy Transform
created_byuuid(Optional) The ID of the user or Application that created the Proxy
created_atstring(Optional) Created date of the Proxy in ISO 8601 format
modified_byuuid(Optional) The ID of the user or Application that last modified the Proxy
modified_atdate(Optional) Last modified date of the Proxy in ISO 8601 format

Proxy Request Transform Object

AttributeTypeDescription
codestringTransform code which will be executed when the Proxy transform is processed. See Request Transforms for details.

Proxy Response Transform Object

See Response Transforms for details regarding the various types of response transforms.

AttributeTypeDescription
typestringThe type of response transform. One of code or mask. Default: code.
codestringTransform code which will be executed when the Proxy transform is processed. Required when type is code
matcherstringThe type of matching. One of regex or chase_stratus_pan. Required when type is mask
replacementstringThe replacement character for masking. Must be only one character in length. Required when type is mask
expressionstringThe regular expression to use when determining masking values. Must contain at least one capture group using parenthesis. Required when type is mask and matcher is regex.

Transforms

Pre-configured proxies allow you to optionally define request or response transforms, which allow custom Node.js code to be executed before and after the HTTP request is forwarded to the destination URL. When a transform is defined on a proxy, your custom Node.js code will execute in Basis Theory's secure serverless reactor environment.

Testing

Testing Transforms works the same as testing Reactors.

Whitelisted npm modules

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

Errors

Custom errors can be returned from request and response transforms by throwing reactor errors..

Any errors thrown from a transform will cause the proxy request to be terminated and the HTTP response to be immediately returned. In particular, errors thrown from a request transform will cause the proxy request to terminate before calling the destination API.

Reactor Errors

All pre-defined reactor error types, excluding errors of type CustomHttpResponseError, will be returned in their standard format and wrapped in a proxy_error property to distinguish these errors from destination API errors.

For example, a transform containing the following code:

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

module.exports = async function (req) {
const apiKey = req.args.headers['MY-CUSTOM-API-KEY'];

if (!apiKey)
throw new AuthenticationError('MY-CUSTOM-API-KEY header is required');

// ...
}

would result in the following error response with a 401 status code if the MY-CUSTOM-API-KEY header is omitted:

{
"proxy_error": {
"errors": {
"error": [
"MY-CUSTOM-API-KEY header is required"
]
},
"title": "One or more validation errors occurred.",
"status": 401,
"detail": "Authentication Failed"
}
}

Custom Errors

To provide more control over the errors returned from a proxy transform, a CustomHttpResponseError can be thrown from the transform. This will enable you to specify a status code, custom headers, and have complete control over the response body that is returned.

For example, a transform containing the following code:

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

module.exports = async function (req) {
throw new CustomHttpResponseError({
status: 400,
headers: {
"Custom-Response-Header-1": "custom-value-1",
"Custom-Response-Header-2": "custom-value-2"
},
body: {
myCustomError: "My custom error message"
}
});
};

results in an API response with status code 400, having the headers:

Custom-Response-Header-1: custom-value-1
Custom-Response-Header-2: custom-value-2

and the response body:

{
"myCustomError": "My custom error message"
}

Request Transforms

Request Transforms can be used to:

  • Transform the body or headers on the HTTP request before forwarding the request to the destination
  • Tokenize parts of an inbound HTTP request and replace sensitive data with tokens before it hits your systems
  • Inject secrets that are configured within the proxy (e.g., third party API credentials) into the request body or headers

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.

Request transforms are Node.js v16 code blocks which export a function of the form:

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
};
};

Request Transform - Request Object

The request transform function receives the following object:

AttributeTypeDescription
argsobjectProperties of the proxy request (see below)
configurationobjectThe configuration defined for the Proxy object
btobjectA pre-configured Basis Theory JS instance if an application was configured on the Proxy object

where args contains:

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)

Request Transform - 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

Response Transforms

There are two types of Response Transforms available: code and mask.

Code Response Transforms

Code Response Transforms 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 are Node.js v16 code blocks which export a function of the form:

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
};
};
Code Response Transform - Javascript Request Object

The response transform function receives the following object:

AttributeTypeDescription
argsobjectProperties of the proxy response (see below)
configurationobjectThe configuration defined for the Proxy object
btobjectA pre-configured Basis Theory JS instance if an application was configured on the Proxy object

where args contains:

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.
Code Response Transform - Javascript 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

Mask Response Transform

Mask response transforms 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 transforms using the regex matcher are defined as regular expressions and a replacement character.

{
"name": "My masked proxy",
"destination_url": "https://echo.basistheory.com/anything",
"require_auth": false,
"response_transform": {
"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_transform": {
"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

Tokenizing or Detokenizing

In some situations, you may want to tokenize or detokenize data within a 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.