Single Card Payment Method Distribution

If you need to send a single payment method to an HTTP endpoint, use the single card form of PMD. If you are looking to export more than one card at a time to an SFTP endpoint, please see batch export instead.

Provisioning a test receiver

Spreedly provides a test receiver that has all the functionality of a production receiver with the exception that it can only distribute test payment methods. Begin your integration by creating a test receiver pointing to the endpoint host you wish to distribute to (the http:// and domain name, but not the path).

We want to deliver payment methods to the URL http://posttestserver.com/post.php here (a simple echo-endpoint) so the hostname is just http://posttestserver.com.

$ curl https://core.spreedly.com/v1/receivers.json \
  -u 'C7cRfNJGODKh4Iu5Ox3PToKjniY:4UIuWybmdythfNGPqAqyQnYha6s451ri0fYAo4p3drZUi7q2Jf4b7HKg8etDtoKJ' \
  -H 'Content-Type: application/json' \
  -d '{
        "receiver": {
          "receiver_type": "test",
          "hostnames": "http://posttestserver.com",
          "credentials": [
            {
              "name": "app-id",
              "value": 1234,
              "safe": true
            },
            {
              "name": "app-secret",
              "value": 5678
            }
          ]
        }
      }'

$ curl https://core.spreedly.com/v1/receivers.xml \
  -u 'C7cRfNJGODKh4Iu5Ox3PToKjniY:4UIuWybmdythfNGPqAqyQnYha6s451ri0fYAo4p3drZUi7q2Jf4b7HKg8etDtoKJ' \
  -H 'Content-Type: application/xml' \
  -d '<receiver>
        <receiver_type>test</receiver_type>
        <hostnames>http://posttestserver.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": "RxyJ6QBFFcSvXMINtZvPZEez3Mi",
    "hostnames": "http://posttestserver.com",
    "state": "retained",
    "created_at": "2017-07-27T17:55:23Z",
    "updated_at": "2017-07-27T17:55:23Z",
    "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>aIMoZQDdT2Dw3L5rrjBPZ61eHF3</token>
  <hostnames>http://posttestserver.com</hostnames>
  <state>retained</state>
  <created_at type="dateTime">2017-07-27T17:55:23Z</created_at>
  <updated_at type="dateTime">2017-07-27T17:55:23Z</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>

Credentials

If your test endpoint requires authentication, you can specify credentials on creation (which will then be available as a variable when making the actual delivery request - see below). Credentials are supplied as one or more name/value pairs. The safe property indicates values that are not sensitive (public keys, usernames etc…). 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 but to the receiver on delivery.

Credentials should be used sparingly. Only if you have values you don’t want echoed in transcripts and other artifacts should you specify credentials. Otherwise, it’s best to store dynamic values yourself and insert them into the template you send to Spreedly. It’s simpler that way, and clearly delineates Spreedly’s responsibility of managing sensitive data from yours of formatting the request and providing the rest of the template.

Deliver payment method

Once you’ve specified where to deliver card data (the receiver), you have to specify what to deliver. The best way to think about payment method distribution is that you define the raw HTTP request that will get sent to the receiver and all Spreedly does is populate the request with the sensitive data from your credit card vault before executing the request. Once you have a receiver provisioned, you need to tell Spreedly how to build the HTTP request including the sensitive card data. This is done using a simple templating language and the deliver API endpoint.

There are four basic properties that define the distribution of a payment method: The token representing the payment method to be distributed, the URL to distribute to, and the HTTP request headers and body. The exact content of these elements will be determined by the third party receiver to which the payment method will be delivered; they 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’ll be using in production for information about their expected format and fields.

A simple PMD deliver request might look like the following:

