Card Vaulting
Tokenize cards with Collect.js, store them in EPD Gateway, and attach them to EPD Commerce customers.
What this is and who needs it
To bill a customer more than once — or to charge them later without making them re-enter their card — you have to store the card somewhere safely. Storing card data yourself means PCI compliance, audits, and risk you do not want.
EPD handles this for you: card details are tokenized client-side by EPD Gateway’s Collect.js, stored in the EPD Gateway vault, and EPD Commerce keeps a tokenized mirror that points back to the stored card. Your servers never see raw card data.
If you charge customers more than once — subscriptions, top-ups, win-backs, saved-card checkout — you need to understand this flow.
Card vaulting is currently handled through EPD Gateway. A native EPD Commerce vaulting API is on the roadmap.
The two systems
Where the actual card data lives. PCI-compliant vault. Tokenizes cards via Collect.js and exposes a server-side API at https://secure.easypaydirectgateway.com/api/transact.php.
The API documented here. Stores a mirror of the card — last 4 digits, brand, expiry — keyed by the billing_id from EPD Gateway. Returns a UUID id for the payment method.
EPD Commerce does not accept raw PAN, CVV, or expiry data over its API. There is no POST /v1/cards endpoint that takes a card number. Card data must reach EPD through the Gateway.
Prerequisites
- An EPD Gateway account with API credentials (security key).
- A Collect.js tokenization key from your EPD Gateway merchant portal.
- An EPD Commerce API key (
epd_live_sk_...orepd_test_sk_...).
The full flow
Client-side
The customer enters card information into Collect.js hosted fields on your checkout page. Your servers and pages never see the raw PAN.
Client-side → EPD Gateway
Collect.js sends the card data directly to EPD Gateway and returns a payment_token.
The payment_token expires after approximately 15 minutes. Complete the next steps promptly after tokenization.
Server-side → EPD Gateway
Your backend creates an EPD Gateway customer vault using the token. EPD Gateway returns a customer_vault_id — this identifies the customer’s vault, not a specific card.
curl -X POST https://secure.easypaydirectgateway.com/api/transact.php \
-d "security_key=$EPD_GATEWAY_KEY" \
-d "customer_vault=add_customer" \
-d "payment_token=$PAYMENT_TOKEN"
Server-side → EPD Gateway
Your backend adds the tokenized card to the vault. EPD Gateway returns a billing_id — this identifies the specific card inside the vault.
curl -X POST https://secure.easypaydirectgateway.com/api/transact.php \
-d "security_key=$EPD_GATEWAY_KEY" \
-d "customer_vault=add_billing" \
-d "customer_vault_id=$CUSTOMER_VAULT_ID" \
-d "payment_token=$PAYMENT_TOKEN"
Server-side → EPD Commerce
You have two ways to make the vaulted card usable in EPD Commerce — pick whichever fits your flow:
Pass epd_gateway_customer_vault_id on POST /v1/customers. EPD Commerce reads the card from the vault and creates the customer and their default payment method in one request.
curl https://api.epd.com/v1/customers \
-H "Authorization: Bearer $EPD_KEY" \
-H "epd-version: 2026-02-11" \
-H "X-EPD-Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{
"email": "jane@example.com",
"first_name": "Jane",
"last_name": "Doe",
"phone": "+14155551234",
"epd_gateway_customer_vault_id": "12345678"
}'
Call POST /v1/customers/:id/payment_methods with the billing_id. EPD Commerce reads the card metadata from the gateway vault, stores a mirror, and returns a UUID id for the payment method.
curl https://api.epd.com/v1/customers/$CUSTOMER_ID/payment_methods \
-H "Authorization: Bearer $EPD_KEY" \
-H "epd-version: 2026-02-11" \
-H "X-EPD-Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{
"billing_id": "987654",
"set_as_default": true
}'
Pass payment_method_id: "<uuid>" on POST /v1/orders or POST /v1/subscriptions. The card never has to be entered again.
Key identifiers
Four different identifiers move through this flow. They are easy to confuse — keep this table close.
| Identifier | Source | Lifetime | What it identifies |
|---|---|---|---|
payment_token | Collect.js | ~15 minutes | One-time token representing raw card data |
customer_vault_id | EPD Gateway | Permanent | The customer’s vault in EPD Gateway |
billing_id | EPD Gateway | Permanent | A specific card inside that vault |
payment_method_id | EPD Commerce | Permanent | The mirrored payment method on an EPD Commerce customer |
customer_vault_id and billing_id are not the same thing. The vault holds zero or more cards; each card has its own billing_id.
Sandbox shortcut
In sandbox you can skip the entire Collect.js → EPD Gateway flow. Pass a test card token like card_visa directly as either:
epd_gateway_customer_vault_idonPOST /v1/customers, orbilling_idonPOST /v1/customers/:id/payment_methods.
Sandbox mode is keyed off your API key — same base URL, no separate environment. See the Testing Guide for the full token list.
Why this matters
| Without a vault | With EPD Gateway vault |
|---|---|
| Card data flows through your servers | Card data never reaches your servers |
| Full PCI DSS audit (SAQ D) | Reduced PCI scope (SAQ A or A-EP) |
| You store sensitive card data | Gateway stores it; you store a token only |
| Re-entry required for each charge | Charge stored cards on demand |
Security
Never log, store, or transmit raw card numbers. Always use Collect.js for client-side tokenization.
- Keep EPD Gateway API keys server-side only — never expose them to the browser.
- Use HTTPS for all API calls to both EPD Gateway and EPD Commerce.
- Rotate EPD Gateway API keys periodically through the EPD Gateway merchant portal.