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

EPD Gateway

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.

EPD Commerce

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_... or epd_test_sk_...).

The full flow

Collect card details

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.

Tokenize

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.

Create the customer vault

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"
Add the card to the vault

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"
Link to EPD Commerce

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
  }'
Charge using the payment-method id

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.

IdentifierSourceLifetimeWhat it identifies
payment_tokenCollect.js~15 minutesOne-time token representing raw card data
customer_vault_idEPD GatewayPermanentThe customer’s vault in EPD Gateway
billing_idEPD GatewayPermanentA specific card inside that vault
payment_method_idEPD CommercePermanentThe 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_id on POST /v1/customers, or
  • billing_id on POST /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 vaultWith EPD Gateway vault
Card data flows through your serversCard data never reaches your servers
Full PCI DSS audit (SAQ D)Reduced PCI scope (SAQ A or A-EP)
You store sensitive card dataGateway stores it; you store a token only
Re-entry required for each chargeCharge 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.

Common questions