An AI agent calling an API needs two kinds of input: parameters the agent provides, and credentials applied by the system. These must not mix.
Parameters flow through the LLM. The model reasons about what values to provide—customer IDs, quantities, search queries. Credentials flow through secure infrastructure. API keys decrypt from vaults. OAuth tokens refresh automatically. The model never sees them.
This isn’t a nice-to-have. If credentials appear as parameters, the LLM will try to generate them. That’s a security violation. The boundary between parameters and credentials must be architectural, not policy.
OpenAPI has a mechanism for this. Security schemes declare authentication separately from parameters. Operations reference schemes by name. A well-structured spec draws the boundary clearly.
Most specs don’t.
The corpus
We analyzed 4,138 OpenAPI specifications from the APIs.guru corpus—real APIs serving real traffic. GitHub, Stripe, Twilio, thousands more.
39% declare security schemes properly. The other 61% model authentication as regular header parameters. An Authorization header sitting alongside Content-Type, indistinguishable from any other input.
This is a problem. Generic tooling can’t identify which parameters are credentials. The semantic distinction between authentication and data disappears at the spec level.
Why it happened
Security schemes were a relatively late addition to OpenAPI. By the time they existed, thousands of specs were already written using the older pattern: authentication as a header parameter, documented like any other.
And the tooling didn’t push back. Documentation generators render both patterns identically. SDK builders expose both as function arguments. For human developers who handle credentials manually, the distinction doesn’t matter much.
For an AI-API bridge, it’s everything.
Predictable patterns
The 61% aren’t random. We analyzed the patterns:
Among APIs using direct auth headers, 62% use the generic Authorization header. The rest use variations: X-Api-Key, Auth-Token, Access-Token.
For Authorization headers, descriptions reveal the type:
- 66% mention “bearer”, “jwt”, or “token”
- 32% mention OAuth 1.0 signature terminology
- Only 3% are genuinely ambiguous
Description-based detection works. The chaos is more structured than it appears.
The transformation
We built a normalizer that promotes header parameters to proper security schemes. It runs as a transformation pass over parsed specs:
- Identify authentication headers by name pattern
- Infer scheme type from parameter descriptions
- Synthesize the appropriate security scheme object
- Replace the parameter with a security requirement
- Emit the scheme to
components/securitySchemes
A spec arrives with credentials buried in parameters. It leaves with clean separation. Downstream, our execution pipeline knows exactly which inputs are parameters (validate against schema, pass to LLM) and which are credentials (resolve from vault, apply at request time).
The infrastructure payoff
This is a non-trivial transformation. You’re rewriting operation signatures, moving definitions between sections, maintaining references. Done naively, it’s fragile and error-prone.
We built it in a day.
The schema and OpenAPI compiler infrastructure from the past few months made this possible. The same keyword-based architecture that enables tree-shaking enables auth normalization. Parse the spec into a contextually typed structure, transform with full semantic awareness, emit valid output. The pattern is the same; only the transformation logic differs.
This is why we invested in compiler-grade infrastructure. Hard problems become routine when the foundation is solid.
The boundary holds
After normalization, every spec has the same shape. Security schemes declare authentication. Operations reference schemes. Parameters contain only LLM-provided values.
The execution pipeline enforces this unconditionally. Parameters validate against schemas. Credentials resolve from vaults. The two paths never cross.
It doesn’t matter how the original spec was written. The boundary holds.
