Forward API
Examples
Contact your Account Manager for more information or submit an inquiry to our Business Development team.
- Functions
- HTTP basic auth
- Hashed data
- Transformations and overrides
- Conditional transformations
- XML sibling elements sharing a name
- XML attributes
- CVV with vaulted card data
- Forwarding multiple payment methods
- Forwarding multiple payment methods with aliases
Functions
The Forward API provides a number of functions that can be used to construct requests.
Here is part
of a config that uses the join
function to concatenate the card number and CVV with a
hyphen:
- JSON
{
"name": "join_example",
"transformations": [
{
"path": "/body/card_data",
"value": ["join", "-", ["array", "$number", "$cvv"]]
}
]
}
join("-", [number, cvv])
in another programming language.Returns:
- JSON
{
"card_data": "4012888888881881-123"
}
Nested functions
These functions can be composed just like functions in most programming languages. For example, you
could use the join
and base64
functions to encode the above value in base
64.
- JSON
{
"name": "join_example",
"transformations": [
{
"path": "/body/card_data",
"value": ["base64", ["join", "-", ["array", "$number", "$cvv"]]]
}
]
}
base64(join("-", [number, cvv]))
in another programming language.Returns:
- JSON
{
"card_data": "NDAxMjg4ODg4ODg4MTg4MS0xMjM="
}
HTTP basic auth
You can use nested functions to accomplish HTTP basic auth.
- JSON
{
"name": "basic_auth_example",
"transformations": [
{
"path": "/body/card/number",
"value": "$number"
},
{
"path": "/header/Authorization",
"value": [
"join",
" ",
[
"array",
"Basic",
["base64", ["join", ":", ["array", "$user", "$password"]]]
]
]
}
]
}
$user
and $password
will be
provided in each forwarding request under either sensitive_data
or data
.
- bash
curl -i https://forwarding.sandbox.braintreegateway.com/ \
-H "Content-Type: application/json" \
-X POST \
-u "${BRAINTREE_PUBLIC_KEY}:${BRAINTREE_PRIVATE_KEY}" \
-d '{
"merchant_id": "${BRAINTREE_MERCHANT_ID}",
"payment_method_nonce": "fake-valid-nonce",
"debug_transformations": true,
"url": "https://httpbin.org/post",
"method": "POST",
"sensitive_data": {
"user": "unicorn",
"password": "rainbow"
},
"config": {
"name": "basic_auth_example",
"methods": ["POST"],
"url": "^https://httpbin\\.org/post$",
"request_format": {"/body": "json"},
"types": ["CreditCard"],
"transformations": [
{
"path": "/body/card/number",
"value": "$number"
},
{
"path": "/header/Authorization",
"value": [
"join",
" ",
[
"array",
"Basic",
["base64", ["join", ":", ["array", "$user", "$password"]]]
]
]
}
]
}
}'
X-Query-String:
Request-UUID: a-unique-identifier-for-the-request
User-Agent: Braintree Forward API/1.0
Authorization: Basic dW5pY29ybjpyYWluYm93
- JSON
{
"card": {
"number": "4012888888881881"
}
}
Trace-ID
You can add a tracer to a Forward API request by including the header -H “Trace-Id: 123456790357”. The tracer value you pass in Trace-Id will show up in all of the logs for this request.
Hashed data
This config demonstrates the following transformations:
- Hash functions
- Template reference
- Variable override
- bash
curl -i https://forwarding.sandbox.braintreegateway.com/ \
-H "Content-Type: application/json" \
-X POST \
-u "$\{BRAINTREE_PUBLIC_KEY}:$\{BRAINTREE_PRIVATE_KEY}" \
-d '{
"merchant_id": "'$BRAINTREE_MERCHANT_ID'",
"payment_method_nonce": "fake-valid-nonce",
"debug_transformations": true,
"url": "https://httpbin.org/post",
"method": "POST",
"data": {
"cardholder_name": "Pat Smith"
},
"config": {
"name": "hashed_data_example",
"methods": ["POST"],
"url": "^https://httpbin\\.org/post$",
"request_format": {"/body": "xml"},
"types": ["CreditCard"],
"transformations": [
{
"path": "/body/card/number",
"value": "$number"
},
{
"path": "/body/card/cardholder_name",
"value": "$cardholder_name"
},
{
"path": "/urlparam/card_md5",
"value": ["base64", ["md5", "$/body/card"]]
}
]
}
}'
X-Query-String: card_md5=NN59PISOxm8jEIV1xMbvmw%3D%3D
Request-UUID: a-unique-identifier-for-the-request
User-Agent: Braintree Forward API/1.0
- XML
<card>
<number>4012888888881881</number>
<cardholder_name>Pat Smith</cardholder_name>
</card>
$cardholder_name
as a variable override. The
$cardholder_name
is normally
provided by the Braintree Vault, we
override it here with "Pat Smith"
.
We apply md5
and base64
to
the $/body/card
portion of the request, this creates a hash of the serialized content
under the path /body/card
. In this request we're specifiying XML as the serialization
format for the /body
.
Transformations and overrides
This request demonstrates the interaction of transformations and request overrides.
- bash
curl https://forwarding.sandbox.braintreegateway.com/ \
-H "Content-Type: application/json" \
-X POST \
-u "$\{BRAINTREE_PUBLIC_KEY}:$\{BRAINTREE_PRIVATE_KEY}" \
-d '{
"merchant_id": "'$BRAINTREE_MERCHANT_ID'",
"payment_method_nonce": "fake-valid-nonce",
"debug_transformations": true,
"url": "https://httpbin.org/post",
"method": "POST",
"override": {
"body": "<card> <number></number> <cardholder_name>Overridden</cardholder_name> <supplemental_data>passed through</supplemental_data> </card>"
},
"config": {
"name": "transformations_and_overrides",
"methods": ["POST"],
"url": "^https://httpbin\\.org/post$",
"request_format": {"/body": "xml"},
"types": ["CreditCard"],
"transformations": [
{
"path": "/body/card/number",
"value": "$number"
},
{
"path": "/body/card/cardholder_name",
"value": "$cardholder_name"
}
]
}
}'
- XML
<card>
<number>4012888888881881</number>
<cardholder_name>Overridden</cardholder_name>
<supplemental_data>passed through</supplemental_data>
</card>
A few notes on the values passed in the example request above:
effectively serves as a placeholder – if omitted, the transformation will place
as the final element4012888888881881
takes precedence over the transformation because the override value is non-emptyOverridden -
Any additional components of the request that are not affected by transformations – in this
case,
– are passed throughpassed through
Conditional transformations
This request demonstrates the if_defined
transformation modifier.
- bash
curl https://forwarding.sandbox.braintreegateway.com/ \
-H "Content-Type: application/json" \
-X POST \
-u "${BRAINTREE_PUBLIC_KEY}:${BRAINTREE_PRIVATE_KEY}" \
-d '{
"merchant_id": "'"$BRAINTREE_MERCHANT_ID"'",
"payment_method_nonce": "fake-valid-nonce",
"debug_transformations": true,
"url": "https://httpbin.org/post",
"method": "POST",
"config": {
"name": "conditional_transformations",
"methods": ["POST"],
"url": "^https://httpbin\.org/post$",
"request_format": {"/body": "json"},
"types": ["CreditCard"],
"transformations": [
{"path": "/body/card/number", "value": "$number"},
{"path": "/body/card/cardholder_name", "value": "$cardholder_name", "if_defined": "$cardholder_name"},
{"path": "/body/card/cvv", "value": "$cvv", "if_defined": "$cvv"}
]
}
}'
- JSON
{
"card": {
"number": "4012888888881881",
"cvv": "123"
}
}
if_defined
modifier requires the value to be present in order for the
transformation to be applied. Note that the test payment method nonce used in this example,
fake-valid-nonce
, doesn't provide a $cardholder_name
but does provide a
$cvv
.
XML sibling elements sharing a name
This configuration demonstrates numerically indexed transformation paths.
- bash
curl https://forwarding.sandbox.braintreegateway.com/ \
-H "Content-Type: application/json" \
-X POST \
-u "${BRAINTREE_PUBLIC_KEY}:${BRAINTREE_PRIVATE_KEY}" \
-d '{
"merchant_id": "'"$BRAINTREE_MERCHANT_ID"'",
"payment_method_nonce": "fake-valid-nonce",
"debug_transformations": true,
"url": "https://httpbin.org/post",
"method": "POST",
"data": {"item_1_id": "1234", "item_2_id": "5678"},
"config": {
"name": "xml_sibling_example",
"methods": ["POST"],
"url": "^https://httpbin\.org/post$",
"request_format": {"/body": "xml"},
"types": ["CreditCard"],
"transformations": [
{"path": "/body/card/number", "value": "$number"},
{"path": "/body/cart/[0]/item/id", "value": "$item_1_id"},
{"path": "/body/cart/[1]/item/id", "value": "$item_2_id"},
]
}
}'
- XML
<card>
<number>4012888888881881</number>
</card>
<cart>
<item>
<id>1234</id>
</item>
<item>
<id>5678</id>
</item>
</cart>
XML attributes
This configuration demonstrates setting XML attributes.
- bash
curl https://forwarding.sandbox.braintreegateway.com/ \
-H "Content-Type: application/json" \
-X POST \
-u "${BRAINTREE_PUBLIC_KEY}:${BRAINTREE_PRIVATE_KEY}" \
-d '{
"merchant_id": "'"$BRAINTREE_MERCHANT_ID"'",
"payment_method_nonce": "fake-valid-nonce",
"debug_transformations": true,
"url": "https://httpbin.org/post",
"method": "POST",
"config": {
"name": "xml_attribute_example",
"methods": ["POST"],
"url": "^https://httpbin\.org/post$",
"request_format": {"/body": "xml"},
"types": ["CreditCard"],
"transformations": [
{"path": "/body/card/number", "value": "$number"},
{"path": "/body/card/@type", "value": "$card_type"}
]
}
}'
- XML
<card type="Visa">
<number>4012888888881881</number>
</card>
CVV with vaulted card data
Braintree does not store CVVs of vaulted payment methods for compliance reasons. If the destination
API requires CVV and you are using vaulted card data, you must specify a
payment_method_nonce
containing the CVV along with your long-lived
payment_method_token
.
You can collect a CVV-only nonce with the client SDKs by
tokenizing only the CVV property. Once you have that nonce, you can make a request that includes
both the payment_method_token
and CVV-only payment_method_nonce
:
- bash
curl https://forwarding.sandbox.braintreegateway.com/ \
-H "Content-Type: application/json" \
-X POST \
-u "${BRAINTREE_PUBLIC_KEY}:${BRAINTREE_PRIVATE_KEY}" \
-d '{
"merchant_id": "'"$BRAINTREE_MERCHANT_ID"'",
"payment_method_token": "'"$TOKEN"'",
"payment_method_nonce": "'"$CVV_ONLY_NONCE"'",
"debug_transformations": true,
"url": "https://httpbin.org/post",
"method": "POST",
"config": {
"name": "cvv_with_vaulted_data_example",
"methods": ["POST"],
"url": "^https://httpbin\.org/post$",
"request_format": {"/body": "json"},
"types": ["CreditCard"],
"transformations": [
{"path": "/body/card/number", "value": "$number"},
{"path": "/body/card/cvv", "value": "$cvv_2"}
]
}
}'
- JSON
{
"card": {
"number": "4111111111111111",
"cvv": "123"
}
}
$number
variable will come from the payment_method_token
and
$cvv_2
will come from the payment_method_nonce
per the Forward API's
variable suffixing.
Forwarding multiple payment methods
This configuration demonstrates forwarding multiple payment methods using
variable suffixes
and using the
index value-1
to append.
In the example below, the destination API accepts any number of cards
under both set_A
and set_B
. Variables passed in data
are used
to control which transformations are performed.
- bash
curl https://forwarding.sandbox.braintreegateway.com/ \
-H "Content-Type: application/json" \
-X POST \
-u "${BRAINTREE_PUBLIC_KEY}:${BRAINTREE_PRIVATE_KEY}" \
-d '{
"merchant_id": "'"$BRAINTREE_MERCHANT_ID"'",
"payment_method_tokens": ["'"$TOKEN_1"'", "'"$TOKEN_2"'"],
data: {
"first_card_in_set_A": true,
"second_card_in_set_A": true,
"first_card_in_set_B": false,
"second_card_in_set_B": true
},
"debug_transformations": true,
"url": "https://httpbin.org/post",
"method": "POST",
"config": {
"name": "forwarding_multiple_payment_methods_example",
"methods": ["POST"],
"url": "^https://httpbin\.org/post$",
"request_format": {"/body": "xml"},
"types": ["CreditCard"],
"transformations": [
{"path": "/body/data/set_A/card/[0]", "value": "$number_1", "if_defined": "$first_card_in_set_A"},
{"path": "/body/data/set_A/card/[-1]", "value": "$number_2", "if_defined": "$second_card_in_set_A"},
{"path": "/body/data/set_B/card/[0]", "value": "$number_1", "if_defined": "$first_card_in_set_B"},
{"path": "/body/data/set_B/card/[-1]", "value": "$number_2", "if_defined": "$second_card_in_set_B"}
]
}
}'
set_A
but only the second is a member
of set_B
, producing the following XML:
- XML
<data>
<set_A>
<card>378282246310005</card>
<card>4111111111111111</card>
</set_A>
<set_B>
<card>4111111111111111</card>
</set_B>
</data>
set_A
and set_B
uses the index value
-1
to append because the second card's membership in either set is completely
independent of the first card's set membership. It would be possible to express the full set of
possible states with absolute indices, but doing so would require additional conditional
transformations.
Forwarding multiple payment methods with aliases
This configuration represents an alternative to the additional control variables used in
Forwarding multiple payment methods:
variable_aliases
. This approach is somewhat more flexible, but may be less concise than a control variable approach
dependent on the constraints of the destination API.
In the example below, the destination API
accepts any number of cards under both set_A
and set_B
.
- bash
curl https://forwarding.sandbox.braintreegateway.com/ \
-H "Content-Type: application/json" \
-X POST \
-u "${BRAINTREE_PUBLIC_KEY}:${BRAINTREE_PRIVATE_KEY}" \
-d '{
"merchant_id": "'"$BRAINTREE_MERCHANT_ID"'",
"payment_method_tokens": ["'"$TOKEN_1"'", "'"$TOKEN_2"'", "'"$TOKEN_3"'"],
"debug_transformations": true,
"variable_aliases": {"first_A": "number_1", "first_B", "number_2", "second_A": "number_3", "second_B": "number_3"},
"url": "https://httpbin.org/post",
"method": "POST",
"config": {
"name": "forwarding_multiple_payment_methods_example",
"methods": ["POST"],
"url": "^https://httpbin\.org/post$",
"request_format": {"/body": "xml"},
"types": ["CreditCard"],
"transformations": [
{"path": "/body/data/set_A/card/[0]", "value": "$first_A", "if_defined": "$first_A"},
{"path": "/body/data/set_A/card/[-1]", "value": "$second_A", "if_defined": "$second_A"},
{"path": "/body/data/set_B/card/[0]", "value": "$first_B", "if_defined": "$first_B"},
{"path": "/body/data/set_B/card/[-1]", "value": "$number_2", "if_defined": "$second_B"}
]
}
}'
TOKEN_1
is a member of set_A
,
TOKEN_2
is a member of set_B
, and TOKEN_3
is a member of both
set_A
and set_B
, producing the following XML:
- XML
<data>
<set_A>
<card>4111111111111111</card>
<card>5555555555554444</card>
</set_A>
<set_B>
<card>378282246310005</card>
<card>5555555555554444</card>
</set_B>
</data>