Tokenize Customer Card
Card Tokenization — Tokenize Customer Card
7 min readUpdated Mar 27, 2026
POST /api/v1/payments/card/tokenize
Securely vaults a customer's card and returns a reusable token for future charges. The token can be used with Charge Tokenized Card or to set up a recurring subscription.
Guide: Tokenizing a Card — conceptual walkthrough, flow diagrams, and integration patterns.
#Headers
| Header | Value |
|---|---|
Content-Type | application/json |
Authorization | Bearer {token} — see Authentication |
#Request Body Parameters
| Field | Type | Required | Description |
|---|---|---|---|
requestId | String | Yes | Unique identifier for the request. Used for idempotency — if you retry with the same requestId, the system will return the original response instead of processing a duplicate. |
merchantId | Integer | Yes | Merchant account ID associated with the transaction. |
card | Object — See Card | Yes | |
billingDetails | Object — See BillingDetails | No | |
socialSecurityNumber | String | No | |
metadata | Map<String, String> | No | Arbitrary key-value pairs for your own use (e.g. order reference, campaign ID). Returned unchanged in responses and callbacks. |
expirationDate | String | No |
| Field | Type | Required | Description |
|---|---|---|---|
number | String | Yes | Full card number (PAN). Must be a numeric string with no spaces or dashes. Handled securely and never stored in plaintext. |
cardHolderName | String | No | Cardholder's name as printed on the card. |
expMonth | String | Yes | Card expiration month in MM format (e.g. "08" for August). |
expYear | String | Yes | Card expiration year in YYYY format (e.g. "2027"). |
cvv | String | Yes | Card verification value (CVV/CVC) — the 3- or 4-digit security code on the card. |
requestThreeDSecure | Boolean | Yes | Set to true to request 3D Secure authentication. Even if false, some card issuers may still require 3DS. |
| Field | Type | Required | Description |
|---|---|---|---|
externalUserId | String | No | Your internal customer identifier. Useful for linking transactions to user accounts in your system. |
firstName | String | No | Customer's first name. Required for 3DS2 frictionless flow. |
lastName | String | No | Customer's last name. Required for 3DS2 frictionless flow. |
address1 | String | No | Billing street address (line 1). Required for 3DS2 frictionless flow. |
city | String | No | Billing city. Required for 3DS2 frictionless flow. |
state | String | No | Billing state or province. |
country | String | No | Billing country as an ISO 3166-1 alpha-2 code (e.g. US, GB, DE). |
postalCode | String | No | Billing ZIP or postal code. |
phone | String | No | Customer's phone number (including country code). Required for 3DS2 frictionless flow. |
email | String | Yes | Customer's email address. |
dateOfBirth | String | No | Customer's date of birth in YYYY-MM-DD format. Required for 3DS2 frictionless flow. |
#Response
| Field | Type | Description |
|---|---|---|
token | String | Saved card token for tokenized payments. Obtained from the tokenize endpoint. |
cardMask | String | Masked card number showing only the first 6 and last 4 digits (e.g. 411111****1111). |
expirationMonth | String | |
expirationYear | String | |
cardBrand | String | |
cardType | String | Card brand (e.g. VISA, MASTERCARD, AMEX). |
issuingBank | String | |
cardCountry | String | Country of the card issuer as an ISO 3166-1 alpha-2 code. |
expirationDate | String | |
metadata | Map<String, String> | Arbitrary key-value pairs for your own use (e.g. order reference, campaign ID). Returned unchanged in responses and callbacks. |
{
"requestId": "req_abc123",
"merchantId": 12345,
"card": {
"number": "4111111111111111",
"cardHolderName": "John Doe",
"expMonth": "12",
"expYear": "2027",
"cvv": "123",
"requestThreeDSecure": true
},
"billingDetails": {
"externalUserId": "example_externalUserId",
"firstName": "John",
"lastName": "Doe",
"address1": "123 Main St",
"city": "New York",
"state": "NY",
"country": "US",
"postalCode": "10001",
"phone": "+12125551234",
"email": "test@example.com",
"dateOfBirth": "2025-07-17"
},
"socialSecurityNumber": "https://yourserver.com/callback",
"metadata": {
"key1": "value1"
},
"expirationDate": "2025-07-17"
}{
"token": "example_token",
"cardMask": "example_cardMask",
"expirationMonth": "example_expirationMonth",
"expirationYear": "example_expirationYear",
"cardBrand": "example_cardBrand",
"cardType": "example_cardType",
"issuingBank": "example_issuingBank",
"cardCountry": "US",
"expirationDate": "2025-07-17",
"metadata": {
"key1": "value1"
}
}Idempotency: The
requestIdfield ensures idempotent processing. If you retry a request with the samerequestId, the original response is returned without reprocessing.
#Error Responses
| HTTP Status | Description |
|---|---|
400 | Bad Request — missing or invalid parameters. Check the response body for field-level details. |
401 | Unauthorized — missing, expired, or invalid bearer token. Re-authenticate via POST /api/v1/auth. |
404 | Not Found — the requested resource does not exist. |
500 | Internal Server Error — an unexpected error occurred. Retry with exponential backoff. |
curl -X POST https://sandbox.api.exirom.com/api/v1/payments/card/tokenize \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_TOKEN" \
-d '{
"requestId": "req_abc123",
"merchantId": 12345,
"card": {
"number": "4111111111111111",
"cardHolderName": "John Doe",
"expMonth": "12",
"expYear": "2027",
"cvv": "123",
"requestThreeDSecure": true
},
"billingDetails": {
"externalUserId": "example_externalUserId",
"firstName": "John",
"lastName": "Doe",
"address1": "123 Main St",
"city": "New York",
"state": "NY",
"country": "US",
"postalCode": "10001",
"phone": "+12125551234",
"email": "test@example.com",
"dateOfBirth": "2025-07-17"
},
"socialSecurityNumber": "https://yourserver.com/callback",
"metadata": {
"key1": "value1"
},
"expirationDate": "2025-07-17"
}'#Try It
SandboxTry it
https://sandbox.api.exirom.com/api
Was this helpful?