Single card export
If you need to send a single payment method to an HTTPS endpoint, use the single card form of payment method distribution. If you are looking to export more than one card at a time to an SFTP endpoint, please see batch export instead.
Provision a test receiver
Spreedly provides a test receiver that simulates the functionality of a production receiver, but does not deliver the request to a third-party endpoint.
The test receiver will 'echo' the parsed and formatted request in the delivery response, with sensitive data scrubbed. This allows you to validate the deliver API request while ensuring the request is properly formatted using our provided receiver variables and functions.
Additionally, the test receiver can only deliver test payment methods. Begin your integration by creating a test receiver pointing to the endpoint host (the <https://
> and domain name but not the path) you wish to deliver to.
Here, we want to simulate the delivery of payment methods to the URL <https://spreedly-echo.herokuapp.com/
>. For more detail, see the API documentation.
$ curl https://core.spreedly.com/v1/receivers.json \
-u 'BznvQ5afPZiRCXpjjtGPNMyBDNP:rg6SILuBIEkL2JBC6eabB14SUpIYLpUVSGvAarWfsbkLubANfERceJOK6DRaYl4O' \
-H 'Content-Type: application/json' \
-d '{
"receiver": {
"receiver_type": "test",
"hostnames": "https://spreedly-echo.herokuapp.com",
"credentials": [
{
"name": "app-id",
"value": 1234,
"safe": true
},
{
"name": "app-secret",
"value": 5678
}
]
}
}'
$ curl https://core.spreedly.com/v1/receivers.xml \
-u 'BznvQ5afPZiRCXpjjtGPNMyBDNP:rg6SILuBIEkL2JBC6eabB14SUpIYLpUVSGvAarWfsbkLubANfERceJOK6DRaYl4O' \
-H 'Content-Type: application/xml' \
-d '<receiver>
<receiver_type>test</receiver_type>
<hostnames>https://spreedly-echo.herokuapp.com</hostnames>
<credentials>
<credential>
<name>app-id</name>
<value>1234</value>
<safe>true</safe>
</credential>
<credential>
<name>app-secret</name>
<value>5678</value>
</credential>
</credentials>
</receiver>'
The response will include a token
value identifying the new receiver, which you will use when you need to distribute card data from Spreedly to the receiver.
{
"receiver": {
"company_name": "TEST",
"receiver_type": "test",
"token": "TdXjq6sqBHpD1200iIvUhYy9x50",
"hostnames": "https://spreedly-echo.herokuapp.com",
"state": "retained",
"created_at": "2020-02-13T18:38:04Z",
"updated_at": "2020-02-13T18:38:04Z",
"credentials": [
{
"name": "app-id",
"value": 1234,
"safe": true
},
{
"name": "app-secret",
"safe": false
}
]
}
}
<receiver>
<company_name>TEST</company_name>
<receiver_type>test</receiver_type>
<token>NG7rSGp3MPJIWEXwKxZ5sr7tgvj</token>
<hostnames>https://spreedly-echo.herokuapp.com</hostnames>
<state>retained</state>
<created_at type="dateTime">2020-02-13T18:38:04Z</created_at>
<updated_at type="dateTime">2020-02-13T18:38:04Z</updated_at>
<credentials type="array">
<credential>
<name>app-id</name>
<value>1234</value>
<safe>true</safe>
</credential>
<credential>
<name>app-secret</name>
<safe>false</safe>
</credential>
</credentials>
</receiver>
If you are provisioning a different test receiver that requires additional credentials, see the credentials section below.
Deliver a payment method
Once you've specified where to deliver card data (i.e., the receiver), you have to specify what to deliver (i.e., the payment method and any other required fields). The best way to think about payment method distribution is that you send Spreedly the raw HTTP request structure and then Spreedly populates your request with the sensitive data from your credit card vault before sending the request to the receiver. Once you have a receiver provisioned, you need to tell Spreedly how to build the HTTP request, including the sensitive card data. This request structure is built using a simple templating language and the deliver API endpoint.
There are five basic properties that define the distribution of a payment method:
- the token representing the payment method to be distributed,
- the URL to distribute the payment method to,
- the HTTP request headers,
- the HTTP request method, and
- the HTTP request body.
The exact content of these elements will be determined by the third-party receiver to which the payment method will be delivered. These elements may include information about the transaction, such as a product or flight number, the intended recipient of an order, or a payment amount. Please refer to the third-party endpoint you're using in production for information about their expected format and fields.
A simple deliver request might look like the following:
curl https://core.spreedly.com/v1/receivers/0B0G6G51EG9KE87WXDG4JHQQX8/deliver.json \
-u 'BznvQ5afPZiRCXpjjtGPNMyBDNP:rg6SILuBIEkL2JBC6eabB14SUpIYLpUVSGvAarWfsbkLubANfERceJOK6DRaYl4O' \
-H 'Content-Type: application/json' \
-d '{
"delivery": {
"payment_method_token": "1rpKvP8zOUhj4Y9EDrIoIYQzzD5",
"url": "https://spreedly-echo.herokuapp.com",
"headers": "Content-Type: application/json",
"body": "{ \"product_id\": \"916598\", \"card_number\": \"{{credit_card_number}}\" }"
}
}'
curl https://core.spreedly.com/v1/receivers/3NMQGR10238TTVHZQV6VWED60Y/deliver.xml \
-u 'BznvQ5afPZiRCXpjjtGPNMyBDNP:rg6SILuBIEkL2JBC6eabB14SUpIYLpUVSGvAarWfsbkLubANfERceJOK6DRaYl4O' \
-H 'Content-Type: application/xml' \
-d '<delivery>
<payment_method_token>1rpKvP8zOUhj4Y9EDrIoIYQzzD5</payment_method_token>
<url>https://spreedly-echo.herokuapp.com</url>
<headers><![CDATA[Content-Type: application/json]]></headers>
<body><![CDATA[{
"product_id":"916593",
"card_number":"{{ credit_card_number }}"
}]]></body>
</delivery>'
Template variables
When you invoke the deliver endpoint on the Spreedly API, you have to tell Spreedly how to format the HTTP request that will be sent to the receiver. The url
, headers
, and body
values all accept template syntax that is evaluated when the deliver request is sent. These templates allow you to format the request in the structure required by the endpoint without directly accessing sensitive information.
For instance, if you need to create the following JSON request body to send to your receiver:
{
"product_id":"916593",
"card_number":"4111111111111111"
}
Then you would specify the deliver request body as follows:
{
"product_id":"916593",
"card_number":"{{ credit_card_number }}"
}
Any value that you want Spreedly to insert for you should be specified using template syntax: {{ variable_name }}
. Spreedly will insert the value of the given variable that corresponds to the specified payment method represented by the payment_method_token
element into your request template.
A list of all available variables can be found in the reference documentation here.
Template functions
A set of receiver functions is also available to dynamically modify values when a deliver request is sent. For instance, to send a basic authorization HTTP header, you would use the base64
function:
Authorization: Basic {{#base64}}{{ user }}:{{ password }}{{/base64}}
In the above example, base64
encodes the username and password values (which may have been set as credentials when initially provisioning the receiver). Assuming a user value of user
and a password of Pa$$werd
, the resulting value sent to the receiver will be
Authorization: Basic dXNlcjpQYSQkd2VyZA==
All receiver template functions wrap some content, which is then operated on. These functions require leading and trailing tags, which use the syntax {{#function}}
and {{/function}}
, respectively.
A list of all receiver functions can be found in the reference docs.
Provision a production receiver
Once you have completed testing with a test receiver, you will need to provision a production receiver. Production receiver types are more restricted in that they have a pre-specified hostname that must be allowed by Spreedly before they can be used. You will need to contact Spreedly directly to get your receiver endpoint and new receiver_type
provisioned.
Once your receiver has been implemented by Spreedly, you can provision it using the receiver type given to you by Spreedly (or use one of our existing receivers listed below). Production receivers don't accept hostnames since those values are hard-coded into the receiver:
$ curl https://core.spreedly.com/v1/receivers.json \
-u 'BznvQ5afPZiRCXpjjtGPNMyBDNP:rg6SILuBIEkL2JBC6eabB14SUpIYLpUVSGvAarWfsbkLubANfERceJOK6DRaYl4O' \
-H 'Content-Type: application/json' \
-d '{
"receiver": {
"receiver_type": "sabre"
}
}'
{
"receiver": {
"company_name": "Sabre",
"receiver_type": "sabre",
"token": "7VdCtEYxttQ7bGMz0EjYZFRFMpH",
"hostnames": "https://webservices.sabre.com, https://webservices3.sabre.com, https://webservices.havail.sabre.com",
"state": "retained",
"created_at": "2017-07-27T17:55:23Z",
"updated_at": "2017-07-27T17:55:23Z",
"credentials": null
}
}
$ curl https://core.spreedly.com/v1/receivers.xml \
-u 'BznvQ5afPZiRCXpjjtGPNMyBDNP:rg6SILuBIEkL2JBC6eabB14SUpIYLpUVSGvAarWfsbkLubANfERceJOK6DRaYl4O' \
-H 'Content-Type: application/xml' \
-d '<receiver>
<receiver_type>sabre</receiver_type>
</receiver>'
<receiver>
<company_name>Sabre</company_name>
<receiver_type>sabre</receiver_type>
<token>MY9oI3uxM7Mu4Mafsqv505mCFOm</token>
<hostnames>https://webservices.sabre.com, https://webservices3.sabre.com, https://webservices.havail.sabre.com</hostnames>
<state>retained</state>
<created_at type="dateTime">2017-07-27T17:55:24Z</created_at>
<updated_at type="dateTime">2017-07-27T17:55:24Z</updated_at>
<credentials nil="true"></credentials>
</receiver>
If you have a working payment method distribution integration with a test receiver, you should be able to replace the receiver token in your existing deliver
call with the new receiver token when you are ready to move to production. You should also confirm that the url
, headers
and body
are correctly formatted to work with the third-party API endpoint.
The full list of currently supported receivers and the API endpoints they are allowed to access is included in our documentation.
Credentials
If your receiver endpoint requires authentication, you can specify credentials on creation. These credentials will then be available as a variable when making the actual deliver request. Credentials are supplied as one or more name/value pairs. The safe
property indicates values that are not sensitive (e.g., public keys and usernames). These values may be echoed back in receiver transcripts and other integration artifacts. Credentials that do not have safe=true
are considered sensitive and will never be output in plain text anywhere except to the receiver within a deliver request.
Credentials should be used sparingly. You should specify credentials only if you have values you don't want echoed in transcripts and other artifacts. Otherwise, it's best to store dynamic values yourself and to insert them into the template you send to Spreedly. This approach is simpler and provides clear separation between Spreedly's responsibility to manage sensitive data and your responsibility to format the request and to provide the rest of the template.
Recache CVVs
According to the PCI standard, CVVs can't be persisted in long-term storage, even by a vaulting provider like Spreedly. If you need to include CVV data in your receiver request, you will need to recache the CVV first before invoking the deliver
request. On successful completion of a receiver request, the CVV will be wiped from Spreedly's data. Therefore, you will need to recache the CVV immediately prior to every receiver call.
Diagnose Errors
If you attempt to add a receiver using a receiver_type
that is not available, you will receiver a 403
error response:
$ curl https://core.spreedly.com/v1/receivers.json \
-u 'BznvQ5afPZiRCXpjjtGPNMyBDNP:rg6SILuBIEkL2JBC6eabB14SUpIYLpUVSGvAarWfsbkLubANfERceJOK6DRaYl4O' \
-H 'Content-Type: application/json' \
-d '{
"receiver": {
"receiver_type": "NOTREAL"
}
}'
{
"errors": [
{
"key": "errors.unknown_receiver_type",
"message": "The specified receiver_type is not supported"
}
]
}
$ curl https://core.spreedly.com/v1/receivers.xml \
-u 'BznvQ5afPZiRCXpjjtGPNMyBDNP:rg6SILuBIEkL2JBC6eabB14SUpIYLpUVSGvAarWfsbkLubANfERceJOK6DRaYl4O' \
-H 'Content-Type: application/xml' \
-d '<receiver>
<receiver_type>NOTREAL</receiver_type>
</receiver>'
<errors>
<error key="errors.unknown_receiver_type">The specified receiver_type is not supported</error>
</errors>
Additionally, you can only specify hostnames for the test
receiver type. Production receivers have their hostnames explicitly provided by Spreedly to ensure that the delivery endpoints are known and PCI compliant. If you attempt to specify your own hostname for a production receiver, you will receive an error:
$ curl https://core.spreedly.com/v1/receivers.json \
-u 'BznvQ5afPZiRCXpjjtGPNMyBDNP:rg6SILuBIEkL2JBC6eabB14SUpIYLpUVSGvAarWfsbkLubANfERceJOK6DRaYl4O' \
-H 'Content-Type: application/json' \
-d '{
"receiver": {
"receiver_type": "sabre",
"hostnames": "https://maninthemiddle.com"
}
}'
{
"errors": [
{
"key": "errors.hostnames_not_allowed",
"message": "You can't assign a custom hostname to a production receiver. Please don't specify a 'hostnames' property when adding a production receiver."
}
]
}
$ curl https://core.spreedly.com/v1/receivers.xml \
-u 'BznvQ5afPZiRCXpjjtGPNMyBDNP:rg6SILuBIEkL2JBC6eabB14SUpIYLpUVSGvAarWfsbkLubANfERceJOK6DRaYl4O' \
-H 'Content-Type: application/xml' \
-d '<receiver>
<receiver_type>sabre</receiver_type>
<hostnames>https://maninthemiddle.com</hostnames>
</receiver>'
<errors>
<error key="errors.hostnames_not_allowed">You can't assign a custom hostname to a production receiver. Please don't specify a 'hostnames' property when adding a production receiver.</error>
</errors>
Next
This guide explains the steps required to set up your own single-card payment method distribution integration but leaves out many details since every integration has unique requirements. To flesh out your receiver integration, the following resources may be useful:
- Deliver API reference
- The receiver variable reference shows a list of all variables available for a receiver request.
- The receiver function reference shows a list of all the functions that can be used to dynamically format a receiver request.
- The transaction transcript guide shows the raw request that was sent to the receiver, which is useful when debugging template formatting.
Updated 3 months ago