Read this before you paste a live API key
- Your request, key included, is relayed through api-tester.com's server. Browsers block a web page from reading another origin's response unless that origin opts in, and Stripe's API does not opt in for arbitrary sites. A browser-based tester therefore has to hand the request to a server and return the result. Ours is that server, so your key passes through our infrastructure on the way to Stripe.
- Keys are not logged or stored by us. The credential signs the outbound request and is then gone; your request history stays in your own browser's local storage and is never uploaded. That is a commitment rather than something you can verify from outside, and you are entitled to treat it accordingly.
-
Use a test-mode key only. A key that starts
sk_test_orrk_test_works on separate test data and cannot touch real payments. A live secret key can refund, pay out and read customer data, and must never be pasted into a third-party tool, this one included. - If you are unsure about a key, rotate it. Deleting a key and creating a replacement takes a minute. Any key you have pasted into a third-party tool and feel uneasy about should simply be replaced.
If none of this sits right for a particular credential, build the request here with the key field empty, press Copy as cURL, and add the key on your own machine. You get the exact request and the secret never leaves your laptop.
How to test a Stripe API key
1. Find your test-mode key
Stripe gives every account separate credentials for testing. In the Dashboard, switch to test mode or a sandbox, open the API keys page under Developers, and reveal the secret key. The prefix tells you what you are holding:
| Prefix | Kind of key | Paste it here? |
|---|---|---|
sk_test_ | Secret key, test mode | Yes |
rk_test_ | Restricted key, test mode | Yes — the best choice |
pk_test_, pk_live_ | Publishable key, for Stripe.js in a browser | It will not authenticate most API calls |
sk_live_, rk_live_ | Live keys with access to real payments | No |
A restricted key is one you create with chosen permissions, for example read-only access to customers and nothing else. It is the right credential for any single-purpose integration, and for experiments like this one.
2. Use the balance endpoint as your probe
The request pre-filled above is a GET to https://api.stripe.com/v1/balance. It
changes nothing and needs no parameters. A standard secret key can always call it; a restricted key
needs read access to Balance, and answers 403 without it.
3. Send the key as a bearer token
The Auth tab is already set to Bearer token; paste the key into the field. Stripe also
accepts HTTP Basic authentication with the key as the username and an empty password, which is what
curl -u sk_test_…: sends. Both reach the same result; the
API key guide shows the forms side by side.
4. Send and read the response
A 200 with an object whose object field is "balance" means the
key works. Check livemode in the body: it should be false. If it is
true, you have pasted a live key; roll it in the Dashboard.
Valid key vs invalid key: what you'll see
GET https://api.stripe.com/v1/balance
Authorization: Bearer sk_test_…
200 OK → { "object": "balance", "livemode": false,
"available": [ { "amount": 0, "currency": "usd", … } ],
"pending": [ { "amount": 0, "currency": "usd", … } ] }
401 → { "error": { "type": "invalid_request_error",
"message": "Invalid API Key provided: sk_test_****…" } }
Amounts are integers in the currency's smallest unit, so 4900 in usd is
$49.00, not $4,900. A few currencies, the Japanese yen among them, have no smaller unit, and there
4900 is ¥4,900. Getting this wrong by a factor of a hundred is the classic first Stripe
bug.
Stripe request bodies are form-encoded, not JSON
Stripe's /v1 endpoints return JSON and do not accept it. A request body must be
application/x-www-form-urlencoded, the format an HTML form submits. Sending JSON is the
most common reason a first POST fails, and the error — a
400 complaining about an unknown parameter — does not make the
cause obvious.
POST https://api.stripe.com/v1/customers Authorization: Bearer sk_test_… Content-Type: application/x-www-form-urlencoded Idempotency-Key: 5f1d0c7e-8a2b-4c39-9d41-1b6e2f3a7c55 email=ada%40example.com&name=Ada+Lovelace&metadata[plan]=trial
Nested objects use square brackets — metadata[plan]=trial — and arrays use an index or
empty brackets, as in expand[]=customer. Values must be percent-encoded: the
@ in an email address becomes %40, and the
URL encoder will do it for you. To run this in the console, set the
method to POST, add the Content-Type header in the Headers tab, and put the
line of fields in the Body tab. The curl form POST example gives the
command-line equivalent.
Idempotency keys
A POST that times out leaves you not knowing whether the customer or the charge was
created. Stripe solves this with the Idempotency-Key header: send a unique value, such as
a UUID, and repeat the same value when you retry. Stripe
returns the saved result of the first attempt instead of acting twice. Reusing a key with different
parameters is an error. The idempotency guide explains the pattern,
which Stripe did much to popularise.
Reading Stripe errors
Stripe's error object is more specific than most, and using all of it saves time.
| Field | Tells you |
|---|---|
type | The category: invalid_request_error, card_error, idempotency_error or api_error |
code | The specific reason, such as resource_missing or parameter_unknown |
param | Which parameter was at fault |
decline_code | For card errors, the issuer's reason, such as insufficient_funds |
message | A sentence for developers. For card errors it is safe to show to the customer |
doc_url | A link to the documentation for that code |
| Status | Meaning on this API |
|---|---|
| 400 | A required parameter is missing or a value is invalid |
| 401 | No valid API key was provided |
| 402 | The parameters were valid and the request failed, most often a declined card |
| 403 | The key lacks permission — the usual result of a restricted key doing its job |
| 404 | The object does not exist, or exists in the other mode |
| 409 | The request conflicts with another, often a reused idempotency key |
| 429 | Too many requests too quickly; back off exponentially |
| 5xx | A fault on Stripe's side. Retry with the same idempotency key |
The 404 row hides a frequent confusion. Test mode and live mode
hold entirely separate objects. A customer ID created with a live key does not exist as far as a test
key is concerned, so asking for it returns resource_missing — and the message says which
mode the object was found in when Stripe can tell.
Stripe test cards
In test mode no real card is ever charged. Stripe publishes card numbers that simulate particular outcomes; use any future expiry date and any three-digit security code with them.
| Card number | Result | Test payment method |
|---|---|---|
4242 4242 4242 4242 | Payment succeeds | pm_card_visa |
4000 0000 0000 0002 | Declined, generic decline | pm_card_chargeDeclined |
4000 0000 0000 9995 | Declined, insufficient funds | pm_card_chargeDeclinedInsufficientFunds |
4000 0025 0000 3155 | Requires 3D Secure authentication | pm_card_authenticationRequired |
The numbers are for typing into a payment form built with Stripe's own Elements or Checkout. When you
call the API directly, as from this console, do not send card numbers at all: Stripe blocks raw card
data on most accounts, for compliance reasons. Pass the matching test payment method instead, for
example payment_method=pm_card_visa when creating a PaymentIntent. Stripe's testing
documentation lists many more cards, by brand, country and failure type.
From API calls to webhooks
Most Stripe integrations are half requests and half events: you create a payment with the API, and
Stripe tells you the outcome with a webhook. The /v1/events endpoint in the list beside the
console returns the same event objects a webhook delivers, which makes it a convenient way to look at a
real payload. The Stripe webhook example shows the
headers and how the Stripe-Signature value is checked, and the
webhook tester gives you a temporary URL to receive one.
Provider APIs change — check the official docs
api-tester.com is an independent tool with no affiliation to, partnership with or endorsement from Stripe. Nothing here is official documentation. Endpoints, model names, error wording and limits are the provider's to change, and this page can fall behind. For current and authoritative detail, consult the official Stripe API reference.
Stripe versions its API by date, and behaviour depends on the version your account or your Stripe-Version header selects. The test card numbers above are the long-standing ones from Stripe's testing documentation; confirm them there before building a test suite on them.
Test other providers and related tools
Stripe Webhook Example
The payload, headers and signature check for a Stripe event.
Webhook Tester
A temporary URL that shows every request sent to it.
API Key Tester
A generic checker for any API key, whatever the authentication scheme.
Idempotency
Why a retried POST can charge twice, and how keys prevent it.
URL Encoder
Percent-encode values for a form-encoded body.
PayPal Webhook Example
How another payment provider signs and delivers events.
Frequently asked questions
How do I test whether my Stripe API key is valid?
Send a GET request to https://api.stripe.com/v1/balance with the key in an Authorization header using the Bearer scheme. A valid key returns 200 and a balance object. An invalid one returns 401 with an error message that quotes a redacted form of the key.
What is the difference between sk_test and sk_live keys?
A key starting sk_test_ works on test data: no real money moves and no real cards are charged. A key starting sk_live_ acts on real payments and customers. The two modes share endpoints and keep completely separate objects.
Why does Stripe reject my JSON request body?
Because the v1 API accepts only form-encoded bodies. Send Content-Type: application/x-www-form-urlencoded and write the parameters as name=value pairs joined with ampersands, using square brackets for nested fields. Responses are JSON.
What is the Stripe test card number?
4242 4242 4242 4242 is the standard test Visa that always succeeds, with any future expiry date and any three-digit CVC. Other numbers simulate declines and authentication. They work only in test mode.
Is it safe to paste my Stripe key here?
Only a test-mode key. The request is relayed through api-tester.com's server, so the key transits our infrastructure on the way to Stripe. We do not log or store keys, but a live secret key should never be given to any third-party tool. To keep even a test key local, build the request here without it, copy it as cURL and add the key on your own machine.
Is this tool affiliated with Stripe?
No. api-tester.com is an independent HTTP request console with no affiliation to, partnership with or endorsement from Stripe. Check the official Stripe documentation for current endpoints and behaviour.