diff --git a/.speakeasy/gen.lock b/.speakeasy/gen.lock
index 28e97ad4..5ce87411 100644
--- a/.speakeasy/gen.lock
+++ b/.speakeasy/gen.lock
@@ -1,19 +1,19 @@
lockVersion: 2.0.0
id: c48cf606-fb42-4a45-9c23-8f0555307828
management:
- docChecksum: a103037538d332613316e13a17300983
+ docChecksum: ca7e6ffbc81c23f4f96f028264d3a0c6
docVersion: 1.0.0
speakeasyVersion: 1.803.2
generationVersion: 2.950.13
- releaseVersion: 1.3.131
- configChecksum: adc032422d0efdef82e0f3fb3c072d6f
+ releaseVersion: 1.3.132
+ configChecksum: e6838479b1c5f69c83e3581e1ec5fdda
repoURL: https://github.com/OpenRouterTeam/python-sdk.git
installationURL: https://github.com/OpenRouterTeam/python-sdk.git
published: true
persistentEdits:
- generation_id: 00299001-7278-4525-85df-299f2c3aa458
- pristine_commit_hash: b4d0a6a296b91d7f678af19ecde12c49c08a9f3c
- pristine_tree_hash: 758afb314231c4d0aad04d3f5bb0203ebf49e93b
+ generation_id: ed8669f6-9e68-4aa9-9ba3-bfbe3f645b6a
+ pristine_commit_hash: baca27461f2201c3c005cc8adafe4d3e558059d5
+ pristine_tree_hash: 9696b5accb25cbb15b40e39f1214bd7e04273282
features:
python:
acceptHeaders: 3.0.0
@@ -2020,8 +2020,8 @@ trackedFiles:
pristine_git_object: e2ecd460775d54a5b43c5bc597f8027424462b8d
docs/components/chatrequestreasoning.mdx:
id: 8f0176992b3e
- last_write_checksum: sha1:784cf74791cfbd6b92cd02b368f97b7826b511aa
- pristine_git_object: 1c04df67ad034913cdb2a139f05821023c4977b4
+ last_write_checksum: sha1:3247d0ea825f01d20bea2ecee221e3e6b33cf035
+ pristine_git_object: 057e91d78f416d541dd4c3ce4d07125fd06aa8e0
docs/components/chatrequestreasoningeffort.mdx:
id: a8ac4d0f36fd
last_write_checksum: sha1:7cf50deaeb4a20ca64352b8713479059834e5f78
@@ -10440,8 +10440,12 @@ trackedFiles:
pristine_git_object: e0298f128f4fac5b60ecbd405fc4f251ed23c128
docs/operations/listresponse.mdx:
id: 0fbda0f81ae8
- last_write_checksum: sha1:73963968eb448421e0ad3a5a442192da7c46c6a9
- pristine_git_object: a39b3dad1e5a8250b05181280a5b81e2042244a0
+ last_write_checksum: sha1:038d67577055fc228a26c28173b10968f116570a
+ pristine_git_object: d6a65aadf3cfc06e13ef3c2b40004c3f7d52e3aa
+ docs/operations/listresponsebody.mdx:
+ id: 2608b7720d49
+ last_write_checksum: sha1:57867f1dcfdfe3106e329a2ba6026b5a4a3acf47
+ pristine_git_object: c66af276a0d1722a9b8c9797f651c6af297d3cac
docs/operations/listscimgroupmappingsglobals.mdx:
id: 895d22ec37c3
last_write_checksum: sha1:32c624e1f723d52068a5de4bb763dac0325b4b1d
@@ -10856,8 +10860,8 @@ trackedFiles:
pristine_git_object: 2cfd14c40ab962877968c79c6c958ea432a4f083
docs/sdks/apikeys/README.mdx:
id: 27fcaae1c346
- last_write_checksum: sha1:80273bedf61e6131728eaafbdea8c2a9e7d8e7e7
- pristine_git_object: c2e930c8fceb2d22431d2a2be01ceb227df72937
+ last_write_checksum: sha1:09195a526bc468df6743e47dbdee79949f66e77c
+ pristine_git_object: 2f4950880ee5164aa8988d13d4eba940778d5f17
docs/sdks/batch/README.mdx:
id: e367aa4f4295
last_write_checksum: sha1:e5084fc19c2bfc9aa28e90a86d4accb5c9153130
@@ -11008,8 +11012,8 @@ trackedFiles:
pristine_git_object: 3e38f1a929f7d6b1d6de74604aa87e3d8f010544
pyproject.toml:
id: 5d07e7d72637
- last_write_checksum: sha1:ec5bd30f505e4052b284661c9a29ff2fac35647c
- pristine_git_object: e0c226a4f028f7fc0bd43c0c16ccf7997cf300ae
+ last_write_checksum: sha1:ddf3436a53d9ced3db7db5e63b0195f1d67a09b0
+ pristine_git_object: 326597ffe04f2ab8bcd91c8164128eeef3acc969
scripts/prepare_readme.py:
id: e0c5957a6035
last_write_checksum: sha1:77f44b60b98bc126557ec27391f91dfba764bb54
@@ -11036,8 +11040,8 @@ trackedFiles:
pristine_git_object: 86713cfea633e09d33b3d4e65281071fe20e6137
src/openrouter/_version.py:
id: d8d15ad6c586
- last_write_checksum: sha1:a6b9ba70c16d696c1b6b2786b6bc21465a2da557
- pristine_git_object: 26e24a92c8db5c8328a8fb4655c0c4abc9c72a49
+ last_write_checksum: sha1:81469ff054eae539eb5d2bd9ef2ec462ba5f9b17
+ pristine_git_object: 4c8151ae024627c7c683ab46a866d3893b3d0efe
src/openrouter/alpha.py:
id: 306c4d93308d
last_write_checksum: sha1:80cc0f39649445431cc2247ed0e0765438467766
@@ -11048,8 +11052,8 @@ trackedFiles:
pristine_git_object: 0e567f3a37cc6aeb45a2551d0d500412e4b7796d
src/openrouter/api_keys.py:
id: 876fac88fff6
- last_write_checksum: sha1:3a2893899424d7129a75bf66fd877c83d54af502
- pristine_git_object: 28616aac95dc38d48923169945f49cf2bceeeaf2
+ last_write_checksum: sha1:eee27956e31d7525d8cfbc9177d5b79db2b3aab3
+ pristine_git_object: 73c16d709a3b6f578233a79c00211dadd67e77a5
src/openrouter/basesdk.py:
id: c5733c5a1e12
last_write_checksum: sha1:65769ff2cb5473f85b364c6213a0ddc8c68644ea
@@ -11928,8 +11932,8 @@ trackedFiles:
pristine_git_object: 8bbde153b53887e426989fd5b0486b6dc1122810
src/openrouter/components/chatrequest.py:
id: 5e39eaefa9cf
- last_write_checksum: sha1:ae69df07e940af7449bd9a974d404886becfd00f
- pristine_git_object: b278ed4451980d3550bed9907e638a184b28e257
+ last_write_checksum: sha1:34203bf0d944f6c4baa608b3600089b7b82d7210
+ pristine_git_object: 5fc9915bea11993b3149d3d06dc367b75219f0be
src/openrouter/components/chatresult.py:
id: 9062fe2935fe
last_write_checksum: sha1:832ad4df3f9f92818e36e9d26a73da3bcff3eb7a
@@ -14904,8 +14908,8 @@ trackedFiles:
pristine_git_object: 4a35ede011d09dddab042e2c00413ce4f6be655e
src/openrouter/operations/__init__.py:
id: 9afcea1e7161
- last_write_checksum: sha1:3549a224597521d4f1d080a8d9acdfd6a9de3fa7
- pristine_git_object: 7319f555fe88b80496da7b646185e294f6d83d38
+ last_write_checksum: sha1:62969538c6bbd7a6bbf9509c09299d5f32e41304
+ pristine_git_object: 6f0b96c552f725aa1e7660e7c0afdac1168291b3
src/openrouter/operations/activateprivateendpoint.py:
id: 3b39eec5d66f
last_write_checksum: sha1:9406e6b3d38c82895fd795f637702ef579cc6d36
@@ -15248,8 +15252,8 @@ trackedFiles:
pristine_git_object: 0365c6edd5a01c4086dfcf75d326fb48a67ad9d6
src/openrouter/operations/list.py:
id: 3ced31e3804e
- last_write_checksum: sha1:ed6233bd58de02cb3126d333c2e361b83d8b5bce
- pristine_git_object: bf7d30f58097da5c25d83a257163f280c7276693
+ last_write_checksum: sha1:f139bef84fb09ba815b0529517988ff109c13cba
+ pristine_git_object: 8abf4d7aa09edae2e53f7fac0b90d701e9889f98
src/openrouter/operations/listbatches.py:
id: 9ad1345dc956
last_write_checksum: sha1:b7017793a979647ef2ec7fee333e34063664c9eb
@@ -20204,7 +20208,4 @@ examples:
"500":
application/json: {"error": {"code": 500, "message": "Internal Server Error"}}
examplesVersion: 1.0.2
-releaseNotes: |
- ## Python SDK Changes:
- * `open_router.alpha.decisions.create()`: `response.usage` **Changed**
- * `open_router.system_one.create()`: `response.usage` **Changed**
+releaseNotes: "## Python SDK Changes:\n* `open_router.presets.create_presets_chat_completions()`: \n * `request.reasoning.max_tokens` **Added**\n"
diff --git a/.speakeasy/gen.yaml b/.speakeasy/gen.yaml
index 46a7cb80..1b71fa6c 100644
--- a/.speakeasy/gen.yaml
+++ b/.speakeasy/gen.yaml
@@ -37,7 +37,7 @@ generation:
documentation: mintlify
preApplyUnionDiscriminators: true
python:
- version: 1.3.131
+ version: 1.3.132
additionalDependencies:
dev:
pytest: '>=8.3'
diff --git a/.speakeasy/out.openapi.yaml b/.speakeasy/out.openapi.yaml
index c517e7f6..7f183d9b 100644
--- a/.speakeasy/out.openapi.yaml
+++ b/.speakeasy/out.openapi.yaml
@@ -8018,6 +8018,12 @@ components:
- 'string'
- 'null'
x-speakeasy-unknown-values: allow
+ max_tokens:
+ description: 'Maximum number of tokens the model may spend on reasoning, for models that take a reasoning token budget instead of an effort level. Cannot be combined with `reasoning.effort` or the top-level `reasoning_effort`: a request that sets both is rejected with "Only one of "reasoning.effort" and "reasoning.max_tokens" can be specified".'
+ example: 2000
+ type:
+ - 'integer'
+ - 'null'
summary:
$ref: '#/components/schemas/ChatReasoningSummaryVerbosityEnum'
type: 'object'
@@ -45949,6 +45955,14 @@ paths:
tags:
- 'API Keys'
x-speakeasy-name-override: 'list'
+ x-speakeasy-pagination:
+ inputs:
+ - in: 'parameters'
+ name: 'offset'
+ type: 'offset'
+ outputs:
+ results: '$.data'
+ type: 'offsetLimit'
post:
description: 'Create a new API key for the authenticated user. The plaintext `key` is returned only in this response. Treat it as a write-only, sensitive value; it cannot be retrieved later. Authenticate with a [management key](/docs/guides/overview/auth/management-api-keys). The optional `external` object associates the key with a partner-defined user and lookup key.'
operationId: 'createKeys'
diff --git a/.speakeasy/workflow.lock b/.speakeasy/workflow.lock
index ed015a05..164f90ea 100644
--- a/.speakeasy/workflow.lock
+++ b/.speakeasy/workflow.lock
@@ -2,8 +2,8 @@ speakeasyVersion: 1.803.2
sources:
OpenRouter API:
sourceNamespace: open-router-chat-completions-api
- sourceRevisionDigest: sha256:1fbf0ee26aa1ab7658acda2193df1c36156f4f7b68ccdc009f23357819e34c9c
- sourceBlobDigest: sha256:877af691c84d4fdbe8207d6f21a620711e2b9ad0b87868945f9082d1e7d90178
+ sourceRevisionDigest: sha256:7fa53baff74eba40ecab14053aff50edff9bfeda6cc0c9a253bbf5dacce30f92
+ sourceBlobDigest: sha256:25762da0a3ec232b94ad91452bf08c3c87f0fa962252a43cda859120cccaf1ec
tags:
- latest
- 1.0.0
@@ -11,10 +11,10 @@ targets:
open-router:
source: OpenRouter API
sourceNamespace: open-router-chat-completions-api
- sourceRevisionDigest: sha256:1fbf0ee26aa1ab7658acda2193df1c36156f4f7b68ccdc009f23357819e34c9c
- sourceBlobDigest: sha256:877af691c84d4fdbe8207d6f21a620711e2b9ad0b87868945f9082d1e7d90178
+ sourceRevisionDigest: sha256:7fa53baff74eba40ecab14053aff50edff9bfeda6cc0c9a253bbf5dacce30f92
+ sourceBlobDigest: sha256:25762da0a3ec232b94ad91452bf08c3c87f0fa962252a43cda859120cccaf1ec
codeSamplesNamespace: open-router-python-code-samples
- codeSamplesRevisionDigest: sha256:15a9b9c933c6560ccfe4b3e78bbf894bb543e3cbdfd67777926d3dccd206fca3
+ codeSamplesRevisionDigest: sha256:b78bd40223c09d9bc104a66eb734dd5b5306bbb494ca4b6dff108da6578cf178
workflow:
workflowVersion: 1.0.0
speakeasyVersion: 1.803.2
diff --git a/RELEASES.md b/RELEASES.md
index 4e7fa953..323a5bf8 100644
--- a/RELEASES.md
+++ b/RELEASES.md
@@ -4079,4 +4079,14 @@ Based on:
### Generated
- [python v1.3.131] .
### Releases
-- [PyPI v1.3.131] https://pypi.org/project/openrouter/1.3.131 - .
\ No newline at end of file
+- [PyPI v1.3.131] https://pypi.org/project/openrouter/1.3.131 - .
+
+## 2026-11-05 21:39:51
+### Changes
+Based on:
+- OpenAPI Doc
+- Speakeasy CLI 1.803.2 (2.950.13) https://github.com/speakeasy-api/speakeasy
+### Generated
+- [python v1.3.132] .
+### Releases
+- [PyPI v1.3.132] https://pypi.org/project/openrouter/1.3.132 - .
\ No newline at end of file
diff --git a/docs/components/chatrequestreasoning.mdx b/docs/components/chatrequestreasoning.mdx
index 1c04df67..057e91d7 100644
--- a/docs/components/chatrequestreasoning.mdx
+++ b/docs/components/chatrequestreasoning.mdx
@@ -7,7 +7,8 @@ Configuration options for reasoning models
## Fields
-| Field | Type | Required | Description | Example |
-| -------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------- |
-| `effort` | [OptionalNullable[components.ChatRequestEffort]](../components/chatrequesteffort.mdx) | ➖ | Constrains effort on reasoning for reasoning models | medium |
-| `summary` | [OptionalNullable[components.ChatReasoningSummaryVerbosityEnum]](../components/chatreasoningsummaryverbosityenum.mdx) | ➖ | N/A | concise |
\ No newline at end of file
+| Field | Type | Required | Description | Example |
+| -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| `effort` | [OptionalNullable[components.ChatRequestEffort]](../components/chatrequesteffort.mdx) | ➖ | Constrains effort on reasoning for reasoning models | medium |
+| `max_tokens` | *OptionalNullable[int]* | ➖ | Maximum number of tokens the model may spend on reasoning, for models that take a reasoning token budget instead of an effort level. Cannot be combined with `reasoning.effort` or the top-level `reasoning_effort`: a request that sets both is rejected with "Only one of "reasoning.effort" and "reasoning.max_tokens" can be specified". | 2000 |
+| `summary` | [OptionalNullable[components.ChatReasoningSummaryVerbosityEnum]](../components/chatreasoningsummaryverbosityenum.mdx) | ➖ | N/A | concise |
\ No newline at end of file
diff --git a/docs/operations/listresponse.mdx b/docs/operations/listresponse.mdx
index a39b3dad..d6a65aad 100644
--- a/docs/operations/listresponse.mdx
+++ b/docs/operations/listresponse.mdx
@@ -2,11 +2,8 @@
title: "ListResponse"
---
-List of API keys
-
-
## Fields
-| Field | Type | Required | Description |
-| ------------------------------------------------------ | ------------------------------------------------------ | ------------------------------------------------------ | ------------------------------------------------------ |
-| `data` | List[[operations.ListData](../operations/listdata.mdx)] | ✔️ | List of API keys |
\ No newline at end of file
+| Field | Type | Required | Description | Example |
+| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
+| `result` | [operations.ListResponseBody](../operations/listresponsebody.mdx) | ✔️ | N/A | \{
"data": [
\{
"byok_usage": 17.38,
"byok_usage_daily": 17.38,
"byok_usage_monthly": 17.38,
"byok_usage_weekly": 17.38,
"created_at": "2025-08-24T10:30:00Z",
"creator_user_id": "user_2dHFtVWx2n56w6HkM0000000000",
"disabled": false,
"expires_at": "2027-12-31T23:59:59Z",
"external_user": null,
"hash": "f01d52606dc8f0a8303a7b5cc3fa07109c2e346cec7c0a16b40de462992ce943",
"include_byok_in_limit": false,
"label": "Production API Key",
"last_used_at": "2026-09-15T15:45:00Z",
"limit": 100,
"limit_remaining": 74.5,
"limit_reset": "monthly",
"name": "My Production Key",
"updated_at": "2025-08-24T15:45:00Z",
"usage": 25.5,
"usage_daily": 25.5,
"usage_monthly": 25.5,
"usage_weekly": 25.5,
"workspace_id": "0df9e665-d932-5740-b2c7-b52af166bc11"
}
]
} |
\ No newline at end of file
diff --git a/docs/operations/listresponsebody.mdx b/docs/operations/listresponsebody.mdx
new file mode 100644
index 00000000..c66af276
--- /dev/null
+++ b/docs/operations/listresponsebody.mdx
@@ -0,0 +1,12 @@
+---
+title: "ListResponseBody"
+---
+
+List of API keys
+
+
+## Fields
+
+| Field | Type | Required | Description |
+| ------------------------------------------------------ | ------------------------------------------------------ | ------------------------------------------------------ | ------------------------------------------------------ |
+| `data` | List[[operations.ListData](../operations/listdata.mdx)] | ✔️ | List of API keys |
\ No newline at end of file
diff --git a/docs/sdks/apikeys/README.mdx b/docs/sdks/apikeys/README.mdx
index c2e930c8..2f495088 100644
--- a/docs/sdks/apikeys/README.mdx
+++ b/docs/sdks/apikeys/README.mdx
@@ -82,8 +82,10 @@ with OpenRouter(
res = open_router.api_keys.list()
- # Handle response
- print(res)
+ while res is not None:
+ # Handle items
+
+ res = res.next()
```
diff --git a/pyproject.toml b/pyproject.toml
index e0c226a4..326597ff 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,6 +1,6 @@
[project]
name = "openrouter"
-version = "1.3.131"
+version = "1.3.132"
description = "Official Python Client SDK for OpenRouter."
authors = [{ name = "OpenRouter" },]
readme = "README-PYPI.md"
diff --git a/src/openrouter/_version.py b/src/openrouter/_version.py
index 26e24a92..4c8151ae 100644
--- a/src/openrouter/_version.py
+++ b/src/openrouter/_version.py
@@ -3,10 +3,10 @@
import importlib.metadata
__title__: str = "openrouter"
-__version__: str = "1.3.131"
+__version__: str = "1.3.132"
__openapi_doc_version__: str = "1.0.0"
__gen_version__: str = "2.950.13"
-__user_agent__: str = "speakeasy-sdk/python 1.3.131 2.950.13 1.0.0 openrouter"
+__user_agent__: str = "speakeasy-sdk/python 1.3.132 2.950.13 1.0.0 openrouter"
try:
if __package__ is not None:
diff --git a/src/openrouter/api_keys.py b/src/openrouter/api_keys.py
index 28616aac..73c16d70 100644
--- a/src/openrouter/api_keys.py
+++ b/src/openrouter/api_keys.py
@@ -2,12 +2,13 @@
from .basesdk import BaseSDK
from datetime import datetime
+from jsonpath import JSONPath
from openrouter import components, errors, operations, utils
from openrouter._hooks import HookContext
from openrouter.types import OptionalNullable, UNSET
from openrouter.utils import get_security_from_env
from openrouter.utils.unmarshal_json_response import unmarshal_json_response
-from typing import Any, Mapping, Optional, Union
+from typing import Any, Awaitable, Dict, List, Mapping, Optional, Union
class APIKeys(BaseSDK):
@@ -267,7 +268,7 @@ def list(
server_url: Optional[str] = None,
timeout_ms: Optional[int] = None,
http_headers: Optional[Mapping[str, str]] = None,
- ) -> operations.ListResponse:
+ ) -> Optional[operations.ListResponse]:
r"""List API keys
List all API keys for the authenticated user. [Management key](/docs/guides/overview/auth/management-api-keys) required.
@@ -359,9 +360,38 @@ def list(
retry_config=retry_config,
)
+ def next_func() -> Optional[operations.ListResponse]:
+ body = utils.unmarshal_json(http_res.text, Union[Dict[Any, Any], List[Any]])
+
+ offset = request.offset if isinstance(request.offset, int) else 0
+
+ if not http_res.text:
+ return None
+ results = JSONPath("$.data").parse(body)
+ if len(results) == 0 or len(results[0]) == 0:
+ return None
+ next_offset = offset + len(results[0])
+
+ return self.list(
+ http_referer=http_referer,
+ x_open_router_title=x_open_router_title,
+ x_open_router_categories=x_open_router_categories,
+ include_disabled=include_disabled,
+ include_expired=include_expired,
+ offset=next_offset,
+ workspace_id=workspace_id,
+ retries=retries,
+ server_url=server_url,
+ timeout_ms=timeout_ms,
+ http_headers=http_headers,
+ )
+
response_data: Any = None
if utils.match_response(http_res, "200", "application/json"):
- return unmarshal_json_response(operations.ListResponse, http_res)
+ return operations.ListResponse(
+ result=unmarshal_json_response(operations.ListResponseBody, http_res),
+ next=next_func,
+ )
if utils.match_response(http_res, "400", "application/json"):
response_data = unmarshal_json_response(
errors.BadRequestResponseErrorData, http_res
@@ -419,7 +449,7 @@ async def list_async(
server_url: Optional[str] = None,
timeout_ms: Optional[int] = None,
http_headers: Optional[Mapping[str, str]] = None,
- ) -> operations.ListResponse:
+ ) -> Optional[operations.ListResponse]:
r"""List API keys
List all API keys for the authenticated user. [Management key](/docs/guides/overview/auth/management-api-keys) required.
@@ -511,9 +541,41 @@ async def list_async(
retry_config=retry_config,
)
+ def next_func() -> Awaitable[Optional[operations.ListResponse]]:
+ body = utils.unmarshal_json(http_res.text, Union[Dict[Any, Any], List[Any]])
+
+ async def empty_result():
+ return None
+
+ offset = request.offset if isinstance(request.offset, int) else 0
+
+ if not http_res.text:
+ return empty_result()
+ results = JSONPath("$.data").parse(body)
+ if len(results) == 0 or len(results[0]) == 0:
+ return empty_result()
+ next_offset = offset + len(results[0])
+
+ return self.list_async(
+ http_referer=http_referer,
+ x_open_router_title=x_open_router_title,
+ x_open_router_categories=x_open_router_categories,
+ include_disabled=include_disabled,
+ include_expired=include_expired,
+ offset=next_offset,
+ workspace_id=workspace_id,
+ retries=retries,
+ server_url=server_url,
+ timeout_ms=timeout_ms,
+ http_headers=http_headers,
+ )
+
response_data: Any = None
if utils.match_response(http_res, "200", "application/json"):
- return unmarshal_json_response(operations.ListResponse, http_res)
+ return operations.ListResponse(
+ result=unmarshal_json_response(operations.ListResponseBody, http_res),
+ next=next_func,
+ )
if utils.match_response(http_res, "400", "application/json"):
response_data = unmarshal_json_response(
errors.BadRequestResponseErrorData, http_res
diff --git a/src/openrouter/components/chatrequest.py b/src/openrouter/components/chatrequest.py
index b278ed44..5fc9915b 100644
--- a/src/openrouter/components/chatrequest.py
+++ b/src/openrouter/components/chatrequest.py
@@ -144,6 +144,8 @@ class ChatRequestReasoningTypedDict(TypedDict):
effort: NotRequired[Nullable[ChatRequestEffort]]
r"""Constrains effort on reasoning for reasoning models"""
+ max_tokens: NotRequired[Nullable[int]]
+ r"""Maximum number of tokens the model may spend on reasoning, for models that take a reasoning token budget instead of an effort level. Cannot be combined with `reasoning.effort` or the top-level `reasoning_effort`: a request that sets both is rejected with \"Only one of \"reasoning.effort\" and \"reasoning.max_tokens\" can be specified\"."""
summary: NotRequired[Nullable[ChatReasoningSummaryVerbosityEnum]]
@@ -153,12 +155,15 @@ class ChatRequestReasoning(BaseModel):
effort: OptionalNullable[ChatRequestEffort] = UNSET
r"""Constrains effort on reasoning for reasoning models"""
+ max_tokens: OptionalNullable[int] = UNSET
+ r"""Maximum number of tokens the model may spend on reasoning, for models that take a reasoning token budget instead of an effort level. Cannot be combined with `reasoning.effort` or the top-level `reasoning_effort`: a request that sets both is rejected with \"Only one of \"reasoning.effort\" and \"reasoning.max_tokens\" can be specified\"."""
+
summary: OptionalNullable[ChatReasoningSummaryVerbosityEnum] = UNSET
@model_serializer(mode="wrap")
def serialize_model(self, handler):
- optional_fields = set(["effort", "summary"])
- nullable_fields = set(["effort", "summary"])
+ optional_fields = set(["effort", "max_tokens", "summary"])
+ nullable_fields = set(["effort", "max_tokens", "summary"])
serialized = handler(self)
m = {}
diff --git a/src/openrouter/operations/__init__.py b/src/openrouter/operations/__init__.py
index 7319f555..6f0b96c5 100644
--- a/src/openrouter/operations/__init__.py
+++ b/src/openrouter/operations/__init__.py
@@ -680,6 +680,8 @@
ListRequest,
ListRequestTypedDict,
ListResponse,
+ ListResponseBody,
+ ListResponseBodyTypedDict,
ListResponseTypedDict,
)
from .listbatches import (
@@ -1784,6 +1786,8 @@
"ListRequest",
"ListRequestTypedDict",
"ListResponse",
+ "ListResponseBody",
+ "ListResponseBodyTypedDict",
"ListResponseTypedDict",
"ListScimGroupMappingsGlobals",
"ListScimGroupMappingsGlobalsTypedDict",
@@ -2474,6 +2478,8 @@
"ListRequest": ".list",
"ListRequestTypedDict": ".list",
"ListResponse": ".list",
+ "ListResponseBody": ".list",
+ "ListResponseBodyTypedDict": ".list",
"ListResponseTypedDict": ".list",
"ListBatchesGlobals": ".listbatches",
"ListBatchesGlobalsTypedDict": ".listbatches",
diff --git a/src/openrouter/operations/list.py b/src/openrouter/operations/list.py
index bf7d30f5..8abf4d7a 100644
--- a/src/openrouter/operations/list.py
+++ b/src/openrouter/operations/list.py
@@ -12,7 +12,7 @@
from openrouter.utils import FieldMetadata, HeaderMetadata, QueryParamMetadata
import pydantic
from pydantic import model_serializer
-from typing import List, Optional
+from typing import Awaitable, Callable, List, Optional, Union
from typing_extensions import Annotated, NotRequired, TypedDict
@@ -349,15 +349,28 @@ def serialize_model(self, handler):
return m
-class ListResponseTypedDict(TypedDict):
+class ListResponseBodyTypedDict(TypedDict):
r"""List of API keys"""
data: List[ListDataTypedDict]
r"""List of API keys"""
-class ListResponse(BaseModel):
+class ListResponseBody(BaseModel):
r"""List of API keys"""
data: List[ListData]
r"""List of API keys"""
+
+
+class ListResponseTypedDict(TypedDict):
+ result: ListResponseBodyTypedDict
+
+
+class ListResponse(BaseModel):
+ next: Union[
+ Callable[[], Optional[ListResponse]],
+ Callable[[], Awaitable[Optional[ListResponse]]],
+ ]
+
+ result: ListResponseBody
diff --git a/uv.lock b/uv.lock
index d9c9720e..82d077b3 100644
--- a/uv.lock
+++ b/uv.lock
@@ -231,7 +231,7 @@ wheels = [
[[package]]
name = "openrouter"
-version = "1.3.131"
+version = "1.3.132"
source = { editable = "." }
dependencies = [
{ name = "httpcore" },