On this page
- Quick reference
- 401 Unauthorized: authentication failed
- A good 401 debugging sequence
- 401 can also be a custom-endpoint problem
- 403 Forbidden: authenticated, but not allowed
- Model access is a common source of 403 errors
- 429 Too Many Requests: not always “too fast”
- Rate limit vs quota vs capacity
- Rate limit
- Quota
- Capacity throttling
- How to retry 429 correctly
- 400 Bad Request: the request itself is wrong
- 404 Not Found: endpoint or model mismatch
- 500, 502, and 503: likely server-side
- A practical decision tree
- The exact error body is often more useful than the status code
- What to record when debugging
- A better debugging order for BYOK clients
- Example: why changing the key can waste time
- Example: why retrying can be dangerous with tools
- Preventing errors before they happen
- The practical takeaway
When an AI API request fails, the HTTP status code is often the fastest clue to the real problem.
Three codes cause a large share of BYOK connection failures: 401, 403, and 429. They may all appear to the user as “the request failed,” but they usually point to different layers of the system.
The useful mental model is:
401 → authentication
403 → authorization
429 → rate, quota, or capacity
That is only the starting point. The response body, endpoint, provider account, and request details still matter.
Quick reference
| Code | Usually means | First thing to check | Retrying immediately? |
|---|---|---|---|
| 401 | Credentials were not accepted | API key and auth header | Usually no |
| 403 | Identity is known but operation is blocked | permissions and account/model access | Usually no |
| 429 | A usage or capacity limit was hit | rate limit, quota, credits, spending limit | Sometimes |
| 400 | Request itself is invalid | payload and unsupported parameters | No |
| 404 | Endpoint/model/resource not found | base URL and model identifier | No |
| 5xx | Server or gateway failed | provider health and transient failure | Often reasonable |
If you only remember one debugging rule, remember this: do not rotate keys, change models, and retry repeatedly before identifying which layer failed.
401 Unauthorized: authentication failed
A 401 generally means the server did not accept the credentials attached to the request.
Typical causes include:
- no API key was sent;
- the key was copied incompletely;
- the key was revoked or rotated;
- the key belongs to a different provider;
- the authentication header is malformed;
- the endpoint expects a different authentication scheme;
- leading or trailing whitespace was stored with the key;
- the request is going to the wrong host.
A common BYOK mistake is pairing a valid key with the wrong base URL.
For example:
Key: valid key for Provider A
Base URL: Provider B endpoint
Result: authentication failure
Creating another Provider A key will not fix that configuration.
A good 401 debugging sequence
- Confirm the final hostname and base URL.
- Confirm the selected provider/connection in the client.
- Re-copy the credential from the provider dashboard.
- Check for whitespace or accidental quotes.
- Verify the endpoint’s expected auth header.
- Confirm the key has not been revoked.
- Try the smallest possible request.
Do not paste the real key into screenshots, issue reports, analytics, or public logs while debugging.
401 can also be a custom-endpoint problem
With an OpenAI-compatible API, authentication may not behave exactly like a first-party provider.
A local server may:
- require no key;
- accept a placeholder key;
- require a real server-defined token;
- sit behind a reverse proxy that handles authentication;
- require an additional custom header.
That is why “my API key works elsewhere” is not enough evidence. The credential must be valid for the exact endpoint receiving the request.
403 Forbidden: authenticated, but not allowed
A 403 usually means the service recognized the request’s identity but refuses the requested operation.
Possible reasons include:
- the account cannot access the selected model;
- the API is disabled for that project;
- the key has restrictions that exclude the requested service;
- an organization policy blocks the operation;
- the feature requires a different account tier;
- regional or compliance policy blocks access;
- the project or organization association is wrong;
- the provider suspended or restricted the account.
The conceptual difference is useful:
401: I cannot authenticate you.
403: I know who you are, but you cannot do this.
That immediately changes what you should investigate.
With a 403, creating a new key under the same restricted account may reproduce the exact same failure.
Model access is a common source of 403 errors
An account can be valid while one model is unavailable to it.
If Model A succeeds and Model B returns 403 with the same connection, the credential itself is probably not the first thing to blame. Check model access, project policy, and account eligibility.
Similarly, a request may work for plain chat while failing for a protected feature such as file processing, tools, or another API surface.
429 Too Many Requests: not always “too fast”
A 429 is commonly called a rate-limit error, but in AI APIs it can represent several different resource limits.
Examples include:
- requests per minute;
- input tokens per minute;
- output or total tokens per minute;
- concurrent requests;
- daily quota;
- monthly quota;
- account credits;
- spending caps;
- temporary service capacity.
This is why the response body matters.
These two failures can both use 429 but need completely different responses:
Case A:
Too many requests in a short period
→ slow down and retry later
Case B:
Monthly credit or account quota exhausted
→ waiting 30 seconds changes nothing
Blind retries are appropriate for Case A and wasteful for Case B.
Rate limit vs quota vs capacity
These terms are often mixed together.
Rate limit
A rate limit controls how quickly you can consume the API.
Examples:
- 60 requests per minute;
- 100,000 tokens per minute;
- 4 concurrent generations.
Once enough time passes, capacity becomes available again.
Quota
A quota controls how much you may consume over a larger period or allocation.
Examples:
- daily request allowance;
- project quota;
- prepaid credits;
- monthly usage allocation.
A short retry delay may not help.
Capacity throttling
Sometimes the account is healthy but the provider is temporarily unable to serve the requested traffic at the expected rate.
This behaves more like a transient operational condition. Retrying with backoff may succeed.
How to retry 429 correctly
For transient rate limits, clients should prefer provider-supplied retry information when available.
A reasonable strategy is usually:
- respect explicit retry timing if returned;
- otherwise wait before trying again;
- increase the delay after repeated failures;
- add small random jitter so many clients do not retry simultaneously;
- stop after a sensible number of attempts;
- show the user what is happening.
What a client should not do is instantly replay the same request in a tight loop.
That can:
- keep the account rate-limited;
- waste quota;
- create duplicate generations;
- produce duplicate tool actions;
- make a provider outage noisier.
For tool-enabled conversations, retry behavior deserves extra caution because a model round may have already caused an external action before the visible request failed.
400 Bad Request: the request itself is wrong
A 400 usually means the server understood where the request was sent but rejected the payload.
Common causes include:
- unsupported parameter;
- malformed message structure;
- invalid JSON;
- context or input too large;
- invalid tool schema;
- unsupported image/file format;
- structured-output schema rejected;
- feature not supported by that model.
When 400 appears after switching models, compare model capabilities before changing authentication.
A model that supports plain text may not support tools, images, or the same generation parameters as another model.
404 Not Found: endpoint or model mismatch
A 404 is especially common with custom endpoints.
It can mean:
- the URL path is wrong;
/v1is missing or duplicated;- the server implements a different API route;
- the requested model identifier does not exist;
- the client is calling an endpoint the server does not implement.
For example:
Configured base: https://host.example/v1
Client appends: /v1/chat/completions
Final request: https://host.example/v1/v1/chat/completions
The key can be perfectly valid and the result will still fail.
500, 502, and 503: likely server-side
A 5xx response usually indicates the provider, reverse proxy, gateway, or upstream service could not complete a request it otherwise accepted.
Common situations include:
- provider outage;
- overloaded server;
- gateway timeout;
- upstream model process crashed;
- local inference server ran out of memory;
- reverse proxy lost connection to the model backend.
If the exact request worked moments ago and no configuration changed, a transient retry may be reasonable.
If a local server returns 500 repeatedly, inspect the server logs rather than rotating the client credential.
A practical decision tree
Use the status code to choose the next question:
Request failed
│
├─ 401 → Is the credential valid for this exact endpoint?
│
├─ 403 → Does this account/project have permission for this model or feature?
│
├─ 404 → Is the base URL/path/model identifier correct?
│
├─ 429 → Is this temporary rate pressure or exhausted quota/credits?
│
├─ 400 → Is the request or selected feature unsupported?
│
└─ 5xx → Is the provider/server unhealthy or overloaded?
This is much faster than changing unrelated settings randomly.
The exact error body is often more useful than the status code
HTTP status codes are broad categories. Providers frequently include a structured error payload with a more specific code or message.
A useful client should preserve information such as:
HTTP status: 429
Provider: ExampleAI
Model: example-model
Provider code: rate_limit_exceeded
Detail: token limit exceeded for current project
That is far more actionable than:
Something went wrong.
Friendly UI and technical detail do not have to be opposites. A client can summarize the likely problem while still exposing the provider’s diagnostic information.
What to record when debugging
You usually do not need to record the user’s prompt or API key to troubleshoot an API failure.
Useful diagnostic fields include:
- timestamp;
- provider/connection name;
- hostname or endpoint label;
- model identifier;
- HTTP status;
- provider error code;
- request ID returned by the provider;
- whether streaming was enabled;
- retry count;
- duration before failure.
Avoid putting secrets, full authorization headers, or sensitive prompt contents into logs.
This matters especially in BYOK software because the provider credential belongs to the user.
A better debugging order for BYOK clients
When a request fails, check the layers in this order:
- Network — can the device reach the endpoint?
- Endpoint — is the base URL and path correct?
- Credential — is authentication valid for this endpoint?
- Permission — may the account use this model or feature?
- Model — is the model identifier valid and available?
- Quota — are rate limits, credits, budgets, or concurrency exhausted?
- Request — are the parameters and input supported?
- Provider/server health — is the service currently failing?
For local servers, add firewall, machine sleep, and server binding to the network checks. For cloud providers, account status and billing are more likely to matter.
Example: why changing the key can waste time
Imagine this sequence:
1. Client sends request.
2. Provider returns 429 quota exhausted.
3. User assumes the key is broken.
4. User creates a new key under the same account.
5. New key uses the same exhausted quota.
6. Request still returns 429.
Nothing was wrong with either key.
The status category already told you to investigate usage limits rather than authentication.
Example: why retrying can be dangerous with tools
Suppose a model requests a tool that creates an external issue, sends a message, or modifies a file.
If the tool succeeds but a later network response fails, automatically replaying the entire model/tool round can perform the action twice unless the system has idempotency or duplicate protection.
Retry logic for ordinary text generation and retry logic for side-effecting tools should not be treated as the same problem.
Preventing errors before they happen
A well-designed BYOK client can reduce avoidable failures by:
- validating base URLs;
- separating credentials by provider connection;
- discovering models when the provider supports it;
- not exposing unsupported settings for a selected model;
- clearly identifying the active provider and model;
- showing quota-related errors without pretending they are auth failures;
- preserving provider request IDs for debugging;
- making retry behavior visible.
If you regularly switch among providers, Using Multiple AI Providers in One Workflow explains why keeping connections separate is safer than treating every API as interchangeable.
The practical takeaway
Remember the core categories:
- 401 = authentication
- 403 = authorization
- 429 = rate, quota, or capacity
Then read the provider’s actual error payload before changing anything.
The fastest debugging path is to identify the failing layer first. In a BYOK setup, the chat client controls request construction and error presentation, while account permissions, billing, quotas, and provider-side availability remain properties of the provider account you control.