This guide will help you update payment card data from a third party or web frontend without having the data touch your own servers.
Similar to how you can capture full card data, you can use a capture endpoint to update a specific card with new data (e.g. updating the CVV temporarily for a call to a payment service provider)
By using uniquely generated capture endpoints you can ingest sensitive data without compromising your key or your authorization details. Capturing data this way is the most PCI compliant way of ingesting payment card data. The capture endpoint can be created so that any data sent through to it, updates an existing card already stored in the vault. Note: This guide will use the term "third party" to refer to third parties, your own web frontend or to any other untrusted source.
There are two ways to use a capture endpoint.
Both methods require the creation of a capture endpoint which is locked down to a specific card.
Create an endpoint for capturing data using "Create a Capturing Endpoint".
Provide the existing token you'd like to update and optionally a reference that was stored with it.
Each of these endpoints also come with a default TTL (Time To Live) of 24 hours. If you'd like to make the endpoint expire sooner, use the ttl query parameter to set it e.g. PT10M for 10 minutes. It is not recommended to make an endpoint used for card updates have a longer TTL than 24 hours.
For example, this Python code:
import requests
from requests.auth import HTTPBasicAuth
auth = HTTPBasicAuth('user', 'password')
url = "https://api.pcivault.io/v1/capture"
user = "test-user"
passphrase = "ALongAndVerySecretPassphraseThatIsSuperSecure"
token = "44c93045e3cf54d23792c7821c42c2386e3040680caaa1ab512aa45091ad8fd1"
reference = "my-reference"
res = requests.post(f'{url}?user={user}&passphrase={passphrase}&ttl=PT10M&token={token}&reference={reference}', auth=auth)
# do something with the response
print(res)
print(res.text)
should return a JSON object like this:
{
"url":"/v1/capture/NjUDoEi3z8zFB33WEwSRg",
"secret":"S2TRYkjufkfwf8oItW2G_j1HcZ1ftMvURZwZJlbzb2BylPEPo8536sqdkO6J9i3x",
"expires_at":"2022-07-25T15:42:59Z",
"lockdown_info": {
"token": "44c93045e3cf54d23792c7821c42c2386e3040680caaa1ab512aa45091ad8fd1",
"reference": "my-reference"
}
}
This endpoint can only be used to update the card with token 44c93045e3cf54d23792c7821c42c2386e3040680caaa1ab512aa45091ad8fd1 and reference my-reference. Any data passed in will be merged with the existing data, except the card number itself, as that is immutable.
First be sure to create your capture endpoint. Using a caputre endpoint to manually POST data is a 2-step process:
The way in which you share the URL and Secret to the third party depends on your setup. Typically, you would do this in response to an HTTPS request from the third party.
Here are some dos and don'ts:
If the third party is a web frontend, keep in mind that the user will have access to all data that you send. There is no effective way to protect the URL & Secret once it is on the user's browser. That is why it is a good idea to not disable expiry, and delete the endpoint after it was used.
Using the URL & Secret,
the third party can send data to the vault to be tokenized.
The secret must be in the X-PCIVault-Capture-Secret HTTP header of the POST request.
The rest of the request works exactly the same as POSTing to the vault directly from your own server, except that the basic auth details, key, and passphrase have been replaced by the URL & Secret.
For example, you can send the data using JavaScript's fetch API:
const requestInfo = {
method: 'POST',
headers: {
'X-PCIVault-Capture-Secret': 'S2TRYkjufkfwf8oItW2G_j1HcZ1ftMvURZwZJlbzb2BylPEPo8536sqdkO6J9i3x',
},
body: JSON.stringify({
"card_expiry": "06-2025",
"cvv": "145"
}),
};
fetch("https://api.pcivault.io/v1/capture/NjUDoEi3z8zFB33WEwSRg", requestInfo)
.then((response) => {
return response.json();
})
.then((response) => {
console.debug(response);
// do something with the response
})
The vault will reply to the third party with the token and reference like this:
{
"user": "test-user",
"token": "44c93045e3cf54d23792c7821c42c2386e3040680caaa1ab512aa45091ad8fd1",
"reference": "my-reference"
}
First be sure to create your capture endpoint. Using the endpoint with a configured hosted form is a 3-step process:
To create a configured hosted form, we use the Create a Hosted Form endpoint.
For example, this Python code:
import requests
import json
import base64
from requests.auth import HTTPBasicAuth
auth = HTTPBasicAuth('user', 'password')
# javascript to execute on successful submission
callback_code = """function(responseData, requestData) {
const reference = responseData.reference;
window.location.replace(`https://mywebsite.com/update/success?reference=${reference}`);
}"""
url = "https://api.pcivault.io/v1/capture/iframe"
body = {
"success_callback": base64.b64encode(callback_code.encode("utf-8")).decode("utf-8"),
"field_options": {
"reference": {
"visible": False
},
"card_holder": {
"visible": False
},
"expiry": {
"visible": False
},
"card_number": {
"visible": False
}
}
}
res = requests.post(f'{url}?form_type=pcd', auth=auth, data=json.dumps(body))
# do something with the response
print(res)
print(res.text)
should return a JSON object like this:
{
"type": "pcd",
"id": "MmRMVP4UjYD8g5kVUcmx4Z",
"link": "api.pcivault.io/v1/capture/iframe/MmRMVP4UjYD8g5kVUcmx4Z"
}
Make note of the link field, we'll use it to construct a URL to load the iframe, which makes use of the capture endpoint we created earlier.
Putting it all together, we use the capture endpoint id and secret with our configured form url as follows:
https://{{form_link}}?unique_id={{capture_endpoint_id}}&secret={{capture_endpoint_secret}}
For example,
https://api.pcivault.io/v1/capture/iframe/MmRMVP4UjYD8g5kVUcmx4Z?unique_id=NjUDoEi3z8zFB33WEwSRg&secret=S2TRYkjufkfwf8oItW2G_j1HcZ1ftMvURZwZJlbzb2BylPEPo8536sqdkO6J9i3x
The first part of the URL is the link to the configured form, and as query string parameters we pass the capture endpoint id as well as the capture endpoint secret. This URL will load the configured hosted form which hides all fields except the CVV, coupled to the capture endpoint which we locked down to a specific card token and reference. Data submitted through this form will be merged with the existing data stored in the vault, thereby updating the CVV field only. (If you would like to update the expiry date too, simply create your configured hosted form with "expiry": {"visible": True} in the field_options)
This URL can be loaded as the src of an iframe or the user can be redirected to it.
When the HTML form is submitted, the data captured hits the capture endpoint. On a successful HTTP request, the callback function will be executed. In this example we created the configured form with a callback function which redirects the user to https://mywebsite.com/update/success?reference=${reference}, but any of the returned fields (token, reference or user) can be leveraged to determine what the next page rendered looks like.