This is a comprehensive guide for testing Flute payment integrations. It covers using test credit and debit cards, error conditions, edge cases, load testing, and automated testing best practices.
The Flute sandbox is a fully isolated environment that mirrors production behavior without processing real transactions. Use it to validate your integration before going live.
All examples in this guide use the sandbox base URL: https://sandbox.api.flute.com
Before running tests, ensure you have:
- A sandbox merchant account provided by Flute. See Creating a Flute Sandbox Account.
- A sandbox API key that includes the clientId and client secret. See Creating an API Key.
- An API token generated from your sandbox environment credentials. See API Tokens.
The sandbox supports two simulation modes depending on how the card is presented.
Card Not Present (CNP): The result is determined by the card number submitted. Use the test PANs listed in the tables below.
Card Present (CP): Because the PAN rides inside track or EMV data that the sandbox does not parse, the result is determined by the transaction amount instead. Use any card and set the amount to one of the values in the tables below. Applies to Swipe, EMV, NFC, EMVContactless, and FallbackSwipe data sources. Manual keyed entry is treated as CNP.
For CNP, use the card below. Any card number not listed in the Decline or Processor Error tables is also approved.
| CNP card number | CP amount | Result |
|---|---|---|
| Any PAN not listed in specific scenarios. Use any future expiration date and any valid CVV code. PAN example: 4111 1111 1111 1111 | Any amount not listed in specific scenarios. Amounts above $5.00 will always get approved. Example: $12.45 | Approved |
Use any future expiration date and any numeric value for the CVV.
Use the CNP card number or the CP amount to trigger a specific issuer decline.
| Result | CNP card number | CP amount |
|---|---|---|
| Decline - Do not honor | 4000 0000 1005 0005 | $1.05 |
| Decline - Insufficient funds | 4000 0000 1051 0008 | $1.51 |
| Decline - Invalid card number | 4000 0000 1014 0004 | $1.14 |
| Decline - Expired card | 4000 0000 1054 0005 | $1.54 |
| Decline - Pickup card (lost) | 4000 0000 1004 0006 | $1.04 |
| Decline - Stolen card | 4000 0000 1043 0009 | $1.43 |
| Decline - Card restricted | 4000 0000 1062 0005 | $1.62 |
| Decline - Transaction not permitted | 4000 0000 1057 0002 | $1.57 |
| Decline - CVV mismatch | 4000 0000 1099 0002 | N/A |
Use the CNP card number or the CP amount to trigger a specific processor error.
| Result | CNP card number | CP amount |
|---|---|---|
| Error - Timeout / no response | 4000 0000 2091 0008 | $2.91 |
| Error - System error | 4000 0000 2096 0003 | $2.96 |
| Decline - Referral required | 4000 0000 2001 0007 | $2.01 |
| Error - Re-enter transaction | 4000 0000 2019 0007 | $2.19 |
The sandbox can simulate a partial approval, where the issuer approves only a portion of the requested amount. This scenario is only available for CP transactions.
| CP amount | Result |
|---|---|
| $4.01 | Approves exactly $2.00 regardless of the requested amount |
Use any of these PANs (primary account numbers) to replicate using a Level 3 commercial card.
| Card number | Result |
|---|---|
| 4000 0000 3001 0005 | Approved as a Visa Level 3 commercial card - exercises the Level 3 processing path in the platform. |
Use any of these addresses to replicate an AVS (address verification system) check.
The sandbox decides the AVS result from the billing street and zip on the request. The AVS check itself always succeeds. Any values or value pairings not listed here is returned as verified.
| Street | Postal code | AVS result |
|---|---|---|
| 123 Test St | 10001 | Full match |
| any other street | 10001 | Partial match - postal code only |
| 123 Test St | any other postal code | Partial match - street only |
| any other street | any other postal code | No match |
| any | 10005 | Unavailable |
| any | 10009 | Incompatible. Whether the transaction is then accepted depends on the merchant's AVS policy. |
The sandbox allows testing transactions during app development. This includes being able to replicate specified errors and incomplete transactions.
The following list are test account numbers to simulate specific transaction outcomes in the sandbox environment. Each account number is mapped to a predefined response. This allows you to validate error handling, status transitions, and business logic. Submit a transaction using one of the values below to reproduce an outcome you want to test.
For testing ACH transactions, the following cases apply:
- Verify account (Positive / Negative / Error)
- Payment (debit or credit)
- Refund a cleared payment
- Void a payment before being submitted
- Hold a scheduled payment and remove the hold to release it
- Lifecycle statuses. The sandbox reduces the time required to change or advance the status of an ACH transaction.
Real-world ACH processing is asynchronous and takes up to three business days to clear, updating statuses up to four times a day. To help with testing, sandbox lifecycle status changes are shortened.
The ACH sandbox triggers status changes automatically every 15 minutes. This compresses the end-to-end testing window to approximately one hour.
A typical approved payment progresses through: Scheduled → In Progress → Cleared
A declined payment progresses through: Scheduled → Declined
Use the following routing and account number to simulate a successful ACH transaction. Any routing and account number combination not listed in the Decline Scenarios table below is also approved.
| Routing | Account | Result |
|---|---|---|
| 900000000 | 900000000 | Approved |
The sandbox triggers ACH return codes when the routing and account number pairings match from the list below.
"Soft returns" describe the state of the transaction, not the account. For example, Verify Account still reports the account as usable. However, an actual payment with that same routing and account values is declined with the appropriate R-code.
| Routing | Account | Return code | Verify Account result |
|---|---|---|---|
| 110000000 | 900000101 | R01 — Insufficient funds | Positive (soft return) |
| 110000000 | 900000102 | R02 — Account closed | Negative |
| 110000000 | 900000103 | R03 — No account / unable to locate | Negative |
| 110000000 | 900000104 | R04 — Invalid account number | Negative |
| 110000000 | 900000107 | R07 — Authorization revoked | Negative |
| 110000000 | 900000108 | R08 — Payment stopped | Positive (soft return) |
| 110000000 | 900000109 | R09 — Uncollected funds | Positive (soft return) |
| 110000000 | 900000110 | R10 — Customer advises unauthorized | Negative |
| 110000000 | 900000116 | R16 — Account frozen | Negative |
| 110000000 | 900000120 | R20 — Non-transaction account | Negative |
Once an ACH payment is approved, the routing and account numbers also decide the path it will take through its lifecycle.
| Routing | Account | Condition | ACH Transaction Lifecycle |
|---|---|---|---|
| 110000000 | 900000200 | Held by processor | Scheduled → In Progress → Held by Processor |
| 110000000 | 900000300 | Charged back | Scheduled → In Progress → Cleared → Charged Back |
Hold / Remove Hold / Void / Refund only apply in the right state. If you try them at the wrong moment, the sandbox declines with an explanatory message. You can also test the unhappy paths:
- Void requires status Scheduled
- Hold requires status Scheduled
- Remove Hold requires status Held
- Refund requires the parent transaction to be Cleared
Test each error type to ensure your integration handles failures gracefully and communicates clearly with end users.
| HTTP Status | Error Code | Common Cause | Handling Recommendation |
|---|---|---|---|
| 400 | VALIDATION_ERROR | Missing or malformed request field | Display field-level validation messages to the user |
| 401 | UNAUTHORIZED | Missing, expired, or invalid API token | Refresh the API token and retry the request once |
| 403 | FORBIDDEN | API token lacks required permission | Check API key permissions in the merchant dashboard |
| 404 | NOT_FOUND | Resource does not exist or belongs to another merchant | Verify the resource ID and merchant scope |
| 429 | RATE_LIMITED | Too many requests in a short period | Implement exponential backoff with jitter |
| 500 | INTERNAL_ERROR | Unexpected server error | Retry with exponential backoff; alert if persistent |
| 503 | SERVICE_UNAVAILABLE | Flute service temporarily unavailable | Retry after a delay; do not retry immediately |
A duplicate transaction is a transaction that appears to have been submitted more than once for the same payment event. To help prevent this, Flute uses duplicate controls. This is a configurable feature, called duplicate controls, that helps prevent duplicate transactions that may lead to double-charging customers. It is available at the merchant account level.
When enabled, duplicate controls automatically validate incoming payment transactions. It uses customizable criteria to check for possible duplicates. The duplicate controls configuration can be enabled and customized in the Merchant account dashboard.
When a new payment transaction is received, duplicate controls compare it against other, recent transactions from the same merchant. If a transaction with matching details is found within a specified validation period, the system flags it. It is marked as a duplicate and prevents it from being processed again.
A transaction marked as a duplicate returns an HTTP response of 400 and a V0000 validation error (ValidationException).
A transaction is considered a duplicate if all the following fields match against a recent transaction:
- Operator ID, such as API client ID, terminal ID, user ID
- Merchant ID
- Amount
- Operation type (Auth or Sale)
- Card number (the last four digits)
- Reference ID (if provided)
The duplicate check applies within a configurable validation period (default: 10 minutes).
If the new transaction is legitimate, the merchant can either:
- Wait for the validation period and resubmit it, or
- Set a different reference ID and resend the transaction immediately. The new reference ID prevents the transaction from being flagged as a duplicate.
Coordinate with Flute before running load tests against the sandbox environment. High traffic against the shared sandbox infrastructure can affect other merchants using the same environment. Contact developer@flute.com to schedule a load test window.
Focus your load tests on the endpoints your integration uses most heavily. For each endpoint, measure:
| Metric | Acceptable Target | Notes |
|---|---|---|
| P95 latency | < 2 seconds | For API token creation and payment session endpoints |
| P99 latency | < 5 seconds | Under sustained load |
| Error rate | < 0.1% | Excluding intentional decline scenarios |
| Throughput | Match expected peak TPS | Ramp up gradually — do not start at peak |
| API token refresh success rate | 100% | API tokens must never silently fail to refresh |