The short answer
There is no hidden "best" CVV for Adyen. The CVV on a test card exists so the sandbox can mimic a live terminal. You use the value Adyen publishes next to that card in its test card table, and the sandbox returns the outcome that card is wired for. For the standard Visa test number 4111 1111 1111 1111, that value is 737. If you have a different card, open the table and read the row.
Adyen Test CVV: What the Test Values Are and What They Are Not
Anything else you find floating around forums is either a copy of that table or someone guessing.
Where the numbers come from
Adyen publishes test cards per region, and each card is mapped to a specific result: authorised, refused, error, pending, and so on. The CVV, the expiry, and sometimes the amount all feed into which outcome fires. That is why two people can paste the same card number and get different results. One of them read the row, the other did not.
- Expiry: any future date works in the sandbox.
- Cardholder name: anything, it is not checked.
- CVV: use the published value, three digits for Visa and Mastercard, four for American Express.
- API key: the sandbox key, not the live one. Test cards will not authorise against a live account, and you should not try.
Why a "CVV test" is really a result test
In production the CVV check is the issuer's job. In the sandbox nobody is checking anything. You are choosing an outcome by choosing a card. So when I test CVV handling, I am not testing whether 737 is correct. I am testing whether my code reads the response properly and shows the right message to the customer.
Adyen Test CVV vs Authorize.Net Comparison Review
Pick the card whose listed outcome is the CVV mismatch, send it, and confirm your integration surfaces a clear, non-scary message and does not retry into a loop. Then pick the authorised card and confirm the happy path still works. That is the whole exercise.
Things that trip people up
- Mixing environments. Sandbox keys against live card numbers, or the reverse. Both fail, and the error messages rarely say which mistake you made.
- Four digits on Amex. A three-digit CID on an Amex test card gets rejected before it ever reaches the outcome mapping.
- Hard-coding one card. Teams ship an integration that only ever sees "authorised" and then discover their error handling is empty.
- Assuming the table is static. Adyen updates test cards. Pin a copy in your repo or re-check before each release cycle.
- Storing test data in a shared database. It leaks into dashboards and confuses whoever reads the numbers later.
Reading the result in code
The response carries a result code and, when a payment is refused, a refusal reason. Log both. A test card that returns "refused" with a CVV-related reason is doing its job; the bug is usually downstream, in the branch that decides what the shopper sees next. I look for three states handled cleanly: authorised, refused for the shopper's action, and refused because of your configuration. Only the middle one belongs in front of the customer.
Bottom line
Grab the current test card table from Adyen's developer docs, use the CVV printed beside the card you picked, keep test keys and live keys apart, and write code that handles every outcome in the table. That is as good as test CVV data gets.