Retrieve Assets From Card Details
This guide outlines how to securely integrate with Spinwheel’s Credit Card Brand Asset endpoint to retrieve the card program name and artwork by providing credit card metadata.
Overview
Encryption Required
Due to the nature of the payload, the value provided as creditCardNumberEncrypted must be encrypted with our public key before making requests to the credit card brand API. This ensures end-to-end encryption, with only Spinwheel able to decrypt the value using our private key.
The full API reference can be found here: Retrieve Credit Card Brand.
Encryption Steps
1. Retrieve Spinwheel's public key
The sandbox key can be found here: sandbox-public-v1.pem
2. Encrypt the credit card number
Use RSA with OAEP padding (RSA-OAEP with SHA-256) to encrypt the raw card number string.
Code Examples
const fs = require('fs');
const crypto = require('crypto');
// Load Spinwheel's public key
const publicKey = fs.readFileSync('./spinwheel_public.pem', 'utf8');
const cardNumber = '4111111111111111';
// Encrypt using the crypto module from node
const encryptedBuffer = crypto.publicEncrypt(
{
key: publicKey,
padding: crypto.constants.RSA_PKCS1_OAEP_PADDING,
oaepHash: 'sha256',
},
Buffer.from(cardNumber, 'utf8')
);
// Encode to base64 for sending in JSON
const encryptedBase64 = encryptedBuffer.toString('base64');
// Use this as the cardNumber in your API request
console.log(encryptedBase64);
from cryptography.hazmat.primitives import serialization, hashes
from cryptography.hazmat.primitives.asymmetric import padding
import base64
# Load Spinwheel's public key
with open('./spinwheel_public.pem', 'rb') as f:
public_key = serialization.load_pem_public_key(f.read())
card_number = '4111111111111111'
# Encrypt using RSA OAEP with SHA-256
encrypted = public_key.encrypt(
card_number.encode('utf-8'),
padding.OAEP(
mgf=padding.MGF1(algorithm=hashes.SHA256()),
algorithm=hashes.SHA256(),
label=None
)
)
# Encode to base64 for sending in JSON
encrypted_base64 = base64.b64encode(encrypted).decode('utf-8')
# Use this as the cardNumber in your API request
print(encrypted_base64)
require 'openssl'
require 'base64'
# Load Spinwheel's public key
public_key = OpenSSL::PKey::RSA.new(File.read('./spinwheel_public.pem'))
card_number = '4111111111111111'
# Encrypt using RSA with OAEP and SHA-256
encrypted = public_key.public_encrypt(
card_number,
OpenSSL::PKey::RSA::PKCS1_OAEP_PADDING
)
# Encode to base64 for sending in JSON
encrypted_base64 = Base64.strict_encode64(encrypted)
# Use this as the cardNumber in your API request
puts encrypted_base64
This encryptedBase64
string should be passed as the value of the creditCardNumberEncrypted
field in your API request.
3. Send the encrypted payload
Example curl
request:
curl --request POST \
--url https://secure-sandbox-api.spinwheel.io/v1/creditCards/brands \
--header 'accept: application/json' \
--header 'content-type: application/json' \
--header 'authorization: Bearer <Your access token>' \
--data '
{
"extUserId": "user-123456",
"creditCards": [
{
"extCreditCardId": "147500249-1098-1221-2168-6122859797551",
"creditCardNumberEncrypted": "<Encrypted card number>",
"accountOriginationDate": "2024-03-12",
"liabilitySubtype": "FlexibleSpendingCreditCard",
"creditor": {
"originalName": "JPMCB CARD SERVICES",
"address": {
"addressLine1": "123 Main Street",
"city": "New York",
"state": "NY",
"zip": "10001"
}
}
}
]
}
'
Replace <BASE64_ENCRYPTED_CARD_NUMBER>
with the actual base64-encoded encrypted string.
Complete Encryption Example
You can use the following test card number and retrieve the sandbox key below, to verify your encryption logic:
- Test card number:
4147202097111111
- The sandbox key can be found here: sandbox-public-v1.pem
Expected encrypted output:
WTFCOX/Nfibo7kpEITwIuKjEIMR7kLo/6iiOdpnJHdU8SeH2IvSG/cCcIuLcXuH89F6XWwCzyoqX55vABN4Jdi1c+o+0Q8+JxSPakVVyr7FwohffBMD2UbH7vYCxQrNZr/S2eAH0KxeEj7+go1qA94ons7GKpDjnMtIR9vJ0AEcOKRaUYWdWFdJxtpZ9MfplIiPrDFJqJyb52N80Oy34l3J9z9Mr6MrpWqQ5gbONcHYY+xIoOMYj8HKUJCtlpBUEzJR2awc6JmKAPeeKRaETt4QTSa4RrXDlqmJG/ZruRRruY8YWF2UMYZKw0J7d0zP8SX4n0jz8UEwT6G66Gf85lw==
Verifying output
Because RSA-OAEP encryption uses random padding, encrypting the same card number multiple times with the same key will produce different encrypted outputs. This is expected and improves security by preventing ciphertext pattern attacks.
Request to Spinwheel:
curl --request POST \
--url https://secure-sandbox-api.spinwheel.io/v1/creditCards/brands \
--header 'accept: application/json' \
--header 'content-type: application/json' \
--header 'authorization: Bearer <Your access token>' \
--data '
{
"extUserId": "user-123456",
"creditCards": [
{
"extCreditCardId": "147500249-1098-1221-2168-6122859797551",
"creditCardNumberEncrypted": "WTFCOX/Nfibo7kpEITwIuKjEIMR7kLo/6iiOdpnJHdU8SeH2IvSG/cCcIuLcXuH89F6XWwCzyoqX55vABN4Jdi1c+o+0Q8+JxSPakVVyr7FwohffBMD2UbH7vYCxQrNZr/S2eAH0KxeEj7+go1qA94ons7GKpDjnMtIR9vJ0AEcOKRaUYWdWFdJxtpZ9MfplIiPrDFJqJyb52N80Oy34l3J9z9Mr6MrpWqQ5gbONcHYY+xIoOMYj8HKUJCtlpBUEzJR2awc6JmKAPeeKRaETt4QTSa4RrXDlqmJG/ZruRRruY8YWF2UMYZKw0J7d0zP8SX4n0jz8UEwT6G66Gf85lw==",
"accountOriginationDate": "2024-03-12",
"liabilitySubtype": "FlexibleSpendingCreditCard",
"creditor": {
"originalName": "JPMCB CARD SERVICES",
"address": {
"addressLine1": "123 Main Street",
"city": "New York",
"state": "NY",
"zip": "10001"
}
}
}
]
}
'
Key Rotation
Spinwheel may periodically rotate its public key. When this happens:
- We will notify you in advance
- You'll be able to download the new public key from the same location
- A grace period may be supported during which both keys are accepted
Integrating with our Sandbox Environment
We have set up a handful of test cards that you can use as you build out your integration. The relevant details are as follows:
- Base URL: https://secure-sandbox-api.spinwheel.io/
- Sandbox public key for encrypting credit card numbers: Download link
Test card number | Expected result |
---|---|
4147202097111111 | Chase Sapphire Preferred |
5156769324111111 | Capital One Savor MasterCard |
4433905000111111 | Summit Credit Union Platinum Credit Card |
5466801038111111 | MyLowe's Rewards Credit Card |
4111111111111111 | CREDIT_CARD_NOT_SUPPORTED |
9111111111111111 | INVALID_CARD_NUMBER |
5111111111111111 | UNKNOWN_ERROR |
Updated 2 days ago