Read this before you paste a live API key
This matters more than anything else on the page, so it is not hidden in a footer or softened into marketing language:
- Your request, including the API key, is sent through api-tester.com's server. A web page cannot call the OpenAI API directly, because browsers enforce the same-origin policy and the API does not hand out permissive CORS headers to arbitrary websites. The only way a browser tool can make this request work is to forward it through a server that is not bound by CORS. That server is ours, so the key travels through our infrastructure on its way to OpenAI.
- We do not log or store keys. Credentials are used to sign the outbound request and are then discarded. Your request history lives in your own browser's local storage and never leaves your device. But "we don't keep it" is a promise, not a technical guarantee you can verify from where you're sitting, and you should weigh it as such.
- Prefer a test or restricted key. If your account supports scoping a key to a specific project or restricting its permissions, use one of those here rather than an organisation-wide key with full access. The test is the same either way; the blast radius is not.
- Rotate anything you are unsure about. Revoking a key and issuing a new one takes under a minute. If you have already pasted a production key into any third-party tool — this one included — and it nags at you, rotate it. That instinct is correct.
If a credential is sensitive enough that none of the above is acceptable, run the request from your own
machine with curl instead. Build it here without a key, press Copy as cURL,
and fill the key in locally. You still get the request shape; the secret never leaves your laptop.
How to test an OpenAI API key
The fastest reliable check is a read-only request that requires authentication but does no work and generates no output. Listing models fits perfectly: it tells you whether the credential is accepted, and as a bonus it tells you which model identifiers your account can actually reference — which is useful, because model availability differs between accounts and changes over time.
1. Get a key
Sign in to the OpenAI developer platform and create a key from the API keys area of your account
settings. The key is displayed exactly once at creation. If you did not copy it then, you cannot recover
it later — create a new one and revoke the old. Keys are conventionally prefixed with
sk-, and keys scoped to a project carry a longer prefix.
2. Set the request
The method is GET and the URL is https://api.openai.com/v1/models, both
already filled in above. There is no request body — a GET carries none, and the tool ignores the Body
tab for GET and HEAD requests.
3. Set the authentication
Open the Auth tab, which is already set to Bearer token, and paste
your key into the field. The tool assembles the header for you as
Authorization: Bearer <your key>. Getting this exactly right by hand is the single
most common failure: the word Bearer, one space, then the key, with no quotes and no
trailing newline. If you would rather build the header yourself, the
HTTP headers reference covers the syntax of the
Authorization header in general.
4. Send, and read the status code first
A 200 with a JSON object containing a list of model entries means the key is valid and
the account is in good standing. Anything else is diagnostic, and the next section covers what each
code is telling you.
Valid key vs invalid key: what you'll actually see
A successful call to the models endpoint returns a JSON object whose data field is an
array of objects, each describing one model your key can use. You do not need to read the whole thing
— the presence of a populated array is the answer. Note the identifiers, though, since those are the
exact strings you'll pass as model in later requests.
A rejected key returns a JSON object with an error field containing a human-readable
message plus machine-readable type and code fields. That shape
is consistent across OpenAI API errors, so once you can read one you can read all of them. The
message is usually blunt about the cause; read it before theorising.
GET https://api.openai.com/v1/models
Authorization: Bearer sk-…
200 OK → { "object": "list", "data": [ { "id": "…", … }, … ] }
401 → { "error": { "message": "…", "type": "…", "code": "…" } }
Field names above are stable, but exact messages and codes vary. Treat the status code as the authoritative signal and the body as the explanation.
Reading 401, 403 and 429 from the OpenAI API
Three status codes account for nearly every failed request against a large-model API, and confusing them wastes a lot of time. They mean genuinely different things.
401 — the credential was not accepted
The server did not recognise the key at all. In practice this is almost always mechanical rather than
mysterious: a truncated paste, a stray space or newline inside the key, the word Bearer
missing, quotation marks copied along with the value, an environment variable that resolved to an
empty string, or a key that has since been revoked. If you are testing from code rather than here, log
the length of the key you're sending — not the key — and compare it with the real one. A length
mismatch finds the bug immediately. See 401 Unauthorized for the
general semantics.
403 — the credential is fine, the action is not
A 403 means you authenticated successfully but are not permitted to do this specific thing. That points at scope rather than validity: a key restricted to a project that does not have access to the resource you asked for, an account-level or regional restriction, or an endpoint your account is not enabled for. The fix is never "check the key is correct" — it already is. Read 403 Forbidden for why this distinction exists in HTTP.
429 — slow down, or you have nothing left to spend
This one is genuinely ambiguous on its face, because the OpenAI API uses 429 both for "you are sending requests faster than your account is allowed to" and for "this account has no available quota." The response body disambiguates them, and the difference determines your response: the first is solved by backing off and retrying with exponential delay, the second is solved by fixing billing and will never succeed no matter how long you wait. Retrying a quota error in a loop is a classic way to turn a small problem into a noisy one. Our 429 Too Many Requests page covers backoff strategy and the response headers worth honouring.
Other codes worth recognising
A 400 generally means your JSON was malformed or a parameter was invalid — a misspelled
field, a model identifier that does not exist for your account, or a value outside the allowed range.
A 404 on a path you expected to work usually means a typo in the URL or a model
identifier embedded in the path that no longer exists. Codes in the 5xx range are the
provider's problem, not yours, and are the correct case for a retry with backoff.
Testing a chat request instead of a key check
Once the key is confirmed, the next question is usually whether an actual generation request works.
That is a POST to the chat completions endpoint at
https://api.openai.com/v1/chat/completions, with the same
Authorization header, Content-Type: application/json, and a JSON body
naming a model and a list of messages.
POST https://api.openai.com/v1/chat/completions
Authorization: Bearer sk-…
Content-Type: application/json
{
"model": "PUT-A-MODEL-ID-FROM-/v1/models-HERE",
"messages": [ { "role": "user", "content": "Say hello." } ]
}
The placeholder is deliberate. Model identifiers are added and retired regularly, and a page that
hard-codes one becomes wrong without warning — so take the value from your own
/v1/models response, which is authoritative for your account at this moment. To send this
here: switch the method to POST, change the URL, open the Body tab,
paste the JSON, and use Format JSON to check it parses before sending. Unlike the
models check, this request does real work and consumes quota.
Note that a streaming request is not useful in this tool: streamed responses arrive as a sequence of server-sent events, and the console renders a completed response body. Leave streaming off here.
Common integration problems this tool isolates
The real value of a standalone request console is that it cuts your application out of the picture. When a call fails inside your own code, the fault could be the key, the endpoint, the payload, your HTTP client, your framework's header handling, a proxy in front of you, or your own logic. Reproducing the identical request here answers one question definitively: does it work outside my app?
- It works here but not in my app. The credential and the endpoint are fine, so the problem is in your code — most often a header that is not being set the way you think, or an environment variable that is empty in the environment that is actually failing.
- It fails here too. Then it is the key, the URL or the payload, and you have narrowed it to something you can see in one screen.
- It works locally but not in production. Different key, different project, different egress IP, or a restriction that only applies to one of the two. Compare the two environments field by field.
- Intermittent failures. Check for 429s specifically. Concurrency that is fine at low traffic starts tripping limits under load, and the symptom often reads as a random error rather than a rate limit unless you are logging status codes.
If your application layers its own token on top — say, a JWT your backend issues to your frontend, separate from the provider key — the JWT decoder will show you its claims and expiry, which is the usual culprit when auth works for a while and then stops.
Provider APIs change — check the official docs
This is an independent guide. api-tester.com is not affiliated with, partnered with or endorsed by OpenAI, and nothing here is official documentation. Endpoints, parameters, model identifiers, error codes and limits are all subject to change by the provider at any time, and this page may lag behind. For current and authoritative details, always consult the official OpenAI API documentation.
We have deliberately avoided quoting prices, specific rate limits or particular model names on this page. Those are exactly the details that go stale fastest, and a confidently stated wrong number is worse than no number at all. What is described here is the durable shape of the API: the authentication scheme, the error format, and how to interpret the status codes.
Test other providers and related tools
Gemini API Tester
Validate a Google Gemini API key and learn why a bad key returns 400 rather than 401.
Anthropic API Tester
Test a Claude API key, including the version header the API requires.
API Key Tester
A generic checker for any API key, whatever the authentication scheme.
Postman Alternative
Where a browser console fits and where an installed API client is the better tool.
JWT Decoder
Decode a bearer token and check its claims and expiry when authentication fails.
HTTP Headers
How Authorization, Content-Type and rate-limit headers actually work.
Frequently asked questions
How do I test whether my OpenAI API key is valid?
Send an authenticated GET request to https://api.openai.com/v1/models with your key in
an Authorization header using the Bearer scheme. A valid key returns 200 and a JSON object
listing the models your account can use. An invalid or revoked key returns 401 with a JSON error object
instead. The tool at the top of this page is pre-filled for exactly that request.
Does my API key pass through your server?
Yes, and we would rather say so plainly. Browsers block cross-origin reads, so the request is forwarded through api-tester.com's server to bypass CORS — which means your key transits our infrastructure on the way to the provider. We do not log or store keys, but you should prefer a test or restricted key over a production key with full permissions, and rotate any key you are unsure about. To keep the secret entirely local, build the request here without a key, copy it as cURL and add the key on your own machine.
What does a 401 from the OpenAI API mean?
Authentication failed. The Authorization header was missing, malformed, or carried a
key the server does not recognise. In practice: a typo, a truncated paste, a missing
Bearer prefix, whitespace inside the value, or a revoked key.
Why am I getting 429 when I've barely sent any requests?
Because 429 covers two different situations on this API: being throttled, and having no available quota. The second is not a traffic problem at all and will not resolve by waiting. Read the error body to tell them apart — retrying a quota error with backoff simply fails more slowly.
Can I test a streaming completion here?
Not usefully. Streaming responses arrive as a sequence of server-sent events over a long-lived connection, while this console renders one completed response body. Leave streaming disabled for tests here, then enable it in your own client.
Is this tool affiliated with OpenAI?
No. api-tester.com is an independent HTTP request console with no affiliation to, partnership with or endorsement from OpenAI. Check the official OpenAI documentation for current endpoints and behaviour.