Developers › Get started
Test cards
sk_test_. Nothing here moves real money.A test payment ends on one of two pages. If it has buttons saying what should happen, press one: there is no card to enter. If it asks for a card, use a number from the second table.
| Button | What happens |
|---|---|
| The payment works | Succeeds |
| It works, and the money is ready at once | Succeeds, and skips the wait before it can be paid out |
| Declined: not enough money | Fails, with decline_code insufficient_funds |
| Declined: the customer’s bank says no | Fails, with decline_code generic_decline |
| The customer leaves without paying | Expires, with no decline_code |
| The customer’s bank asks them to confirm | Waits at requires_action, then they confirm, fail or give up |
| It works, then the customer disputes it | Succeeds, then opens a test dispute. Answer it from your dashboard: evidence containing losing_evidence loses, any other evidence wins, and no answer by the deadline loses |
| Number | Expiry | CVC | What happens |
|---|---|---|---|
5555555555555599 | 12/34 | 123 | Succeeds |
4111111111111111 | 12/26 | 123 | Succeeds |
5168494895055780 | 12/26 | 123 | Declined |
123 for all of them. If the bank’s page does something other than what the table says, tell us and quote the payment’s id.What a decline looks like
The customer is shown “The payment did not go through” on our result page, with a button to try another card — they are not sent to your cancel_url. The payment goes back to requires_payment_method and carries a last_payment_error with a decline_code, and you get payment_intent.payment_failed. The checkout session stays open, so they can try another card without you creating anything new.
Leaving the bank’s page without paying is not a decline. The bank expires the page about twenty minutes at most after it opened — sooner if the checkout session had less time left than that — and the payment goes back to requires_payment_method with last_payment_error.code payment_intent_payment_attempt_expired and no decline_code.
Which decline_code the decline card in the second table produces is up to the bank’s sandbox, and we have not pinned it down; do not build a test that expects a particular one from it. A reason we cannot map arrives as generic_decline. The raw code the bank sent is on the payment at gateway.action_code, for support — branch on decline_code, never on that.
What authentication looks like
The payment sits at requires_action while the cardholder’s bank asks them to confirm. It is not a failure and it is not finished — wait for the webhook rather than reading the status once and deciding. To see it on purpose, press “The customer’s bank asks them to confirm”. The bank does not document a test card that always asks for authentication, so a page that asks for a card may or may not show you this step; your integration should handle it either way.
Running the same test twice
Our default risk rules apply in test mode too, and one of them refuses a payment after five attempts from the same email address within an hour. If you re-run a test with a fixed receipt_email or customer_email, the sixth press of Pay by card in an hour is refused — and so is every press after it, because a refusal counts as an attempt too. Use a fresh address per run, leave the email off, or add your test address to your allow list in test mode. The risk page says exactly what is counted.