Summary
models.list_for_user() is the only method in the SDK (1 of 95 operations) that requires
an operation-level security= argument. The api_key passed to the OpenRouter client is
ignored for this one call, so users must supply the same credential twice, through a
differently-named type and a differently-named env var.
The cause is a duplicate security scheme in the OpenAPI document, not the generator.
Steps to reproduce
from openrouter import OpenRouter
client = OpenRouter(api_key="sk-or-v1-...")
client.models.list() # works
client.models.list_for_user() # TypeError
Actual behavior
TypeError: Models.list_for_user() missing 1 required keyword-only argument: 'security'
The signature (src/openrouter/models_.py:1067) makes security required and non-defaulted:
def list_for_user(
self,
*,
security: Union[
operations.ListModelsUserSecurity,
operations.ListModelsUserSecurityTypedDict,
],
...
The only way to call it is to re-pass the key that the client already holds:
from openrouter import OpenRouter, operations
client = OpenRouter(api_key="sk-or-v1-...")
client.models.list_for_user(
security=operations.ListModelsUserSecurity(bearer="sk-or-v1-...") # same key, again
)
docs/sdks/models/README.mdx:210 compounds this by reading it from a second env var,
OPENROUTER_BEARER, while every other snippet in the docs uses OPENROUTER_API_KEY.
Expected behavior
client.models.list_for_user() authenticates with the client-level api_key, like every
other method on the SDK.
Root cause
.speakeasy/out.openapi.yaml defines two security schemes that are identical down to the
description:
securitySchemes:
apiKey:
description: 'API key as bearer token in Authorization header'
scheme: 'bearer'
type: 'http'
bearer:
description: 'API key as bearer token in Authorization header'
scheme: 'bearer'
type: 'http'
Global security is apiKey:
listModelsUser (GET /models/user) is the single operation that overrides it with the
other name:
operationId: 'listModelsUser'
...
security:
- bearer: []
Counts across the whole document:
apiKey: [] appears 8 times
bearer: [] appears exactly once — on this operation.
Both in.openapi.yaml and out.openapi.yaml agree, so it originates upstream in the
monorepo spec rather than in an overlay.
Because the scheme name differs from the global one, hoistGlobalSecurity /
flattenGlobalSecurity can't apply, and the generator emits a required per-operation
security parameter.
Suggested fix
One line upstream — either point the operation at the existing global scheme:
or drop the per-operation security block entirely so it inherits the global one, and
remove the now-unused bearer scheme from components.securitySchemes.
Environment
- openrouter 1.1.23 (main @ cb401a8)
- Python 3.11.9, httpx 0.28.1, pydantic 2.12.4
- Windows 11
Summary
models.list_for_user()is the only method in the SDK (1 of 95 operations) that requiresan operation-level
security=argument. Theapi_keypassed to theOpenRouterclient isignored for this one call, so users must supply the same credential twice, through a
differently-named type and a differently-named env var.
The cause is a duplicate security scheme in the OpenAPI document, not the generator.
Steps to reproduce
Actual behavior
The signature (
src/openrouter/models_.py:1067) makessecurityrequired and non-defaulted:The only way to call it is to re-pass the key that the client already holds:
docs/sdks/models/README.mdx:210compounds this by reading it from a second env var,OPENROUTER_BEARER, while every other snippet in the docs usesOPENROUTER_API_KEY.Expected behavior
client.models.list_for_user()authenticates with the client-levelapi_key, like everyother method on the SDK.
Root cause
.speakeasy/out.openapi.yamldefines two security schemes that are identical down to thedescription:
Global security is
apiKey:listModelsUser(GET /models/user) is the single operation that overrides it with theother name:
Counts across the whole document:
apiKey: []appears 8 timesbearer: []appears exactly once — on this operation.Both
in.openapi.yamlandout.openapi.yamlagree, so it originates upstream in themonorepo spec rather than in an overlay.
Because the scheme name differs from the global one,
hoistGlobalSecurity/flattenGlobalSecuritycan't apply, and the generator emits a required per-operationsecurityparameter.Suggested fix
One line upstream — either point the operation at the existing global scheme:
or drop the per-operation security block entirely so it inherits the global one, and
remove the now-unused
bearerscheme fromcomponents.securitySchemes.Environment