Testing your integration
The sandbox processor answers from a fixed table instead of reaching a card network, so every case below is repeatable. Send the trigger and you get the outcome, every time.
How the triggers work
Route a merchant to the sandbox processor, then provoke a case in one of two ways. Most cases key off the transaction amount: the cents pick the outcome, and the amount you send is otherwise ignored. The rest key off a value you already send anyway, such as the billing ZIP or the CVV.
When you need an outcome no amount produces, send a control field instead. Control fields go on the transaction as a custom field, are matched without regard to case, and outrank the amount triggers. Every one of them is listed at the bottom of this page.
One constraint applies to the custom-field channel. If the merchant has defined any custom fields at all, every submitted custom-field name has to match one of those definitions, and a name that doesn't match is rejected with a 400. A sandbox merchant with no custom-field definitions accepts any name, which is the usual case. If you get a 400 naming the control field you sent, define a custom field with that name on the merchant.
Nothing on this page reaches a card network or moves money, and none of it works on a merchant routed to a live processor.
Test cards
Every card below is a published test number: it's issued to nobody, carries no funds and reaches no card network. Send one with the expiry and CVV shown. Any other network test card works too, as long as the BIN database knows its prefix.
One card per brand
These cards decide nothing about the outcome; the amount does that. Send each brand at least once, because several response modifiers are brand-scoped and a client that only ever sends one brand has never exercised its own brand handling.
| Brand | Number | Expiry | CVV | What it exercises |
|---|---|---|---|---|
| Visa | 4111111111111111 |
12/2030 |
123 |
Brand handling on the Visa rail. The amount decides the outcome, and the classification comes from the BIN database like any real card. |
| Mastercard | 5555555555554444 |
12/2030 |
123 |
Brand handling on the Mastercard rail. The amount decides the outcome, and the classification comes from the BIN database like any real card. |
| Amex | 378282246310005 |
12/2030 |
1234 |
Brand handling on the Amex rail. The amount decides the outcome, and the classification comes from the BIN database like any real card. |
| Discover | 6011111111111117 |
12/2030 |
123 |
Brand handling on the Discover rail. The amount decides the outcome, and the classification comes from the BIN database like any real card. |
Cards that classify as something specific
Send one of these when you need the platform to see a debit, prepaid, commercial, government, healthcare or EBT card. The full number resolves to the classification shown, in every environment, so acceptance rules, fee and surcharge eligibility, enhanced-data requirements and the commercial-card indicator on the response all behave as they would for a real card of that kind. Only the exact number classifies this way; a number that merely shares the prefix resolves from the BIN database like any other.
| Classifies as | Number | Expiry | CVV | What it exercises |
|---|---|---|---|---|
| Visa, Debit, classic, personal | 4002960001111116 |
12/2030 |
123 |
Classifies as consumer debit, so debit-only acceptance, fee and surcharge rules see a debit card. |
| Mastercard, Debit, standard, personal | 5555531000000010 |
12/2030 |
123 |
Classifies as consumer debit on the Mastercard rail. |
| Mastercard, Debit, prepaid, personal, prepaid | 5312411232145699 |
12/2030 |
123 |
Classifies as prepaid, so the funding source reads Prepaid rather than Debit and prepaid-specific rules apply. |
| Visa, Credit, purchasing, commercial | 4005562231212123 |
12/2030 |
123 |
Classifies as a commercial purchasing card, so the response reports a commercial card and Level 2 and Level 3 data rules engage. |
| Amex, Credit, corporate, commercial, regulated | 378730000000006 |
12/2030 |
1234 |
Classifies as a commercial corporate card on the American Express rail, with the regulated flag set. Carries a four-digit CVV, as every American Express card does. |
| Visa, Debit, prepaid healthcare, personal, healthcare, prepaid | 4373191234567806 |
12/2030 |
123 |
Classifies as a healthcare (FSA) card: prepaid debit with the healthcare flag, which is what healthcare-eligibility rules key on. |
| EBT, Debit, standard, personal | 5076800001111112 |
12/2030 |
123 |
Classifies the way a real EBT card does: brand EBT on the debit rail. The tender is never inferred from the card. Send a tender type of EbtSnap, EbtCash or Ewic with PIN data, on a merchant with that tender enabled; sent without a tender it processes as an ordinary debit card. Amount triggers do not apply to this card. |
| Visa, Credit, purchasing government, commercial, government | 4486000000000005 |
12/2030 |
123 |
Classifies as a government purchase (GSA) card, which is also commercial, so government-card data requirements engage. No processor publishes a GSA test card, so this is a synthesized Luhn-valid number in the GSA SmartPay Visa purchase-card range. It resolves only through the sandbox classification, never from the BIN database. |
The amount still decides the outcome for these cards, with one exception: the EBT card takes no amount trigger and approves unless a control field says otherwise. To see a debit routing indicator on the response, send isDebitRouting as true on the card; the loopback.routing control field outranks it.
For one scenario per classification card, with the request to send, the classification to expect on the response and the behavior each card lets you observe, read Sandbox test cards.
Start here: one guaranteed case each way
If you only wire up two tests per flow, wire up these. Each pair is guaranteed to succeed and to fail respectively, and neither depends on anything about the card you send.
| Flow | Always succeeds | Result | Always fails | Result |
|---|---|---|---|---|
| Card authorization | 10.00 |
Ok: Approved | 10.01 |
Decline: AUTH DECLINED; host error 200 |
| Partial approval and prepaid | 2.03 |
Ok: Approved; beginning balance 0.00 | 9.66 |
Decline: Decline; beginning balance 4.03; available balance 5.08 |
| Prepaid balance responses | 19.71 |
Ok: Approved | 89.66 |
Decline: Decline; beginning balance 74.75; available balance 75.80 |
| ACH debits and returns | 25.00 |
Ok: ACH Sale Approved | 25.01 |
Decline: ACH Returned (R01); NACHA R01 |
| Processor failover | loopback.notProcessedProfileId=<primary profile id> |
Ok: Approved | loopback.notProcessed=true |
Decline: The transaction could not be processed by an available processor. |
| Address verification (AVS) | 66666 |
Y: Address and ZIP match | 33333 |
N: Address and ZIP do not match |
| Cardholder verification (CVV) | 111 |
M: CVV match | 222 |
N: CVV no match |
Card authorization
The cents of the transaction amount select the outcome. These apply to Visa, Mastercard, Amex and Discover; a brand the sandbox does not recognise approves everything.
| Send | Trigger | Outcome | Result |
|---|---|---|---|
10.00 |
Any amount of 1.00 or more whose cents are not listed below, on any supported brand. Amounts under 1.00 also approve on every brand except Discover. | Approved | Ok: Approved |
10.01 |
Any amount of 1.00 or more whose cents are .01. | Declined | Decline: AUTH DECLINED; host error 200 |
10.02 |
Any amount of 1.00 or more whose cents are .02. | Referral | Referral: CALL VOICE OPER; host error 201 |
10.03 |
Any amount of 1.00 or more whose cents are .03. | Referral | Referral: HOLD - CALL; host error 202 |
10.04 |
Any amount of 1.00 or more whose cents are .04. | Referral | Referral: CALL VOICE OPER; host error 203 |
10.05 |
Any amount of 1.00 or more whose cents are .05. | Error | InvalidAccountNumber: INVALID CARD NO; host error 204 |
10.06 |
Any amount of 1.00 or more whose cents are .06. | Error | InvalidExpirationDate: INVALID EXP DATE; host error 205 |
10.07 |
Any amount of 1.00 or more whose cents are .07. | Error | InvalidMerchantInfo: INVALID ICA NO; host error 206 |
10.08 |
Any amount of 1.00 or more whose cents are .08. | Error | InvalidAbaNumber: INVALID ABA NO; host error 207 |
10.09 |
Any amount of 1.00 or more whose cents are .09. | Error | FieldFormatError: INVALID PIN NO; host error 208 |
10.10 |
Any amount of 1.00 or more whose cents are .10. | Error | InvalidMerchantInfo: INVALID BANK MID; host error 209 |
10.11 |
Any amount of 1.00 or more whose cents are .11. | Error | InvalidRegisterInfo: INVALID TERM NO; host error 210 |
10.12 |
Any amount of 1.00 or more whose cents are .12. | Error | InvalidAmount: INVALID AMOUNT; host error 211 |
10.13 |
Any amount of 1.00 or more whose cents are .13. | Error | FieldFormatError: INVALID STATE CD; host error 212 |
10.14 |
Any amount of 1.00 or more whose cents are .14. | Declined | Decline: DECLINE; host error 213 |
10.15 |
Any amount of 1.00 or more whose cents are .15. | Referral | Referral: CALL VOICE OPER; host error 214 |
10.16 |
Any amount of 1.00 or more whose cents are .16. | Declined | Decline: LOST/STOLEN CARD; host error 215 |
10.17 |
Any amount of 1.00 or more whose cents are .17. | Error | FieldFormatError: INVALID PIN; host error 216 |
10.18 |
Any amount of 1.00 or more whose cents are .18. | Declined | InsufficientFundsAvailable: OVER CREDIT FLR; host error 217 |
10.19 |
Any amount of 1.00 or more whose cents are .19. | Rejected | Reject: *REQUEST DENIED*; host error 218 |
10.20 |
Any amount of 1.00 or more whose cents are .20. | Error | GeneralError: NOT ONLINE TO ??; host error 220 |
10.21 |
Any amount of 1.00 or more whose cents are .21. | Rejected | Reject: *REQUEST DENIED*; host error 218 |
10.22 |
Any amount of 1.00 or more whose cents are .22. | Rejected | Reject: *REQUEST DENIED*; host error 218 |
10.23 |
Any amount of 1.00 or more whose cents are .23. | Rejected | Reject: *REQUEST DENIED*; host error 218 |
10.24 |
Any amount of 1.00 or more whose cents are .24. | Rejected | Reject: *REQUEST DENIED*; host error 218 |
10.25 |
Any amount of 1.00 or more whose cents are .25. | Rejected | Reject: *REQUEST DENIED*; host error 218 |
10.59 |
Any amount of 1.00 or more whose cents are .59. | Declined | Decline: DECLINED PER CARDHOLDER; host error 218 |
10.92 |
Any amount of 1.00 or more whose cents are .92. | Rejected | Reject: *REQUEST DENIED*; host error 218 |
10.93 |
Any amount of 1.00 or more whose cents are .93. | Rejected | Reject: *REQUEST DENIED*; host error 218 |
10.94 |
Any amount of 1.00 or more whose cents are .94. | Rejected | Reject: *REQUEST DENIED*; host error 218 |
10.97 |
Any amount of 1.00 or more whose cents are .97. | Rejected | Reject: *REQUEST DENIED*; host error 218 |
10.98 |
Any amount of 1.00 or more whose cents are .98. | Rejected | Reject: *REQUEST DENIED*; host error 218 |
10.99 |
Any amount of 1.00 or more whose cents are .99. | Rejected | Reject: *REQUEST DENIED*; host error 218 |
1000000.00 |
Any amount above 999,999.99. Checked before the cents table, so it wins whatever the cents are. | Error | InvalidAmount: INVALID AMOUNT; host error 319 |
0.50 |
Any amount below 1.00 on Discover. Brand-specific. The same amount approves on Visa, Mastercard and Amex. | Error | InvalidAmount: INVALID AMOUNT; host error 211 |
Partial approval and prepaid
Send a prepaid indicator of P (or a partial-authorization indicator of true) and the exact amount selects the outcome. This is how you exercise a partial approval, which is the case most integrations get wrong.
| Send | Trigger | Outcome | Result |
|---|---|---|---|
0.00 |
Prepaid indicator P (or partial-authorization indicator true) with this exact amount. | Approved | Ok: Approved; beginning balance 3.01 |
2.03 |
Prepaid indicator P (or partial-authorization indicator true) with this exact amount. | Approved | Ok: Approved; beginning balance 0.00 |
2.78 |
Prepaid indicator P (or partial-authorization indicator true) with this exact amount. | Partial approval | Partial: Partial Approval; approves 2.57; beginning balance 0.00 |
3.26 |
Prepaid indicator P (or partial-authorization indicator true) with this exact amount. | Partial approval | Partial: Partial Approval; approves 1.26; beginning balance 0.00 |
3.27 |
Prepaid indicator P (or partial-authorization indicator true) with this exact amount. | Partial approval | Partial: Partial Approval (Non-Prepaid Card); approves 1.27; beginning balance 0.00 |
3.28 |
Prepaid indicator P (or partial-authorization indicator true) with this exact amount. | Approved | Ok: Full/Partial Approval (Depleted Card); approves 3.28 |
4.41 |
Prepaid indicator P (or partial-authorization indicator true) with this exact amount. | Partial approval | Partial: Partial Approval; approves 2.00; beginning balance 0.00 |
6.34 |
Prepaid indicator P (or partial-authorization indicator true) with this exact amount. | Partial approval | Partial: Partial Approval; approves 3.56; beginning balance 0.00 |
7.67 |
Prepaid indicator P (or partial-authorization indicator true) with this exact amount. | Partial approval | Partial: Partial Approval; approves 4.49; beginning balance 0.00 |
8.64 |
Prepaid indicator P (or partial-authorization indicator true) with this exact amount. | Partial approval | Partial: Partial Approval; approves 2.30; beginning balance 0.00 |
9.63 |
Prepaid indicator P (or partial-authorization indicator true) with this exact amount. | Approved | Ok: Approved; beginning balance 3.01 |
9.64 |
Prepaid indicator P (or partial-authorization indicator true) with this exact amount. | Approved | Ok: Approved; beginning balance 3.02; available balance 4.34 |
9.65 |
Prepaid indicator P (or partial-authorization indicator true) with this exact amount. Returns negative balances, so a client that assumes non-negative values fails here. | Approved | Ok: Approved; beginning balance -4.02; available balance -5.49 |
9.66 |
Prepaid indicator P (or partial-authorization indicator true) with this exact amount. | Declined | Decline: Decline; beginning balance 4.03; available balance 5.08 |
9.67 |
Prepaid indicator P (or partial-authorization indicator true) with this exact amount. | Partial approval | Partial: Partial Approval; approves 2.00; beginning balance 0.00 |
9.68 |
Prepaid indicator P (or partial-authorization indicator true) with this exact amount. | Approved | Ok: Approved; beginning balance 0.00 |
9.69 |
Prepaid indicator P (or partial-authorization indicator true) with this exact amount. | Partial approval | Partial: Partial Approval; approves 7.00; beginning balance 0.00 |
9.70 |
Prepaid indicator P (or partial-authorization indicator true) with this exact amount. | Declined | Decline: Decline; beginning balance 3.08 |
9.71 |
Prepaid indicator P (or partial-authorization indicator true) with this exact amount. | Approved | Ok: Approved |
9.72 |
Prepaid indicator P (or partial-authorization indicator true) with this exact amount. | Approved | Ok: Approved; beginning balance 156.10 |
21.64 |
Prepaid indicator P (or partial-authorization indicator true) with this exact amount. | Approved | Ok: Approved; beginning balance 43.45 |
24.41 |
Prepaid indicator P (or partial-authorization indicator true) with this exact amount. | Partial approval | Partial: Partial Approval; approves 19.00; beginning balance 0.00 |
37.88 |
Prepaid indicator P (or partial-authorization indicator true) with this exact amount. | Partial approval | Partial: Partial Approval; approves 15.36; beginning balance 0.00 |
Prepaid balance responses
Send a prepaid indicator of B and the exact amount selects which balances come back, including negative ones.
| Send | Trigger | Outcome | Result |
|---|---|---|---|
19.71 |
Prepaid indicator B with this exact amount. | Approved | Ok: Approved |
59.63 |
Prepaid indicator B with this exact amount. | Approved | Ok: Approved; beginning balance 100.01 |
69.64 |
Prepaid indicator B with this exact amount. | Approved | Ok: Approved; beginning balance 33.02; available balance 34.34 |
79.65 |
Prepaid indicator B with this exact amount. Returns negative balances, so a client that assumes non-negative values fails here. | Approved | Ok: Approved; beginning balance -4.02; available balance -5.49 |
89.66 |
Prepaid indicator B with this exact amount. | Declined | Decline: Decline; beginning balance 74.75; available balance 75.80 |
99.68 |
Prepaid indicator B with this exact amount. | Approved | Ok: Approved; beginning balance 0.00 |
109.70 |
Prepaid indicator B with this exact amount. | Declined | Decline: Decline; beginning balance 43.08 |
ACH debits and returns
A transaction carrying check data runs on the ACH rail, where the cents of the amount select the NACHA return. An ACH return is reported as a decline with the return code and reason on the response. That decline is synchronous and final: the sale was refused, so no settlement status ever moves and no ACH lifecycle event is published. The ordinary decline notification still fires. Use this flow to prove your code reads a return code off a declined response. To exercise an ACH webhook, send a sale at an approving amount and then move it with the sandbox ACH status endpoint, which publishes the real status-changed and returned events on demand. The VeriCheck sandbox remains the way to see the real multi-day timing alongside them.
| Send | Trigger | Outcome | Result |
|---|---|---|---|
25.00 |
Any ACH amount below 50,000.00 whose cents are not listed below. The result message names the transaction type, so an ACH authorization reads "ACH Authorization Approved" instead. | Approved | Ok: ACH Sale Approved |
25.01 |
An ACH amount whose cents are .01. | Declined | Decline: ACH Returned (R01); NACHA R01 |
25.02 |
An ACH amount whose cents are .02. | Declined | Decline: ACH Returned (R02); NACHA R02 |
25.03 |
An ACH amount whose cents are .03. | Declined | Decline: ACH Returned (R03); NACHA R03 |
25.04 |
An ACH amount whose cents are .04. | Declined | Decline: ACH Returned (R04); NACHA R04 |
25.07 |
An ACH amount whose cents are .07. | Declined | Decline: ACH Returned (R07); NACHA R07 |
25.08 |
An ACH amount whose cents are .08. | Declined | Decline: ACH Returned (R08); NACHA R08 |
25.10 |
An ACH amount whose cents are .10. | Declined | Decline: ACH Returned (R10); NACHA R10 |
25.16 |
An ACH amount whose cents are .16. | Declined | Decline: ACH Returned (R16); NACHA R16 |
25.20 |
An ACH amount whose cents are .20. | Declined | Decline: ACH Returned (R20); NACHA R20 |
50000.00 |
Any ACH amount of 50,000.00 or more whose cents are not listed above. | Declined | Decline: ACH Returned (R01); NACHA R01 |
Processor failover
The sandbox can report that it did not process a transaction at all, which is what makes the gateway attempt its one-shot authorization failover. Nothing is charged either way.
| Send | Trigger | Outcome | Result |
|---|---|---|---|
loopback.notProcessedProfileId=<primary profile id> |
Send loopback.notProcessedProfileId with the id of your primary processor profile. The primary profile reports that it did not process, authorization failover selects the fallback profile, and the fallback approves. Requires the merchant to have a second active processor profile. | Approved | Ok: Approved |
loopback.notProcessed=true |
Send loopback.notProcessed set to true. Every profile reports that it did not process, so failover is attempted once and then exhausted. On a merchant with a single profile this instead exercises the fail-closed no-processor-configured path. | Declined | Decline: The transaction could not be processed by an available processor. |
Address verification (AVS)
The billing ZIP selects the AVS response code. The code comes back on the transaction whatever your own AVS policy then does with it.
| Billing ZIP | Response code | Meaning | Card brand |
|---|---|---|---|
11111 |
A |
Address match only | Any |
44445 |
B |
Address matches, ZIP not verified | Any |
66667 |
C |
Address and ZIP not verified due to incompatible formats | Any |
77778 |
D |
Address and ZIP match (international) | Any |
88888 |
G |
Address not verified (international) | Any |
88889 |
I |
Address not verified (international) | Any |
22222 |
M |
Address and ZIP match (international) | Any |
33333 |
N |
Address and ZIP do not match | Any |
55556 |
P |
ZIP matches, address not verified | Any |
44444 |
R |
System unavailable, retry | Any |
11112 |
S |
AVS not supported | Any |
11113 |
T |
9-digit ZIP matches, address does not | Any |
55555 |
U |
Address information unavailable | Any |
22223 |
W |
9-digit ZIP match, address mismatch | Any |
33334 |
X |
Address and 9-digit ZIP match | Any |
66666 |
Y |
Address and ZIP match | Any |
77777 |
Z |
ZIP match only | Any |
Cardholder verification (CVV)
The CVV selects the cardholder-verification response code. Any CVV without a trigger of its own comes back as a mismatch, so an arbitrary value is a usable negative case.
| CVV | Response code | Meaning | Card brand |
|---|---|---|---|
111 |
M |
CVV match | Any |
222 |
N |
CVV no match | Any |
333 |
P |
CVV not processed | Any |
444 |
S |
CVV should be on card | Any |
555 |
U |
Issuer unable to process CVV | Any |
666 |
(none) |
No code returned The response carries no cardholder-verification code at all, which is how you exercise a client that assumes one is always present. | Any |
777 |
N |
CVV no match | Any |
2222 |
Y |
CVV match (Amex CID) | Amex |
1111 |
N |
CVV no match | Amex |
9999 |
U |
Issuer unable to process CVV | Amex |
Response modifiers
These amounts don't change whether a transaction approves. They change the shape of the response, which is what you want when you're testing your parser.
| Trigger | Effect |
|---|---|
| Visa, amount 1.69, entered manually. | Forces AVS response Y regardless of the billing address sent. |
| Visa, amount 19.58. | Guarantees the authorization code contains the letter D, which is how you exercise a client that parses authorization codes as digits. |
| Visa, any amount from 98.26 to 98.91 inclusive. | Returns downgrade extended error data on the processor response detail. The transaction still approves. |
Response latency
Send loopback.latencyProfile with one of these names and the sandbox takes a realistic amount of time to answer. Each delay is sampled from a log-normal distribution fitted to the profile's median and 95th percentile, then capped at its 99th, so repeated calls vary the way a real processor does rather than pausing for a fixed interval.
Send loopback.latencyMs instead when you want an exact delay, or custom as the profile name together with the three percentile fields to fit your own distribution.
| Profile | Median | 95th | 99th | What it is for |
|---|---|---|---|---|
none |
0 ms | 0 ms | 0 ms | No delay. The default when no profile is configured. |
fast |
50 ms | 200 ms | 500 ms | A responsive processor on a good day. |
typical |
200 ms | 800 ms | 1500 ms | What a healthy card processor usually looks like. |
slow |
500 ms | 2000 ms | 4000 ms | A degraded processor. Use this to check your own timeouts and retries. |
timeout |
3000 ms | 10000 ms | 15000 ms | Long enough to trip most client timeouts. Use this to exercise your timeout path. |
Control fields
Every field the sandbox reads. Send either spelling, on a transaction custom field. A control field outranks the amount triggers above.
| Field | Also accepted as | What it does | Example |
|---|---|---|---|
loopback.resultCode |
loopbackresultcode |
Forces the result code, by member name, by numeric value, or by one of the friendly aliases (approve, decline, partial, submit, pending, reject, referral, insufficientfunds, error). Outranks every amount trigger. | decline |
loopback.result |
loopbackresult |
Alias of loopback.resultCode, read only when that field is absent. | approve |
loopback.approved |
loopbackapproved |
Set to false to force a decline. Ignored when loopback.resultCode is present. | false |
loopback.declined |
loopbackdeclined |
Set to true to force a decline. Ignored when loopback.resultCode is present. | true |
loopback.resultMessage |
loopbackmessage |
Overrides the result message the simulator returns. | Sale Approved |
loopback.resultDetail |
loopbackdetail |
Overrides the longer result detail the simulator returns. | Simulated for integration testing |
loopback.extendedErrorData |
loopbackextendederrordata |
Overrides the extended error data on the processor response detail. | PSERV=N; Downgrade Reason = NP |
loopback.associationCode |
loopbackassociationcode |
Overrides the association response code, by member name or numeric value. | InsufficientFunds |
loopback.responseCategory |
loopbackresponsecategory |
Overrides the response category code, by member name or numeric value. | IssuerCannotApprove |
loopback.requestedAmount |
loopbackrequestedamount |
Overrides the amount the amount triggers are matched against, leaving the transaction's own total alone. Useful for provoking a scenario without changing what you are charging. | 10.01 |
loopback.approvedAmount |
loopbackapprovedamount |
Overrides the approved amount, which is how you provoke an arbitrary partial approval. | 5.00 |
loopback.beginningBalance |
loopbackbeginningbalance |
Overrides the beginning balance on the response amounts. | 25.00 |
loopback.availableBalance |
loopbackavailablebalance |
Overrides the available balance on the response amounts. | 20.00 |
loopback.cashback |
loopbackcashback |
Overrides the cashback amount on the response amounts. | 20.00 |
loopback.preauthorized |
loopbackpreauthorized |
Overrides the preauthorized amount, which otherwise mirrors the approved amount on an authorization. | 10.00 |
loopback.openToBuy |
loopbackopentobuy |
Sets the open-to-buy amount on the response amounts. | 150.00 |
loopback.ewicDiscount |
loopbackewicdiscount |
Sets the eWIC discount on the response amounts. | 1.25 |
loopback.transactionFee |
loopbacktransactionfee |
Sets the transaction fee on the response amounts. | 0.50 |
loopback.balanceDue |
loopbackbalancedue |
Overrides the balance due, which otherwise is the requested amount less the approved amount. | 2.00 |
loopback.avs |
loopbackavs |
Forces the AVS response code, outranking the ZIP triggers. | N |
loopback.avsText |
loopbackavstext |
Overrides the AVS response text. | Address and ZIP do not match |
loopback.cv |
loopbackcv |
Forces the cardholder-verification response code, outranking the CVV triggers. | N |
loopback.cvText |
loopbackcvtext |
Overrides the cardholder-verification response text. | CVV no match |
loopback.cvPresence |
loopbackcvpresence |
Overrides the CVV presence indicator, which forces a verification code of its own: 0 (not submitted) returns P, 2 (illegible) returns S, 9 (not present) returns U. Send 1 (submitted) to leave the CVV triggers in charge. | 2 |
loopback.streetMatchText |
loopbackstreetmatchtext |
Overrides the street-match text on the card validation data. | Street address did not match |
loopback.zipMatchText |
loopbackzipmatchtext |
Overrides the ZIP-match text on the card validation data. | ZIP did not match |
loopback.cardBrand |
loopbackcardbrand |
Overrides the card brand the amount triggers are evaluated for, so a scenario can be provoked without a matching test card. Visa, Mastercard, Amex or Discover. | Visa |
loopback.cardIndicator |
loopbackcardindicator |
Overrides the card indicator on the response, and is read as a fallback for the card brand. | Visa |
loopback.productId |
loopbackproductid |
Overrides the detailed product id on the response. | Credit |
loopback.prepaidIndicator |
loopbackprepaidindicator |
Selects a prepaid scenario table: P for the partial-approval table, B for the balance-response table. | P |
loopback.partialAuthIndicator |
loopbackpartialauthindicator |
Set to true to select the partial-approval scenario table, equivalently to sending a prepaid indicator of P. | true |
loopback.routing |
loopbackrouting |
Overrides the routing indicator, which otherwise reads ProcessedAsDebit when the card was sent with isDebitRouting true and follows the entry mode when it was not. | ProcessedAsDebit |
loopback.authCode |
loopbackauthcode |
Overrides the authorization code, which is otherwise generated from the transaction id. | SAA1B2 |
loopback.debitTrace |
loopbackdebittrace |
Overrides the debit trace number. | 004212 |
loopback.networkId |
loopbacknetworkid |
Overrides the authorizing network id. | LBK-NET-01 |
loopback.networkName |
loopbacknetworkname |
Overrides the authorizing network name. | Loopback Test Network |
loopback.signatureRecommended |
loopbacksignaturerecommended |
Overrides the signature-recommended flag, which otherwise turns on for an approved transaction of 25.00 or more. | false |
loopback.responseDate |
loopbackresponsedate |
Overrides the response date, parsed as UTC. | 2026-01-31T18:04:00Z |
loopback.clientIp |
loopbackclientip |
Overrides the client IP recorded on the response. | 198.51.100.7 |
loopback.latencyMs |
loopbacklatencyms |
Delays the response by exactly this many milliseconds. Outranks every latency profile. | 2500 |
loopback.latencyProfile |
loopbacklatencyprofile |
Selects a named latency profile, or custom to use the three percentile fields below. Falls back to the merchant's loopback processor profile when absent. | slow |
loopback.latencyP50Ms |
loopbacklatencyp50ms |
Median latency in milliseconds for the custom profile. | 200 |
loopback.latencyP95Ms |
loopbacklatencyp95ms |
95th-percentile latency in milliseconds for the custom profile. | 800 |
loopback.latencyP99Ms |
loopbacklatencyp99ms |
99th-percentile latency ceiling in milliseconds for the custom profile. The sampled delay is clamped here. | 1500 |
loopback.achReturnCode |
loopbackachreturncode |
Forces an ACH return with this NACHA code, outranking the ACH amount triggers. Any code is accepted, not only the ones the amount triggers cover. | R05 |
loopback.achReturnReason |
loopbackachreturnreason |
Overrides the reason text that accompanies a forced ACH return. Defaults to the catalog's reason for the code, or a generic one for a code the catalog does not carry. | Unauthorized Debit to Consumer Account |
loopback.secCode |
loopbacksec |
Overrides the SEC code echoed on the response, which otherwise follows the check data. The SEC code also decides the simulated settlement lag. | WEB |
loopback.traceNumber |
loopbacktracenumber |
Overrides the 15-character NACHA trace number, which is otherwise derived from the transaction id so every leg of one transaction shares it. | 123456780001234 |
loopback.achTraceNumber |
loopbackachtracenumber |
Alias of loopback.traceNumber, read only when that field is absent. | 123456780001234 |
loopback.originatingDfi |
loopbackoriginatingdfi |
Overrides the eight-digit originating DFI, which also forms the leading digits of a derived trace number. | 12345678 |
loopback.effectiveEntryDate |
loopbackeffectiveentrydate |
Overrides the effective entry date, which otherwise follows the 4pm Eastern cutoff and rolls over weekends. | 2026-02-02 |
loopback.settlementDate |
loopbacksettlementdate |
Overrides the settlement date. A returned entry carries none regardless. | 2026-02-04 |
loopback.notProcessed |
loopbacknotprocessed |
Set to true and every loopback profile reports that it did not process the transaction, so authorization failover is attempted and then exhausted. | true |
loopback.notProcessedProfileId |
loopbacknotprocessedprofileid |
A comma-separated list of processor profile ids. Only the listed profiles report that they did not process, so the primary can refuse while the fallback approves. | 9f2c4d18-0f4e-4c8b-9c1a-2f0b7d4e6a31 |
Reading back which trigger fired
Every transaction the sandbox answers comes back with a loopbackSimulation field: one entry for each trigger above that your request fired, and one for each response value the sandbox filled in from a default because nothing matched. Read it when an answer isn't the one you expected and you want to know which trigger the sandbox actually saw.
Entries carry isDefault, and the ones set to true are worth knowing about. A response can come back with an address or card verification result that none of your values asked for, which reads like a second deliberate failure beside the case you meant to test. The flag tells the two apart: false is a trigger you sent, true is a value the sandbox supplied.
Each entry says what the sandbox matched on, the value it matched, and what it did as a result. A card verification entry reports the response code the sandbox returned and never the security code you sent, so nothing you submit on a card comes back in this field.
The field describes a simulation, so it's only on transactions the sandbox answered. Anything a live processor handled returns null for it. Nothing in it changes what the transaction did: the ordinary response fields stay the authority on the outcome, and this explains how the sandbox arrived at them.
Forcing an API error
The triggers above force what a processor does. These force what the API does, which is the half your retry and backoff code is written against. Send the header with one of these values and the call is answered with that failure and nothing else happens: no transaction is saved, no processor is called, and no webhook is sent. The call is still recorded in your API request logs, so you can see exactly what you sent alongside the response you were given.
Send the value as the request header X-WinkPG-Mock-Error. The name in the first column is accepted, and so is the HTTP status on its own and, where the case has one, the error code it returns. Matching ignores case.
Only a test key can force an error. On a live key the header is ignored and the request is processed normally, and a value naming no case below is ignored the same way. Sending the header is never itself an error, so client code that always sets it behaves correctly in production.
The forced 429 carries the same X-RateLimit-Limit and X-RateLimit-Remaining headers the real limiter emits, and both it and the 503 carry Retry-After in whole seconds. Wait that long before you retry. That's the behavior these cases exist to let you prove.
| Send | Status | What comes back | What it exercises |
|---|---|---|---|
validation-error, 400 |
400 | A request rejected by validation, with one failure in validationErrors. | That your client reads validationErrors rather than the envelope message, and that a rejected request is not retried unchanged. |
idempotency-conflict, 409, OPERATION_IDEMPOTENCY_KEY_CONFLICT |
409 | An idempotency key reused for a different operation on the same transaction. | That a conflict is surfaced rather than retried: replaying the same key will keep returning this, and only a fresh key can succeed. |
rate-limited, 429 |
429 | An exhausted allowance, with the same Retry-After and rate-limit headers the real limiter emits. | That your backoff waits for Retry-After rather than retrying immediately, and that the remaining-allowance headers are read on every response and not only on this one. |
server-error, 500 |
500 | A fault with no code to branch on and a deliberately generic message. | That an unsafe operation is reconciled before it is retried. A fault says nothing about whether the work was done, so a blind retry is how a duplicate is created. |
service-unavailable, 503 |
503 | A host that is not taking traffic, with a Retry-After telling you when to come back. | That your client distinguishes 'not now' from 'not ever' and waits the interval it is given instead of failing the whole batch. |
Advancing time in the sandbox
The triggers above force what happens inside one request. These reach the behavior that only happens when time passes, which you would otherwise have to wait out. Each one brings a deadline your merchant already had forward to now, then runs the same evaluation the platform runs on its own schedule, so what comes out is what a scheduled run produces.
These controls are accelerators, not a test clock. Each one moves a single deadline and nothing else, so they don't add up into a simulated future: running billing early doesn't age anything else, and nothing here moves a date backwards or changes a record that already exists.
POST to the route with a test key and no body. The call answers once the work has been done, so whatever it produced is there to look at by the time you get the response. Both the key and the merchant have to be in the sandbox: a live key is refused, and so is a test key whose merchant has been promoted to production.
Everything an accelerator produces is real. The charges go through the payment path, the webhooks are sent to your endpoints, and the records appear in your logs and history exactly as they would have on the original schedule.
| Send | Scope | What moves | What then runs | What you can look at |
|---|---|---|---|---|
POST /api/customers/recurring-billing/sandbox/run-now |
transactions:write |
The next scheduled run on every active contract the merchant owns. | The recurring billing engine, scoped to the calling key's merchant: the same due-contract evaluation, charge execution and notification pass a scheduled run performs. | A real transaction per contract billed, visible in the request log, the webhook delivery log and the merchant's billing history, plus a billing run record. |