Your API key is present. The gateway homepage opens. The client still returns 404 Not Found.
Before rotating the key or adding retries, inspect the URL that actually left the client. An extra path segment, an incompatible endpoint, and a model that is unavailable to your account can all lead to a 404, but they require different fixes.
This guide covers custom AI API endpoints and OpenAI-compatible gateways. The hostnames below use the reserved .example domain; they are illustrations, not live services.
1. Start with the final request URL
A configuration field called “Base URL” is ambiguous. One client expects an origin, another expects a versioned API root, and a third expects a complete endpoint.
For a hypothetical service whose documented chat endpoint is POST https://gateway.example/v1/chat/completions, distinguish these values:
| Value | What it represents |
|---|---|
https://gateway.example |
Origin: scheme and host |
https://gateway.example/v1 |
Versioned API root |
https://gateway.example/v1/chat/completions |
Complete endpoint for one operation |
The correct setting depends on what the client appends. A field that expects the versioned root may produce /v1/chat/completions/chat/completions if you paste the full endpoint into it. A tool that already appends /v1 may produce /v1/v1/chat/completions instead.
Inspect the HTTP method, host, and path in a redacted client debug log or browser network panel. For a backend integration, a gateway access log can show what arrived. Match the final request against the service documentation rather than adjusting the configuration by trial and error.
A successful browser visit to the homepage only proves that the web route works. It does not prove that the API route, method, or credentials are correct.
2. Check how paths are joined
Trailing slashes and leading slashes have meaning in standard URL resolution. This Python example makes no network requests:
from urllib.parse import urljoin
base = "https://gateway.example/v1/"
print(urljoin(base, "chat/completions"))
# https://gateway.example/v1/chat/completions
print(urljoin(base, "/chat/completions"))
# https://gateway.example/chat/completions
print(urljoin("https://gateway.example/v1", "chat/completions"))
# https://gateway.example/chat/completions
A leading slash starts at the origin root. Without a trailing slash on the base, the final segment can be treated as a file-like segment and replaced.
This demonstrates Python's URL resolution rules. It does not establish how a particular SDK joins paths: an SDK may normalize or concatenate them differently. Check the behavior of the client version you are running.
Also inspect reverse-proxy rewrites. If the client sends /v1/chat/completions but the upstream receives /chat/completions, investigate the proxy's prefix handling. Changing the model name cannot repair that path mismatch.
3. Match the request protocol to the endpoint
“Compatible” does not mean every API surface is supported.
An OpenAI-compatible chat request commonly uses POST /v1/chat/completions with a messages payload. A Responses-style integration uses a different route and request schema. An Anthropic Messages integration has its own headers and body contract, even if a gateway exposes it under a similar-looking version prefix.
Do not send one protocol's JSON to another protocol's endpoint and expect changing the hostname to translate it. A gateway may offer conversion, but only rely on the routes and features it documents.
Confirm four things together: the operation, HTTP method, authentication scheme, and payload format. Opening a POST endpoint in the address bar sends a GET request; that is not a valid generation test. Unsupported methods may produce a 405 or a service-specific response, so keep the response body instead of interpreting the status alone.
A client update can also change the operation it calls. If an integration worked before an upgrade, compare the actual old and new paths before blaming the key.
4. Separate a missing route from an unavailable model
HTTP 404 says that the server did not find the requested resource, or is not willing to disclose that it exists. It does not identify which layer produced the response.
Use the body and content type as clues:
| Response | Next check |
|---|---|
| HTML “not found” page | Host, web/API routing, proxy, or CDN |
| HTTP 200 containing a login page | Redirects or a web frontend reached instead of the API |
| JSON error naming a model | Exact model identifier, account access, and endpoint compatibility |
| JSON error naming an unknown path | Client path construction and gateway routes |
| A connection failure without an HTTP response | DNS, TLS, or connectivity; a different failure class |
These are clues, not guarantees. A proxy can return JSON, and an API edge can return HTML. Use timestamps and request IDs, where available, to correlate the client, gateway, and upstream logs.
For model errors, use the exact identifier from the service's current documentation or your account's model list. A website display name is not necessarily an API identifier. Check case, punctuation, aliases, and any version suffix.
If the service documents a model-list endpoint, use it as supporting evidence. A successful list response does not prove every listed model supports every operation. Conversely, an unsupported list endpoint does not prove generation is broken. If your gateway uses routing groups or token-level permissions, verify the restrictions on the credential actually used by the application.
Some services intentionally avoid distinguishing missing resources from inaccessible resources. A 404 therefore does not prove authentication succeeded. Consult the documented error code and account permissions before replacing credentials.
5. Inspect redirects before following them
A wrong host may redirect an API request to a dashboard or sign-in page. An automatic redirect can hide that intermediate response, leaving the application to parse HTML as JSON.
During diagnosis, inspect the initial status and Location header. For a redirect, verify the destination host and the method behavior documented by your HTTP client. Do not forward an API credential to a new host merely to make a request succeed.
When checking a browser network panel, look at the request initiated by the application rather than an unrelated successful page load. With backend clients, use sanitized diagnostics that show URL and status without exposing authorization headers.
Never share an unredacted HAR, copied cURL command, or verbose log. These can contain keys, cookies, request bodies, and private prompts.
6. Reduce the problem to one request
Once the route is correct, reproduce with the smallest documented request:
- Use one model you know your account can access.
- Start without streaming, tools, images, or optional parameters.
- Send a short non-sensitive prompt using the documented schema.
- Record the method, sanitized URL, status, error code, and request ID.
- Add features back one at a time after the basic call succeeds.
If the minimal request works while the application fails, compare the final request URLs and protocol choices. Check which configuration is active: a container, process manager, or IDE can still be supplying an older environment variable. Restart only the affected process after correcting it, and verify the next request rather than assuming the new value loaded.
A successful generation test can incur usage charges. A small test is enough to validate the route; repeated generations are not needed to diagnose a duplicated path prefix.
A short incident note that is actually useful
Instead of “the API is down,” capture a sanitized note like this:
Client: application and client-library version
Operation: chat generation, non-streaming
Expected: POST https://gateway.example/v1/chat/completions
Observed: POST https://gateway.example/v1/v1/chat/completions
Response: 404; application/json; documented error code if present
Time: UTC timestamp
Request ID: if supplied by the service
Change: removed the duplicate version prefix in client configuration
Result: one minimal request succeeded
A fixed path mismatch will not heal through backoff. Preserve the error, correct the configuration, and then make a deliberate verification request.
I work on YW Code API (ywcode), an AI API gateway. Clear API roots, explicit protocol choices, and useful error reports matter whether an application calls a provider directly or goes through a gateway.
Related: Handling AI API 429 Errors.
References: HTTP 404 and Python URL parsing.
Prepared with AI assistance; the URL-resolution example was checked locally without calling an AI API.
Top comments (0)