PCI Vault Logo
Authorize.net

Sending card data to Authorize.net

PCI Vault has the ability to forward card data to third parties.

In this proxy recipe, we'll detail how to cater to the use-case, where card data is forwarded to Authorize.net to charge a credit card without the card data ever passing through your own server.

Authorize.net 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 and makes forwarding the card data easy. You'll only need to obtain your API authentication credentials from the Authorize.net dashboard.

Overview

In this proxy recipe, we'll show you how to:

  1. Initiate a proxy request
  2. Handle the response

Step 1: Initiate a proxy request

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 Authorize.net
  • user: the key used to encrypt the data
  • passphrase: the passphrase for the key used to encrypt the data

Optional:

  • reference: if the card data was stored with a reference, this will be required to identify it in the vault

The 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 this:

{
  "request": {
    "method": "POST",
    "url": "https://api.authorize.net/xml/v1/request.api",
    "headers": [
      {
        "Content-Type": "application/json"
      }
    ],
    "body": "{\"createTransactionRequest\": {\"merchantAuthentication\": {\"name\": \"{{auth_name}}\",\"transactionKey\": \"{{auth_transaction_key}}\"},\"refId\": \"{{transaction_reference}}\",\"transactionRequest\": {\"transactionType\": \"authCaptureTransaction\",\"amount\": \"{{amount}}\",\"payment\": {\"creditCard\": {\"cardNumber\": \"{{card_number}}\",\"expirationDate\": \"{{expiry_year}}-{{expiry_month}}\",\"cardCode\": \"{{cvv}}\"}}}}}",
    "extra_data": {
      "auth_name": "5KP3u95bQpv", // <- enter your API credentials here
      "auth_transaction_key": "346HZ32z3fP4hTG2", // <- enter your API credentials here
      "transaction_reference": "your_unique_ref",
      "amount": "50.0"
    }
  },
  "synchronous": true
}

We define the proxy request as being a "POST" method, having content-type of application/json as a header. For the body we'll set a mustache template, where PCI Vault will populate the values from the vault before sending the request to Authorize.net. 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. One important consideration when using the Authorize.net API is that it is not a REST API, but rather it's based on posting XML to one endpoint. This means the order of the fields as they appear in the request body is important and you should consult their API documentation when setting custom data, this example only contains the most basic parameters.

When parsed, the body parameter looks like:

{
  "createTransactionRequest": {
    "merchantAuthentication": {
      "name": "{{auth_name}}",
      "transactionKey": "{{auth_transaction_key}}"
    },
    "refId": "{{transaction_reference}}",
    "transactionRequest": {
      "transactionType": "authCaptureTransaction",
      "amount": "{{amount}}",
      "payment": {
        "creditCard": {
          "cardNumber": "{{card_number}}",
          "expirationDate": "{{expiry_year}}-{{expiry_month}}",
          "cardCode": "{{cvv}}"
        }
      }
    }
  }
}

Note the field names like expiry_year and expiry_month will exist in the vault if the data was captured using the Hosted Capture Form, if your data differs you will need to create a custom rule using the Rule Engine to convert your expiry date to the correct format before using it in this template.

One optional parameter that is set in this example is "synchronous": true. This will tell PCI Vault to wait for the Authorize.net response to be returned and will send the result back to us when the request completes.

Step 2: Handle the response from Authorize.net

The response from Authorize.net 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://api.authorize.net/xml/v1/request.api",
    "headers": [
      {
        "content-type": "application/xml"
      }
    ],
    "body": "...",
    "extra_data": {
      "auth_name": "5KP3u95bQpv",
      "auth_transaction_key": "346HZ32z3fP4hTG2",
      "transaction_reference": "your_unique_ref",
      "amount": "50.0"
    }
  },
  "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": "[third party resonse as JSON string]", // <- Authorize.net response
    "status_code": 200
  }
}

The response from Authorize.net is in the result field. The body is returned as a JSON string, which can be parsed and handled appropriately.