curl https://core.spreedly.com/v1/receivers/IqHtfN2wEKLPHP9iFqIzX6as9yS/deliver.json \
  -u 'C7cRfNJGODKh4Iu5Ox3PToKjniY:4UIuWybmdythfNGPqAqyQnYha6s451ri0fYAo4p3drZUi7q2Jf4b7HKg8etDtoKJ' \
  -H 'Content-Type: application/json' \
  -d '{
        "delivery": {
          "payment_method_token": "56wyNnSmuA6CWYP7w0MiYCVIbW6",
          "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/IqHtfN2wEKLPHP9iFqIzX6as9yS/deliver.xml \
  -u 'C7cRfNJGODKh4Iu5Ox3PToKjniY:4UIuWybmdythfNGPqAqyQnYha6s451ri0fYAo4p3drZUi7q2Jf4b7HKg8etDtoKJ' \
  -H 'Content-Type: application/xml' \
  -d '<delivery>
        <payment_method_token>56wyNnSmuA6CWYP7w0MiYCVIbW6</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 templates using the Mustache syntax that are evaluated at delivery time - allowing you to format the request how the endpoint requires while not 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 following for the delivery body:

{
  "product_id":"916593",
  "card_number":"{{ credit_card_number }}"
}

Note how any value you want Spreedly to insert for you should be specified using the {{ variable_name }} notation. The variable value for the payment method specified by the payment_method_token element will be inserted at that point in the template.

A list of all available variables can be found in the reference documentation here.

Template functions

There are also a set of receiver functions available to dynamically modify values at deliver time. For instance, to send a basic authorization HTTP header, you would use the base64 function:

Authorization: Basic {{#base64}}{{ user }}:{{ password }}{{/base64}}

Which base64 encodes the username and password values (which may habe been set as the credentials during receiver provisioning). Assume a user value of user and password of Pa$$werd, the resulting value sent to the receiver will be:

Authorization: Basic dXNlcjpQYSQkd2VyZA==

Receiver functions all wrap some content, which is then operated on, and requires leading and trailing tags in the syntax {{#function}} and {{/function}}, respectively.

A list of all receiver functions can be found here in the reference docs.

Provisioning 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 white-listed by Spreedly before being used. You will need to contact Spreedly directly to get your receiver endpoint white-listed and a new receiver_type provisioned.

Once your receiver has been whitelisted, you can provision it using the receiver type given to you by Spreedly (or use one of our pre-existing ones below). You’ll notice production receivers don’t accept hostnames since those values are hard-coded into the receiver:

$ curl https://core.spreedly.com/v1/receivers.json \
  -u 'C7cRfNJGODKh4Iu5Ox3PToKjniY:4UIuWybmdythfNGPqAqyQnYha6s451ri0fYAo4p3drZUi7q2Jf4b7HKg8etDtoKJ' \
  -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 'C7cRfNJGODKh4Iu5Ox3PToKjniY:4UIuWybmdythfNGPqAqyQnYha6s451ri0fYAo4p3drZUi7q2Jf4b7HKg8etDtoKJ' \
  -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 PMD integration with a test receiver, flipping to production should be as easy as replacing the receiver token in your existing deliver call with the new production receiver token. You should also confirm that the url, headers and body are correctly formatted to work with the third party API endpoint.

You can see a list of currently supported receiver types and the API endpoints they are whitelisted to access.

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 call you will need to recache it first before invoking the deliver receiver call. On successful completion of the receiver call the CVV value will then be wiped from Spreedly, so you will need to recache this data immediately prior to every receiver call.

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 'C7cRfNJGODKh4Iu5Ox3PToKjniY:4UIuWybmdythfNGPqAqyQnYha6s451ri0fYAo4p3drZUi7q2Jf4b7HKg8etDtoKJ' \
  -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 'C7cRfNJGODKh4Iu5Ox3PToKjniY:4UIuWybmdythfNGPqAqyQnYha6s451ri0fYAo4p3drZUi7q2Jf4b7HKg8etDtoKJ' \
  -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 provided by Spreedly to ensure known and PCI compliant delivery targets. 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 'C7cRfNJGODKh4Iu5Ox3PToKjniY:4UIuWybmdythfNGPqAqyQnYha6s451ri0fYAo4p3drZUi7q2Jf4b7HKg8etDtoKJ' \
  -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 'C7cRfNJGODKh4Iu5Ox3PToKjniY:4UIuWybmdythfNGPqAqyQnYha6s451ri0fYAo4p3drZUi7q2Jf4b7HKg8etDtoKJ' \
  -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 shows you the steps required to setup your own single-card PMD integration, but leaves many details out since every integration has unique requirements. To flesh out your receiver integration, the following may be useful: