Oney private cards (Web SDK)
Oney private cards (OneyCard) are 19-digit cards on the ONEY network. They have no security code: Oney asks for the cardholder's date of birth instead of a CVV. The SecureFields Web SDK handles this inside the secure iframes, but the label you render next to the CVV field is yours to update.
This guide explains how to accept Oney private cards in a form built with initSecureFields, how to relabel the CVV field dynamically, and how to pass the date of birth when you create the payment.
Enable the ONEY brand
Add 'ONEY' to the brands array of your configuration. The BIN lookup only reports brands that appear in this list — without it, an Oney card is never detected and submit() fails because the brand is not allowed.
const secureForm = await sf.initSecureFields({
tenantId: '${VAULT_TENANT_ID}',
config: {
brands: ['CARTE_BANCAIRE', 'VISA', 'MASTERCARD', 'ONEY'],
brandSelector: true,
fields: {
cardNumber: { target: 'pan-placeholder', placeholder: '1234 5678 9012 3456', ariaLabel: 'Card number', iframeTitle: 'Card number' },
expDate: { target: 'exp-placeholder', placeholder: 'MM/YY', ariaLabel: 'Expiry date', iframeTitle: 'Expiry date' },
cvv: { target: 'cvv-placeholder', placeholder: '123', ariaLabel: 'Security code', iframeTitle: 'Security code' },
},
},
});
Oney private cards are never co-branded, so ONEY is always the only brand reported for them. Its position in the brands array has no effect.
What the SDK does for you
Once an Oney BIN is recognised, the SDK adapts the fields inside the iframes. No configuration is needed for this part.
| Field | Standard card | Oney private card |
|---|---|---|
cardNumber | Formatted by the brand (e.g. 4-4-4-4) | Formatted 4-4-4-4-3 (19 digits) |
cvv | Numeric input, 3 or 4 digits | Native date input (browser date picker), must be a date in the past |
submit() result | vault_form_token (+ optional card) | vault_form_token and birth_date (YYYY-MM-DD) |
The input type can change while the customer types — for example, a 3-digit CVV is already filled when the card number finally identifies an Oney BIN. The SDK then resets the field value and its validation state so the customer starts fresh with the date picker. The reverse switch behaves the same way.
Update the CVV label dynamically
The SDK cannot change the <label> you render on your page. Subscribe to the brandDetected event and swap your label and help text whenever the first detected brand is ONEY.
brandDetected fires each time the list of detected brands changes, including with an empty list when the card number is cleared or no longer matches a configured brand — so the same handler restores the CVV wording.
<label id="cvv-label" for="cvv-placeholder">Security code</label>
<div id="cvv-placeholder" aria-labelledby="cvv-label"></div>
<p id="cvv-help">The 3 digits on the back of your card</p>
const cvvTexts = {
cvv: {
label: 'Security code',
help: 'The 3 digits on the back of your card',
},
birthdate: {
label: 'Date of birth',
help: 'Oney private cards use your date of birth instead of a security code',
},
};
secureForm.on('brandDetected', ({ brands }) => {
const variant = brands?.[0] === 'ONEY' ? 'birthdate' : 'cvv';
document.getElementById('cvv-label').textContent = cvvTexts[variant].label;
document.getElementById('cvv-help').textContent = cvvTexts[variant].help;
});
The ariaLabel and iframeTitle you pass in fields.cvv are fixed at initialisation and are read by screen readers instead of your page-side <label>, which cannot reach an input inside a cross-origin iframe. If you accept Oney private cards, choose wording that stays true for both cases — for example Security code or date of birth — or keep the default and rely on the visible label.
The placeholder configured for the cvv field is ignored while the field is a date input: browsers render their own date format there.
Handle the submit result
For an Oney private card, both submit() and the success event return the birth_date alongside the vault_form_token. Forward both to your backend.
const result = await secureForm.submit();
await fetch('/your-server/pay', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
vaultFormToken: result.vault_form_token,
birthDate: result.birth_date, // present for Oney private cards only
}),
});
birth_date is an ISO 8601 date (YYYY-MM-DD). It is absent from the result for every other brand — use 'birth_date' in result to narrow the type. See SubmitResultTokenWithBirthDate.
Create the payment
Pass the date of birth in split[].card.card_holder_birth_date when your server calls the Payment API. The value is transmitted to Oney during the validation step; it is not stored by Purse and is not returned in the response.
curl -X POST 'https://api.purse-sandbox.com/payment/v2/payments' \
--header 'Content-Type: application/json' \
--header "x-api-key: ${API_KEY}" \
--header "Authorization: Bearer ${ACCESS_TOKEN}" \
--data-raw '{
"entity_id": "${ENTITY_ID}",
"amount": 4999,
"currency": "EUR",
"order": {
"reference": "order-456",
"net_amount": 4999,
"tax_amount": 833
},
"split": [
{
"vault_form_token": "${VAULT_FORM_TOKEN}",
"card": {
"card_holder_birth_date": "${BIRTH_DATE}"
},
"three_ds_authentication_options": {
"challenge_indicator": "NO_CHALLENGE_REQUESTED"
}
}
]
}'
- Endpoint:
/payment/v2/payments - Method:
POST - API Reference
The rest of the request is identical to a standard card payment — see Create a payment.
Saved Oney cards (CVV-only form)
When a customer pays with a saved Oney private card, the CVV-only form collects the date of birth instead of a security code. Initialise it with brands: ['ONEY'] and label the field accordingly from the start — there is no card number field, so brandDetected never fires.
const isOney = tokenBrand === 'ONEY';
document.getElementById('cvv-only-label').textContent = isOney ? 'Date of birth' : 'CVV';
const secureForm = await sf.initSecureFields({
tenantId: '${VAULT_TENANT_ID}',
config: {
brands: [tokenBrand],
fields: {
cvv: {
target: 'cvv-only-placeholder',
placeholder: isOney ? 'YYYY-MM-DD' : '123',
ariaLabel: isOney ? 'Date of birth' : 'CVV',
iframeTitle: isOney ? 'Date of birth' : 'CVV',
},
},
},
});
In this case the submit() result contains only birth_date — no vault_form_token is issued, because there is no card data to tokenize. Send birth_date to your server and pass it as split[].card.card_holder_birth_date together with the wallet_token, without a vault_form_token.
Next steps
- Events —
brandDetectedandsuccesspayloads - Token payment — save cards and pay with saved tokens
- Oney — partner overview and payment methods