What this is and who needs it

When you are building or testing an integration, you do not want to spend real money to see if your code works. EPD’s sandbox lets you simulate every important payment outcome — successful charges, declines, expired cards, chargebacks — using fake card tokens that move no real funds.

If you are building, debugging, QA-ing, or running automated tests, this is the page you need.

How testing works

EPD does not have a separate sandbox URL. Instead:

  1. Sign in to the Merchant Portal and switch to your Demo Company — it was auto-created at sign-up and acts as the sandbox. Use the profile avatar (top right) to switch companies.
  2. Open the gear icon (top right) → API KeyCreate API Key. Keys created inside the Demo Company are sandbox keys and start with epd_test_sk_.
  3. Send that key with your request. Any request made with a sandbox key runs in sandbox mode automatically.
  4. Use one of the sandbox card tokens below as the billing_id (also called the EPD Gateway customer vault id) when adding a payment method to a customer.

Sandbox card tokens work only with sandbox keys. Sending one with a live key returns error.code = invalid_vault_id.

Sandbox card tokens

Pass these strings as the billing_id field on POST /v1/customers/:id/payment_methods. Each one simulates a different downstream outcome when the card is later charged.

Success

TokenNetworkOutcome
card_visaVisaCharges succeed
card_mastercardMastercardCharges succeed
card_amexAmerican ExpressCharges succeed
card_discoverDiscoverCharges succeed

Decline & failure

TokenOutcomeerror.code
card_visa_declinedGeneric Visa declinecard_declined
card_mastercard_declinedGeneric Mastercard declinecard_declined
card_insufficient_fundsCard valid but no funds availableinsufficient_funds
card_expiredCard has expiredexpired_card
card_processing_errorGateway-side processing error (retryable)gateway_error
card_cvv_mismatchCVV check failedcard_declined
card_chargebackCharge succeeds, then a chargeback is simulatedpayment_failed

End-to-end example: simulate a successful charge

Create a customer
curl https://api.epd.com/v1/customers \
  -H "Authorization: Bearer $EPD_TEST_KEY" \
  -H "epd-version: 2026-02-11" \
  -H "Content-Type: application/json" \
  -d '{
    "email": "jane@example.com",
    "first_name": "Jane",
    "last_name": "Doe",
    "phone": "+14155551234"
  }'
Attach a sandbox card

Pass the test token as billing_id. EPD mirrors the card from the gateway vault and returns a UUID id for the payment method.

curl https://api.epd.com/v1/customers/$CUSTOMER_ID/payment_methods \
  -H "Authorization: Bearer $EPD_TEST_KEY" \
  -H "epd-version: 2026-02-11" \
  -H "X-EPD-Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
    "billing_id": "card_visa",
    "set_as_default": true
  }'
Create a product

Orders charge against a product, not a free-form amount. Create one and save its id as $PRODUCT_ID.

curl https://api.epd.com/v1/products \
  -H "Authorization: Bearer $EPD_TEST_KEY" \
  -H "epd-version: 2026-02-11" \
  -H "X-EPD-Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Sandbox Test Product",
    "sku": "sandbox-test-product",
    "description": "A throwaway product for sandbox testing.",
    "pricing": { "amount": 2000, "currency": "usd" },
    "requires_shipping": false
  }'
Create an order
curl https://api.epd.com/v1/orders \
  -H "Authorization: Bearer $EPD_TEST_KEY" \
  -H "epd-version: 2026-02-11" \
  -H "X-EPD-Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
    "customer_id": "'"$CUSTOMER_ID"'",
    "payment_method_id": "'"$PM_ID"'",
    "items": [
      { "product_id": "'"$PRODUCT_ID"'", "quantity": 1 }
    ]
  }'

Example: simulate an insufficient-funds decline

Reuse the flow above but use card_insufficient_funds:

curl https://api.epd.com/v1/customers/$CUSTOMER_ID/payment_methods \
  -H "Authorization: Bearer $EPD_TEST_KEY" \
  -H "epd-version: 2026-02-11" \
  -H "X-EPD-Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{ "billing_id": "card_insufficient_funds" }'

When you create the order, the response will be:

{
  "error": {
    "type": "processing_error",
    "code": "insufficient_funds",
    "message": "Your card has insufficient funds.",
    "request_id": "req_..."
  }
}

What sandbox does not simulate

  • Real settlement timing. Sandbox confirmations are immediate; live cards settle 1–3 business days later.
  • Issuer-specific edge cases. Some banks reject otherwise-valid charges based on internal risk rules; sandbox cannot reproduce those.
  • 3-D Secure / SCA challenges. EPD Commerce currently does not require 3DS for sandbox or live transactions through this API.

If you need an outcome not listed above, contact support — many additional decline codes can be enabled per-account.