PCI Vault has the ability to forward card data to third parties.
In this proxy recipe, we'll detail how to cater to a common use-case, where card data is forwarded to Adyen to create a payment transaction without it ever passing through your own server.
Unlike some other payment gateways, Adyen does not require any complicated hashed signatures or data encryption to be applied on the data. This removes the need to create a custom rule to do all the computation. The process is relatively straighforward.
In this proxy recipe, we'll show you how to:
We'll use the Proxy Post endpoint to initiate a proxy request. The following query string parameters are required:
token: the token identifying the card we'd like to send to Adyenuser: the key used to encrypt the datapassphrase: the passphrase for the key used to encrypt the dataThe request URL will look like https://api.pcivault.io/v1/proxy/post?token=uniquetoken&user=ABCD&passphrase=secretpassphrase
The request body will look something like:
{
"request": {
"method": "POST",
"url": "https://yoursubdomain.adyen.com/v71/payments", //remember to set your account-specific subdomain here
"headers": [
{
"Content-Type": "application/json"
},
{
"X-API-Key": "{{api_key}}"
},
{
"Idempotency-Key": "{{idempotency_key}}"
}
],
"body": "{\"amount\": {\"currency\": \"{{currency}}\",\"value\": {{amount}}},\"reference\": \"{{reference}}\",\"paymentMethod\": {\"type\": \"scheme\",\"number\": \"{{card_number}}\",\"expiryMonth\": \"{{expiry_month}}\",\"expiryYear\": \"{{expiry_year}}\",\"holderName\": \"{{card_holder}}\",\"cvc\": \"{{cvv}}\"},\"returnUrl\": \"{{return_url}}\",\"merchantAccount\": \"{{merchant_account}}\"}",
"extra_data": {
"api_key": "your-adyen-api-key",
"idempotency_key": "uuid-generated-for-request",
"currency": "USD",
"amount": 1000,
"reference": "youruniqueref",
"return_url": "https://your-company.example.com/...",
"merchant_account": "yourmerchantaccount",
}
},
"synchronous": true
}
(Note: this request uses field names as they would be captured by our Hosted Form, if your data is in a different format, these field names have to be adjusted accordingly)
We define the proxy request as being a "POST" method, having content-type header of application/json and we also set our Adyen API key and unique idempotency key as headers. For the body we'll set a mustache template, where PCI Vault will populate the values from the vault before sending the request to Adyen. Note that one can construct the body template string with fields already populated or like in this case, set an extra_data object whose fields will be merged with the stored data before being populated in the mustache template. Using extra_data is often simpler and cleaner than string concatenation.
The parsed JSON for the body field looks like:
{
"amount": {
"currency": "{{currency}}",
"value": {{amount}}
},
"reference": "{{reference}}",
"paymentMethod": {
"type": "scheme",
"number": "{{card_number}}",
"expiryMonth": "{{expiry_month}}",
"expiryYear": "{{expiry_year}}",
"holderName": "{{card_holder}}",
"cvc": "{{cvv}}"
},
"returnUrl": "{{return_url}}",
"merchantAccount": "{{merchant_account}}"
}
One optional parameter that is set in this example is "synchronous": true. This will tell PCI Vault to wait for the Adyen response to be returned and will send the result back to us when the request completes.
The response from Adyen will be wrapped in a JSON object like this:
{
"id": "SLHpcudvjdUCokB2UCkR4n",
"status": "success",
"type": "post",
"use_static_ip": false,
"synchronous": true,
"request": {
"method": "POST",
"url": "https://yoursubdomain.adyen.com/v71/payments",
"headers": [
{
"content-type": "application/json"
},
{
"X-API-Key": "{{api_key}}"
},
{
"Idempotency-Key": "{{idempotency_key}}"
}
],
"body": "...",
"extra_data": {
"api_key": "your-adyen-api-key",
"idempotency_key": "uuid-generated-for-request",
"currency": "USD",
"amount": 1000,
"reference": "youruniqueref",
"return_url": "https://your-company.example.com/...",
"merchant_account": "yourmerchantaccount",
}
},
"webhook": {
"status": "pending"
},
"max_attempts": 1,
"attempts": 0,
"debug_mode": false,
"received": "2025-11-12T14:06:06.621177+00:00",
"result": {
"headers": [
{
"Content-Type": "application/json"
},
...
],
"body": "{\"additionalData\": {\"cvcResult\": \"1 Matches\",\"authCode\": \"044925\",\"avsResult\": \"4 AVS not supported for this card type\",\"avsResultRaw\": \"4\",\"cvcResultRaw\": \"M\",\"refusalReasonRaw\": \"AUTHORISED\",\"acquirerCode\": \"TestPmmAcquirer\",\"acquirerReference\": \"8PQMP9VEP3H\"},\"pspReference\": \"993617895204576J\",\"resultCode\": \"Authorised\",\"merchantReference\": \"string\"}",
"status_code": 200
}
}
The response from Adyen is in the result field. The body is returned as a JSON string, which can be parsed and handled as needed.