Auto-Populate Card Details From a Photo

Let customers photograph their physical card to extract and tokenize the card details, then complete checkout with the returned token.

Overview

Instead of asking a customer to manually type in their card number, expiration date, and CVV, you can let them take a photo of their physical card. Coinflow extracts the card details from the image, stores them as a token in Coinflow’s PCI-compliant vault, and returns the token so you can complete the purchase.

The flow is two steps:

  1. Extract the card — send the photo to POST /tokenize/extract-card. The endpoint responds with a 307 redirect to Coinflow’s PCI-compliant vault proxy, so the card photo is processed there and never touches Coinflow’s servers. Following the redirect returns a token along with non-sensitive metadata (firstSix, lastFour, expirationMonth, expirationYear, and whether a CVV was captured).
  2. Charge the card — pass the returned token as card.cardToken to POST /checkout/card/{merchantId} (Card Checkout) to complete the purchase.

Access to POST /tokenize/extract-card requires that your company holds a PCI-DSS certification. Provide your certification to your Coinflow Integrations Representative to have the endpoint enabled for your account.

Step 1: Extract the card from the image

Send a base64-encoded photo of the card in the image field. Optionally set mimeType (defaults to image/jpeg). Authenticate with a merchant API key that has the ADMIN scope.

POST
/api/tokenize/extract-card
curl -X POST https://api-sandbox.coinflow.cash/api/tokenize/extract-card \
-H "Authorization: <apiKey>" \
-H "Content-Type: application/json" \
-d '{}'

The endpoint responds with a 307 Temporary Redirect. Your HTTP client must follow the redirect and re-send the request body to the redirect location (fetch does this automatically; for curl use --location-trusted).

The response contains the token you will use for checkout, plus metadata you can use to pre-fill and confirm the card in your UI. cvvCaptured tells you whether the CVV was readable from the photo — if it is false, prompt the customer to enter their CVV manually before charging.

Response
{
"token": "string",
"firstSix": "string",
"lastFour": "string",
"expirationMonth": "string",
"expirationYear": "string",
"cvvCaptured": true
}

Step 2: Charge the card with the returned token

Use the token from Step 1 as the card.cardToken field of the Card Checkout request. This is the same endpoint used for any new-card (tokenized) purchase.

POST
/api/checkout/card/:merchantId
curl -X POST https://api-sandbox.coinflow.cash/api/checkout/card/merchantId \
-H "x-coinflow-auth-session-key: <apiKey>" \
-H "Content-Type: application/json" \
-d '{
"subtotal": {
"cents": 1,
"currency": "USD"
},
"card": {
"cardToken": "string",
"expYear": "string",
"expMonth": "string",
"email": "string",
"firstName": "string",
"lastName": "string",
"address1": "string",
"city": "string",
"country": "string"
}
}'
Response
{
"paymentId": "string",
"authorizationExpiration": "string"
}

Putting it together

// 1. Extract the card from the photo
const extractResponse = await fetch(
'https://api.coinflow.cash/api/tokenize/extract-card',
{
method: 'POST',
headers: {
Authorization: MERCHANT_API_KEY,
'Content-Type': 'application/json',
},
body: JSON.stringify({
image: base64CardPhoto,
mimeType: 'image/png',
}),
}
);
const {token, expirationMonth, expirationYear, cvvCaptured} =
await extractResponse.json();
// 2. Charge the card using the returned token
const checkoutResponse = await fetch(
`https://api.coinflow.cash/api/checkout/card/${merchantId}`,
{
method: 'POST',
headers: {
Authorization: SESSION_KEY,
'Content-Type': 'application/json',
},
body: JSON.stringify({
card: {
cardToken: token,
expMonth: expirationMonth,
expYear: expirationYear,
// ...customer name and billing address fields
},
subtotal: {cents: 1000},
// ...remaining checkout fields
}),
}
);

If cvvCaptured is false, collect the CVV from the customer and associate it with the token before charging so the transaction can be authorized with a CVV.