Overview
Partners with PCI DSS compliance can retrieve sensitive card data (PAN, CVV, expiry) via a direct API call. The response is RSA-encrypted with your public key — Contro never exposes card data in plaintext.
Prerequisites
Your organization must be PCI DSS compliant
An RSA-4096 (or larger) key pair
Your public key uploaded via the partner dashboard https://partner.contro.me/settings
Step 1: Generate an RSA key pair
# Generate 4096-bit RSA private key
openssl genrsa -out private_key.pem 4096
# Extract the public key
openssl rsa -in private_key.pem -pubout -out public_key.pem
Keep your private key secure. Contro only stores your public key and never has access to your private key.
Step 2: Upload your public key
Upload your PEM-encoded public key via the dashboard Settings page, or programmatically:
curl -X PUT https://api.contro.me/v1/dashboard/partner/settings/rsa-key \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"rsaPublicKey": "-----BEGIN PUBLIC KEY-----\nMIICIjAN...\n-----END PUBLIC KEY-----"
}'
Step 3: Call the reveal endpoint
curl https://api.contro.me/v1/partner/cards/{card_id}/reveal \
-H "Authorization: Bearer sk_live_YOUR_KEY"
Response:
{
"data" : "base64-encoded-RSA-encrypted-payload..."
}
Step 4: Decrypt the response
The data field is a Base64-encoded RSA-OAEP-SHA256 ciphertext. Decrypt with your private key:
import { privateDecrypt , constants } from "node:crypto" ;
import { readFileSync } from "node:fs" ;
const privateKey = readFileSync ( "private_key.pem" , "utf-8" );
const encrypted = Buffer . from ( response . data , "base64" );
const decrypted = privateDecrypt (
{
key: privateKey ,
padding: constants . RSA_PKCS1_OAEP_PADDING ,
oaepHash: "sha256" ,
},
encrypted ,
);
const cardData = JSON . parse ( decrypted . toString ( "utf-8" ));
// { data: { cardNumber: "4111...", cvv: "123", expiryDate: "12/2030" } }
# Using OpenSSL CLI
echo "BASE64_DATA" | base64 -d | openssl pkeyutl -decrypt \
-inkey private_key.pem -pkeyopt rsa_padding_mode:oaep -pkeyopt rsa_oaep_md:sha256
Sandbox testing
In sandbox mode (sk_test_ keys), the endpoint returns encrypted test data :
Field Value cardNumber 4000000000000000cvv 123expiryDate 12/2030
If you haven’t uploaded an RSA key, sandbox mode uses a built-in sandbox key pair automatically. You can use the corresponding sandbox private key to verify your decryption logic.
In live mode, you must have an RSA public key configured. The endpoint returns a 400 error if no key is set.
Security considerations
Card data is encrypted end-to-end — Contro’s API response is encrypted with your key before leaving the server
Key rotation : Replacing your public key takes effect immediately. Coordinate rotation to avoid decryption failures during the swap window