Authentication

AI API Authentication: API Keys, Bearer Tokens, and Environment Variables

OpenAI, Anthropic, and Gemini don't all authenticate requests the same way — the actual header differences, where keys belong, and how to test any of them safely.

AlleForge TeamAugust 16, 20265 min read

Authentication covers how AlleForge handles auth on any request. This guide is narrower: AI/LLM providers don't all authenticate requests the same way, the differences are easy to get wrong, and getting them wrong produces a genuine authentication failure that looks nothing like a code bug.

The core problem

Most people assume every API takes a bearer token in the Authorization header, because that's the most common pattern. It isn't universal — even among the major AI providers:

  • OpenAI: Authorization: Bearer <api_key> — the standard pattern.
  • Anthropic: x-api-key: <api_key>, or Authorization: Bearer <token> where the token is a short-lived one obtained via Workload Identity Federation for enterprise setups. Either way, a mandatory anthropic-version header (e.g. 2023-06-01) is also required on every request — a request missing it fails even with a perfectly valid key.
  • Gemini: x-goog-api-key: <api_key> — a different custom header, not Authorization: Bearer.
  • Ollama: no real authentication for local usage at all (the OpenAI client library requires an api_key value be present, but Ollama ignores it) — but Ollama Cloud, a separate product, does require either signing in (ollama signin) or an API key set via the OLLAMA_API_KEY environment variable.

A request built for one provider's auth convention will fail against another's — not with a helpful "wrong header" message, but usually a plain 401, indistinguishable at a glance from an actually-invalid key.

API key handling

Wherever the key comes from, a few things stay true regardless of provider:

  • Never commit an API key to Git. Treat it as you would a password — it isn't recoverable-by-design once it's in a public (or even private) repository's history.
  • Store it as an environment variable, not a literal string in code:
export API_KEY="your-key-here"
curl https://api.example.com/v1/chat/completions \
  -H "Authorization: Bearer $API_KEY"

Browser security: server-side vs. browser-side

This distinction matters more for AI APIs than most, because a lot of AI-powered frontend demos get it wrong:

Server-side request:
Your backend  →  AI provider
(API key lives on the server, never sent to the browser)
 
Browser-side request:
Browser  →  AI provider
(API key would have to be embedded in frontend JavaScript)

A secret API key placed directly in frontend JavaScript is visible to anyone who opens the browser's network tab or reads the page's source — it isn't actually secret at that point, regardless of minification or bundling. The standard pattern for any AI provider that requires a real credential is:

Browser → your backend → AI provider

Your backend holds the key and makes the actual provider request; the browser only ever talks to your own backend. This is not unique to AI APIs — it's the same rule as any API requiring a real secret — but it's worth stating plainly here because "just call OpenAI directly from the frontend" is a genuinely common first instinct, and it doesn't work safely for anything beyond a local, throwaway experiment.

Where AlleForge fits

Testing an AI API's authentication is the same workflow as testing any authenticated API: set the key as an environment variable, attach it to the request (or configure it once on a collection so every request inside inherits it), send the request from API Testing, and read the actual response — not just whether it returned 200. AlleForge doesn't need anything AI-specific to do this; the same OAuth/API-key/bearer/inherited-auth support already described in the general authentication guide covers every pattern listed above, including a header-based key like Gemini's x-goog-api-key or Anthropic's x-api-key, since both are just custom headers, not something requiring special handling.

A practical testing workflow

  1. Store the provider's credential in an environment variable — never a literal value in the request.
  2. Configure the active environment so the right key is in scope.
  3. Build the request against the provider's endpoint.
  4. Attach authentication — the exact header the provider expects, per the list above.
  5. Send the request.
  6. Inspect the actual response body, not just the status code.
  7. If it fails, check the error against the table below before assuming the key itself is wrong.
  8. Save the working request to a collection so the next test against this provider starts from something that already works.

Error handling

StatusUsual meaning
401 UnauthorizedMissing header, wrong header name for this provider (e.g. sending Authorization: Bearer to Gemini instead of x-goog-api-key), or a genuinely invalid/revoked key
403 ForbiddenKey is valid but lacks permission for this specific operation or model
A 4xx specifically from Anthropic with the key otherwise correctCheck for a missing or wrong anthropic-version header — this is required independently of the auth header itself
Works against one provider, fails against another with "the same" auth codeAlmost always a provider-specific header mismatch, not a broken key — check the table at the top of this guide

Status codes aren't perfectly consistent across providers even for conceptually the same problem — treat this table as a starting point for what to check, not a guarantee of what a specific provider will return.

Sources

Authentication header requirements for OpenAI, Anthropic, and Gemini, and the local-vs-cloud authentication distinction for Ollama, are sourced from each provider's own current official API documentation (platform.claude.com, ai.google.dev, docs.ollama.com), fetched directly for this guide.

See this in AlleForge

Open API Testing