Testing
The Pay Theory sandbox simulates payment processing end to end. Approvals and declines depend on the card or bank account number you use. Settlements, ACH returns, and disputes don't happen on their own in sandbox. You trigger each one with a sandbox-only GraphQL mutation.
This guide covers:
- Test card and bank account numbers, including the ones that fail
- Settling transactions
- Creating ACH returns
- Creating disputes and moving them to won or lost
For webhook setup and payload examples, see Webhooks.
How Sandbox Processing Works
When you tokenize a payment method or run a payment, the sandbox checks the card number or bank account number against a list of failure triggers.
- If the number is on the list, the request fails with that entry's failure code.
- Any other valid number succeeds.
- The amount doesn't affect the result.
- The sandbox checks the list when you create the payment method and again when you run a sale or authorization. So a failure number fails at tokenization, before you get a payment method token.
- Captures, refunds, and voids always succeed.
Some older sandboxes still run payments through a processor's test environment instead of the Pay Theory sandbox. If the test numbers or sandbox mutations on this page don't work for you, your sandbox likely needs an update. Email Pay Theory support at support@paytheory.com and we'll update it for you.
Testing Card Payments
Successful Cards
Use any valid card number that isn't on the failure list. These numbers approve and show the matching card brand:
| Card Brand | Testing Number |
|---|---|
| Visa | 4835 0345 9845 7895 |
| Discover | 6560 0545 6789 1235 |
| MasterCard | 5560 9578 9456 1234 |
| Amex | 3479 847894 56149 |
Use any future expiration date, any CVV, and any ZIP code.
Card Types
| Card Type | Testing Number |
|---|---|
| Business Credit | 4389 9414 7258 3697 |
| Business Debit | 4472 7136 9258 1472 |
| Credit Card | 4835 0325 8143 6793 |
| Debit Card | 4398 8445 6789 1232 |
| Prepaid Card | 4307 6415 9482 6375 |
Cards By Country
| Country | Testing Number |
|---|---|
| Canada | 4527 7111 5544 8861 |
| USA | 4835 0345 9845 7895 |
Card Failures
These card numbers fail with the listed failure code.
| Failure Code | Card Number |
|---|---|
| GENERIC_DECLINE | 4000 0001 0000 0001 |
| INSUFFICIENT_FUNDS | 4000 0002 0000 0000 |
| INVALID_ACCOUNT_NUMBER | 4000 0003 0000 0009 |
| EXPIRED_CARD | 4000 0004 0000 0008 |
| INVALID_CVV | 4000 0005 0000 0007 |
| DO_NOT_HONOR | 4000 0006 0000 0006 |
| LOST_OR_STOLEN_CARD | 4000 0007 0000 0005 |
| FRAUD_DETECTED | 4000 0008 0000 0004 |
| CARD_NOT_SUPPORTED | 4000 0009 0000 0003 |
| CALL_ISSUER | 4000 0010 0000 0000 |
| PICK_UP_CARD | 4000 0011 0000 0009 |
| RESTRICTED_CARD | 4000 0012 0000 0008 |
| EXCEEDS_APPROVAL_LIMIT | 4000 0013 0000 0007 |
| INVALID_TRANSACTION | 4000 0014 0000 0006 |
| TRANSACTION_NOT_PERMITTED | 4000 0015 0000 0005 |
| INACTIVE_CARD | 4000 0016 0000 0004 |
| DUPLICATE_TRANSACTION | 4000 0017 0000 0003 |
| SYSTEM_ERROR | 4000 0018 0000 0002 |
| TIMEOUT | 4000 0019 0000 0001 |
| COMMUNICATION_ERROR | 4000 0020 0000 0008 |
| ADDRESS_VERIFICATION_FAILED_RISK_RULES | 4000 0021 0000 0007 |
| CVV_FAILED_RISK_RULES | 4000 0022 0000 0006 |
For what each failure code means, see Failed Transactions.
Testing ACH Payments
The sandbox ignores the routing number when it decides the outcome. Pass any valid routing number, such as 122105278.
Any account number not listed below succeeds. These account numbers fail with the listed failure code:
| Failure Code | Account Number |
|---|---|
| INVALID_BANK_ACCOUNT_NUMBER | 0000000001 |
| BANK_ACCOUNT_CLOSED | 0000000002 |
| NO_BANK_ACCOUNT_FOUND | 0000000003 |
| BANK_ACCOUNT_FROZEN | 0000000004 |
| GENERIC_DECLINE | 0000000005 |
| NON_TRANSACTION_ACCOUNT | 0000000006 |
| INVALID_ROUTING_NUMBER | 0000000007 |
| PAYMENT_STOPPED | 0000000008 |
These failures happen right away, when you submit the payment. To test an ACH payment that succeeds and is returned later, settle it first and then create an ACH return.
Settling Transactions
Sandbox transactions stay unsettled until you settle them. Settling a merchant takes two mutations:
prepareSandboxSettlementBatchcollects everything waiting to settle and calculates the totals.createSandboxSettlementcreates the settlement from that batch.
You need settled transactions before you can create ACH returns or disputes, so you'll run these two mutations often.
1. Prepare the Batch
mutation {
prepareSandboxSettlementBatch(input: { merchant_uid: "your_merchant_uid" }) {
prep_id
debit_ids
reversal_ids
ach_return_ids
dispute_withdrawal_ids
dispute_deposit_ids
calculated_gross_amount
calculated_net_amount
}
}
The batch includes the merchant's unsettled:
PENDINGpayments- Refunds
- ACH returns
- Disputes that are open and haven't been withdrawn yet
- Disputes that were won and haven't been deposited yet
- Split payments
Preparing the batch captures those PENDING payments and moves them to SUCCEEDED, so you don't need to capture them yourself. The batch also charges the merchant's ACH return fee for each ACH return and the chargeback fee for each dispute withdrawal, based on the merchant's fee settings.
2. Create the Settlement
mutation {
createSandboxSettlement(input: { merchant_uid: "your_merchant_uid" }) {
success
}
}
Once the batch is prepared, create the settlement. Every item in the batch moves to SETTLED, and a settlement batch is created for the merchant.
If the batch included PENDING payments, the captures may still be running when you call createSandboxSettlement. In that case it returns Captures not yet complete. Wait a few seconds and try again.
A few rules to keep in mind:
- A merchant can have only one prepared batch waiting at a time. If you call
prepareSandboxSettlementBatchagain before you create the settlement, it returnsExisting settlement batch prep has not been reconciled. - If there is nothing to settle,
prepareSandboxSettlementBatchreturnsNo settlement items found for merchant. - Both mutations queue their work and return right away. Settlement records can take a few seconds to appear in queries. See Query Settlement Data.
Triggering ACH Returns
Use createSandboxAchReturn to return an ACH payment or refund. The transaction must be:
- An ACH payment or an ACH refund
- Settled. A
PENDINGorSUCCEEDEDtransaction is rejected, so settle it first.
mutation {
createSandboxAchReturn(
input: { transaction_id: "your_transaction_id", return_code: R01 }
) {
success
ach_return_transaction_id
return_code
}
}
return_code accepts any standard NACHA return code from R01 to R85. The code you pick is recorded on the transaction. Every code behaves the same way in sandbox. See the create sandbox ACH return reference for the full list.
When the return goes through:
- The original transaction changes to
RETURNEDand itsach_return_detailshold the return code. - A new
ACH_RETURNtransaction is created for the full amount, with the original transaction as its parent. Its ID is theach_return_transaction_idin the response. - Returning a payment takes the money back from the merchant. Returning a refund gives it back to the merchant.
- The next settlement includes the return and charges the merchant's ACH return fee.
You can request one return per transaction. A second request for the same transaction returns ACH return already requested.
Triggering Disputes
A sandbox dispute takes three settlements to go from payment to resolution:
- Settle the card payment.
- Create the dispute, then settle again. This settlement withdraws the disputed amount and the chargeback fee from the merchant.
- Mark the dispute won or lost. If it's won, settle again to deposit the amount back to the merchant.
Create a Dispute
The transaction must be a settled card payment. Refunds and ACH payments can't be disputed.
mutation {
createSandboxDispute(
input: { transaction_id: "your_transaction_id", reason: FRAUD }
) {
success
dispute_id
transaction_id
}
}
| Key | type | description |
|---|---|---|
| transaction_id | String | The settled card payment to dispute. |
| reason | DisputeReason | One of CLERICAL, FRAUD, INQUIRY, QUALITY, or TECHNICAL. |
The dispute:
- Covers the full payment amount.
- Starts in
PENDING, whateverreasonyou pass. - Has a respond-by date seven days out.
A transaction can have only one open dispute at a time.
Resolve a Dispute
Before you can close a dispute, a settlement has to withdraw the disputed amount. Run both settlement mutations after you create the dispute. The batch lists the dispute in dispute_withdrawal_ids.
Then move the dispute to WON or LOST:
mutation {
updateSandboxDisputeStatus(
input: { dispute_id: "your_dispute_id", status: WON }
) {
success
}
}
LOSTcloses the dispute. The merchant already paid the amount in the earlier settlement, so nothing else moves.WONcloses the dispute in the merchant's favor. The next settlement deposits the amount back to the merchant and lists the dispute indispute_deposit_ids.
WON and LOST are final. A closed dispute can't change status again.
Testing Merchant Onboarding
New sandbox merchants are boarded and ready to take payments as soon as you create them. To test the onboarding flow instead, include "onboarding" anywhere in the merchant name, such as Acme Onboarding Test. Case doesn't matter.
mutation {
createMerchant(merchant_name: "Acme Onboarding Test") {
merchant_uid
}
}
A merchant with "onboarding" in its name:
- Starts with card and ACH processing turned off.
- Shows in the portal as a merchant who still needs to fill out the onboarding form.
- Is approved automatically as soon as you submit the form in sandbox.
Testing Barcode Payments
To simulate a customer paying a cash barcode, call createBarcodePaymentSandbox with the barcode ID and the amount paid in cents. The amount must match the barcode's amount. See the create sandbox barcode payment reference for the full request and response.
Common Errors
Settlements
No settlement items found for merchant: the merchant has nothing waiting to settle.Existing settlement batch prep has not been reconciled: you already prepared a batch. CallcreateSandboxSettlementbefore you prepare another one.No pending settlement prep found: callprepareSandboxSettlementBatchfirst.Captures not yet complete: wait a few seconds and callcreateSandboxSettlementagain.
ACH Returns and Disputes
Transaction cannot be pending or succeeded: the transaction hasn't settled yet. Settle it, then retry.Transaction is not ACH: you calledcreateSandboxAchReturnon a card payment.Transaction is not a card payment: you calledcreateSandboxDisputeon an ACH payment.Transaction already has an active dispute: the transaction already has an open dispute.Dispute must be part of a settlement withdrawal batch before closing: settle the merchant after you create the dispute, then update the status.
Any Sandbox Mutation
Merchant is not using an allowed processor: your sandbox needs an update. Email support@paytheory.com and we'll update it for you.