diff --git a/.speakeasy/gen.lock b/.speakeasy/gen.lock
index b2c9ba4e..930764ec 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: a0be6866e415062274038e3ba19c0f0d
+ docChecksum: 54f6a56b3ce0196f24d04d18f37ab80a
docVersion: 1.0.0
speakeasyVersion: 1.803.2
generationVersion: 2.950.13
- releaseVersion: 1.3.103
- configChecksum: 9ca83bdb4d50a73dd7dc11da2a5485ea
+ releaseVersion: 1.3.104
+ configChecksum: 1787fee2bed548acbc21c5c6887d812c
repoURL: https://github.com/OpenRouterTeam/python-sdk.git
installationURL: https://github.com/OpenRouterTeam/python-sdk.git
published: true
persistentEdits:
- generation_id: 8cb2aeac-f03b-457f-aa3c-90eac8824e0b
- pristine_commit_hash: ec03155fe6ece2bb076a44f5d42d993158d04920
- pristine_tree_hash: 1e4e1550f89b80c07082c5a4d5caa19729a8a0e8
+ generation_id: 5f665d48-31fb-43ff-b17b-1f44c8e03e26
+ pristine_commit_hash: 654fce46a3afc67527b658404a7a088531cfc0ca
+ pristine_tree_hash: 54a0e2a6d89cfb8fa5c0985bb8dd617f4051f6cd
features:
python:
acceptHeaders: 3.0.0
@@ -6826,6 +6826,10 @@ trackedFiles:
id: ffd85d9fcc2c
last_write_checksum: sha1:78e406250f9bb607250b74952d4ac7c816bbf7ac
pristine_git_object: 523d50326413b82c2b177810f9316f6a29967f94
+ docs/components/publiczdrendpoint.mdx:
+ id: a7b6fd35cd0a
+ last_write_checksum: sha1:07a130c7902c3c1b307d88d5698930d8570a46a6
+ pristine_git_object: 1802fa7faa8ebcace9e0c43d9c5a8898da7275e2
docs/components/purpose.mdx:
id: ae295e1d0077
last_write_checksum: sha1:0254976b545dce44c49a9bff2cdfbe687d5fe749
@@ -9900,8 +9904,8 @@ trackedFiles:
pristine_git_object: 6f5e7d90f806137d65995f761ab2abdad34381dd
docs/operations/listendpointszdrresponse.mdx:
id: f8d0c52ac714
- last_write_checksum: sha1:104c6b7cfef65c362d39c30171a0c000ea9538ea
- pristine_git_object: 5fc4002e0eb789a99d53328fd768ca4165011701
+ last_write_checksum: sha1:c77f5cff2fcd665fc1c804ebcde505a71b67245a
+ pristine_git_object: 574db8c80c3b9433ea0c4c49133c9d8eae0e6552
docs/operations/listexternalusersglobals.mdx:
id: 3e2e62682167
last_write_checksum: sha1:2d313c9d85897161bfc07e3690dd62a48a7b5b28
@@ -10764,8 +10768,8 @@ trackedFiles:
pristine_git_object: 3e38f1a929f7d6b1d6de74604aa87e3d8f010544
pyproject.toml:
id: 5d07e7d72637
- last_write_checksum: sha1:a47cc255adc52a027c04fdd7296b4bd5b6ac8c18
- pristine_git_object: b80981b1939d111c80f7f03b19c31d09cf70ff6c
+ last_write_checksum: sha1:80d96447577f36c39ac5a430102b74ec23bd727c
+ pristine_git_object: 1d7d2dd2e33c2cc456254bd409c6602682a6b16c
scripts/prepare_readme.py:
id: e0c5957a6035
last_write_checksum: sha1:77f44b60b98bc126557ec27391f91dfba764bb54
@@ -10792,8 +10796,8 @@ trackedFiles:
pristine_git_object: 86713cfea633e09d33b3d4e65281071fe20e6137
src/openrouter/_version.py:
id: d8d15ad6c586
- last_write_checksum: sha1:2944b4b1cc6add8381f856b0799c35f709502c3c
- pristine_git_object: 60a67b362ef4ba8c3c8ea646460a659482e7748d
+ last_write_checksum: sha1:893c7d1fb3156ec74b7aaaeb8c3f79b7a4df9568
+ pristine_git_object: 7c705ab99672990ae84fdafb09e65b2196e8bc4c
src/openrouter/alpha.py:
id: 306c4d93308d
last_write_checksum: sha1:80cc0f39649445431cc2247ed0e0765438467766
@@ -10840,8 +10844,8 @@ trackedFiles:
pristine_git_object: ad3d247954547814054c01989a2dff3d12b3e4e1
src/openrouter/components/__init__.py:
id: 81754e97b3f4
- last_write_checksum: sha1:56a6747e365c4882056dd693cabb01a7ad9724ff
- pristine_git_object: f74ec63ffe931137169b5c7032aa04075a77bff8
+ last_write_checksum: sha1:0306d5fda8ea78f931eacbd7e470ca26b626f5e8
+ pristine_git_object: 47676c451dd3c8bd1af0e2864b65641ea1f7c3ab
src/openrouter/components/aabenchmarkentry.py:
id: e2e0f0b48c82
last_write_checksum: sha1:fab4d9a24d2cea937bb749d46c5f83941e99d65c
@@ -12042,6 +12046,10 @@ trackedFiles:
id: 5ecad6212326
last_write_checksum: sha1:53ae856232196a956d66c6363cdaedc9f8abfe3a
pristine_git_object: 07e98d54e6a63a4f1e0908b73ce5f8d7e16234f0
+ src/openrouter/components/decisions.py:
+ id: 5d8a5ee323e1
+ last_write_checksum: sha1:cfa3429f0fb6d5ef8fcf554d880df7d3e6bbdc4c
+ pristine_git_object: 6c5a910e6d35cbfc3fe6aa18599837d3a9232ecf
src/openrouter/components/decisionsboxanswer.py:
id: 59a9ef1c30b7
last_write_checksum: sha1:301ee5be0345940b0f210f797e19e537e0f8126e
@@ -12146,6 +12154,10 @@ trackedFiles:
id: dc53aae5b171
last_write_checksum: sha1:44373dac3bf06bd752f0c54122949a024f70d3b5
pristine_git_object: 43ddb3328699a301a8948743ac0ead4a4a8ec776
+ src/openrouter/components/embeddings.py:
+ id: 81553b79cc50
+ last_write_checksum: sha1:f952180280fef71fe3fac4e41ba122af3b931f12
+ pristine_git_object: ade9cf4cc5e9473f422f8d873b30bb44e0d273b0
src/openrouter/components/endpointinfo.py:
id: ce049670b5ae
last_write_checksum: sha1:914f173c73fe1035e56c9acf4ad9e23555bde95a
@@ -12526,6 +12538,10 @@ trackedFiles:
id: 7a791a02cb5b
last_write_checksum: sha1:497f9be381527fd1ee961450a2364a898dba875b
pristine_git_object: 6b9a8990973466285f9b49b366bbc5fc1ae42e41
+ src/openrouter/components/imagegeneration.py:
+ id: 8a20a323529f
+ last_write_checksum: sha1:d86d0852fbda96fa56ee456e38b0f912c9e96132
+ pristine_git_object: fe042dd889e2f17d642f19b0d596cb3e53a7fce2
src/openrouter/components/imagegenerationproviderpreferences.py:
id: 100a82a54e2d
last_write_checksum: sha1:dc7720fb18eb12dab9ff6e599d31f08c0b196e43
@@ -12902,6 +12918,10 @@ trackedFiles:
id: d8236926ce4d
last_write_checksum: sha1:fa3012e6809aa0e6d5b94bddb3bd016f29f5b35e
pristine_git_object: c0f3bdf2b16b3a90399ef94d1cfbd3bdc7afe0be
+ src/openrouter/components/nativetools.py:
+ id: 248c6827f778
+ last_write_checksum: sha1:e0f9801526bb8c3dd9245a4fc2a68e29f4762a02
+ pristine_git_object: 8afefba911b3d7f74ec76de3aa7bc69b6e7c7ec2
src/openrouter/components/notfoundresponseerrordata.py:
id: 6ebceef7a039
last_write_checksum: sha1:bc01cbf5e3da855698de435b270930b4087377fe
@@ -13354,6 +13374,10 @@ trackedFiles:
id: 652397163aaa
last_write_checksum: sha1:a97289b7fd364d4d4d55eaceb452ec0891e97359
pristine_git_object: d4fad42e2a9de3a69093e54375086c2e23854ee0
+ src/openrouter/components/perflast30mbyworkload.py:
+ id: c577beb06381
+ last_write_checksum: sha1:b5d22f0aae68222d51270213f2726083be515ede
+ pristine_git_object: 98d5725c977ffb944f7f649e61ab86c3e96bbcf8
src/openrouter/components/perrequestlimits.py:
id: 5a170d7d1f2e
last_write_checksum: sha1:9b269bd87a1f704a0f0fa731da57cb35bc960674
@@ -13410,6 +13434,10 @@ trackedFiles:
id: 40414eada27a
last_write_checksum: sha1:0e241830bf9014e8ea814465c573711d8a7caa2c
pristine_git_object: 90bdb267893360608210843a5da0d5d68e80d41e
+ src/openrouter/components/pricing.py:
+ id: 33122e4b4dda
+ last_write_checksum: sha1:0f5b42e8b080ee41e906f4d920958ea5c498f2b7
+ pristine_git_object: de6dc2a054ce1e1cb41c32a17c390e6999eee242
src/openrouter/components/pricingoverride.py:
id: 8984e4cc7422
last_write_checksum: sha1:e12629320e02396a2aa1dfcbacd6873fba0d4aba
@@ -13532,8 +13560,8 @@ trackedFiles:
pristine_git_object: 1798ae9dd8c2e4b629bb99cc5c643827895e8231
src/openrouter/components/publicendpoint.py:
id: 848aa2ef9129
- last_write_checksum: sha1:db4e23bf4cda6a1829228c83e13d2645f9dd0325
- pristine_git_object: 60cb7bb398758f1f20e19e006ecbb22c537555d9
+ last_write_checksum: sha1:24c17812df5c49d3491117fe1c215c47aef83c73
+ pristine_git_object: 75eb8e640f7faf5486520c19b5fb131c44255306
src/openrouter/components/publicpricing.py:
id: 96d115d83cc5
last_write_checksum: sha1:fd8c320ac83b282eaf2405045329b55076d4311a
@@ -13542,6 +13570,10 @@ trackedFiles:
id: fc0a585024d6
last_write_checksum: sha1:a9d1074d4ce5c1fcb4cd2fb1ba593458d9174e5e
pristine_git_object: 280a4f38f716950fdf00b966409cef5a37d3d6b6
+ src/openrouter/components/publiczdrendpoint.py:
+ id: 96f5b682772d
+ last_write_checksum: sha1:b61dd30ae315ff73c1173295465ac8518c552fc0
+ pristine_git_object: ab5747e096bd23add5166d02c20d12026ca9a2bb
src/openrouter/components/quantization.py:
id: bde317b3d703
last_write_checksum: sha1:cc9c8d954733d128b53938fbc403bf97b064c09c
@@ -13650,6 +13682,10 @@ trackedFiles:
id: 2c5f5ceaf22d
last_write_checksum: sha1:ec9cf781e7744b582843bdc74f93003e1c19f8a8
pristine_git_object: 72b068484474cb51c64619e8bdbda4c77b64b5f3
+ src/openrouter/components/rerank.py:
+ id: ce0c58ad6b3f
+ last_write_checksum: sha1:a2abdafd0a7fa4e9845a0156f7b7aacf9fc0e045
+ pristine_git_object: e3740a8f28bfe73603bdae2b32153e8188c059ea
src/openrouter/components/responsehealingplugin.py:
id: 06608e027868
last_write_checksum: sha1:f4ee2caaa09379c52353f8920109f5e3e95f2274
@@ -13918,6 +13954,10 @@ trackedFiles:
id: e39bb8998edb
last_write_checksum: sha1:aae5b69a7dc7ced3af224d28b6ab485ad33ff2ef
pristine_git_object: 79b6d3487431628f261a66e552bd97668ded59a2
+ src/openrouter/components/stt.py:
+ id: 3552839c1a7e
+ last_write_checksum: sha1:ad5afe645af4f978313b3bd7d801781864903473
+ pristine_git_object: 2b0b14c1888a013b2d4afa3dda5c800fcfd760aa
src/openrouter/components/sttentity.py:
id: a0df8a8395ea
last_write_checksum: sha1:1acd9736217b336bd5e87f21401cd733b74585a9
@@ -14014,6 +14054,10 @@ trackedFiles:
id: 150a449e46de
last_write_checksum: sha1:56b0dc5aaacd994dfa1f16900a4fe1b4eea2f222
pristine_git_object: ffae73647f1060eeb9f46a4d331de6b9760dc5d9
+ src/openrouter/components/textgeneration.py:
+ id: 106a3b45e8ae
+ last_write_checksum: sha1:0e772f19c60d964f24ba3802431e57c548e7311b
+ pristine_git_object: 7b2f1c41bf7bb32cc9f2fe854978224f337c2ec8
src/openrouter/components/tokenexchangerequest.py:
id: 2359476f8b4b
last_write_checksum: sha1:90071f47bf240283f5e58701a2cf8e50fc96f94e
@@ -14066,6 +14110,10 @@ trackedFiles:
id: 88f4e4be9fc0
last_write_checksum: sha1:69e1f9d19ad27b82d882031c100f8a607344f8af
pristine_git_object: 1f8bea3c63592dc738f70d50eac8c69e2e755096
+ src/openrouter/components/tts.py:
+ id: 0f7a05134681
+ last_write_checksum: sha1:c91367caf26435698bd7e505a9fe3a08016040d5
+ pristine_git_object: 6c89d6bfeb6484b5aac7eafb35bf4e823dad5f74
src/openrouter/components/unauthorizedresponseerrordata.py:
id: 7d9755fc8395
last_write_checksum: sha1:fe0c623742ecc4cec29dbae705ca24e5813ccb8f
@@ -14102,6 +14150,10 @@ trackedFiles:
id: 189239ce6b4f
last_write_checksum: sha1:9d85897b7857707fb6a759aaa938f4b5bf5662c2
pristine_git_object: e1b94da161012480960c726a459b3fbd7c1a9bf4
+ src/openrouter/components/unknown.py:
+ id: 7f603dfcda35
+ last_write_checksum: sha1:e2a4ba97e9e9c2b710853acbc467284eb38dcc27
+ pristine_git_object: b85755f16ed8faf0cc73c8817824f369374844f2
src/openrouter/components/unprocessableentityresponseerrordata.py:
id: e8ca4a51f994
last_write_checksum: sha1:e97c277b49f4bb6bcfad8eef8a46b382730729a0
@@ -14226,6 +14278,10 @@ trackedFiles:
id: cbb498111508
last_write_checksum: sha1:1b9b952ac06a26237868303362363618c8252f0b
pristine_git_object: 70de1bfb3bfb30aaafa4e08251eb7a6cace15be8
+ src/openrouter/components/videogeneration.py:
+ id: 33005645f6fe
+ last_write_checksum: sha1:d9db0d60d9db6840b086366c6a34c856b845b28f
+ pristine_git_object: c2f15eb53f14024dfd1e620c52a564bf4682854f
src/openrouter/components/videogenerationrequest.py:
id: 70e3c9ff288c
last_write_checksum: sha1:5a9ecbd49cb4972cffd165ebbc98d6e27bfcf715
@@ -14904,8 +14960,8 @@ trackedFiles:
pristine_git_object: 6f25eff59336f48df0ac3c184cd0df135bb1212d
src/openrouter/operations/listendpointszdr.py:
id: 588bf206e92f
- last_write_checksum: sha1:dd1cc08d8779d71a9ad80e0ad764fea72b3fb846
- pristine_git_object: f5bd1f67dc835230e6d282e0500cbf3b5781eab4
+ last_write_checksum: sha1:453168ebe0434db364c9ced3c03e84a2c7e39048
+ pristine_git_object: 42e3e4915c3f33d5fe6b85029b1082e4ed1a646c
src/openrouter/operations/listexternalusers.py:
id: 01bd7badf844
last_write_checksum: sha1:05108a63aa626128619f0277f4f61b7c4590ec6a
@@ -15567,7 +15623,7 @@ examples:
speakeasy-default-list-endpoints-zdr:
responses:
"200":
- application/json: {"data": [{"context_length": 8192, "latency_last_30m": {"p50": 0.25, "p75": 0.35, "p90": 0.48, "p99": 0.85}, "max_completion_tokens": 4096, "max_prompt_tokens": 8192, "model_id": "openai/gpt-4", "model_name": "GPT-4", "name": "OpenAI: GPT-4", "native_tools": {}, "pricing": {"completion": "0.00006", "prompt": "0.00003"}, "provider_name": "OpenAI", "quantization": "fp16", "service_tier": "priority", "supported_parameters": ["temperature", "top_p", "max_tokens"], "supports_diarization": false, "supports_image_reference": false, "supports_implicit_caching": true, "supports_multiple_audio_references": false, "supports_tool_choice": {"auto": true, "function": true, "none": true, "required": true}, "supports_voice_cloning": false, "tag": "openai", "throughput_last_30m": {"p50": 45.2, "p75": 38.5, "p90": 28.3, "p99": 15.1}, "uptime_last_1d": 99.8, "uptime_last_30m": 99.5, "uptime_last_5m": 100}]}
+ application/json: {"data": [{"context_length": 8192, "latency_last_30m": {"p50": 0.25, "p75": 0.35, "p90": 0.48, "p99": 0.85}, "max_completion_tokens": 4096, "max_prompt_tokens": 8192, "model_id": "openai/gpt-4", "model_name": "GPT-4", "name": "OpenAI: GPT-4", "native_tools": {}, "pricing": {"completion": "0.00006", "prompt": "0.00003"}, "provider_name": "OpenAI", "quantization": "fp16", "service_tier": "priority", "supported_parameters": ["temperature", "top_p", "max_tokens"], "supports_diarization": false, "supports_image_reference": false, "supports_implicit_caching": true, "supports_multiple_audio_references": false, "supports_tool_choice": {"auto": true, "function": true, "none": true, "required": true}, "supports_voice_cloning": false, "tag": "openai", "throughput_last_30m": {"p50": 45.2, "p75": 38.5, "p90": 28.3, "p99": 15.1}, "uptime_last_1d": 99.8, "uptime_last_30m": 99.5, "uptime_last_5m": 100, "safety_retention": false}]}
"500":
application/json: {"error": {"code": 500, "message": "Internal Server Error"}}
"403":
@@ -19818,7 +19874,4 @@ examples:
examplesVersion: 1.0.2
releaseNotes: |
## Python SDK Changes:
- * `open_router.embeddings.list_models()`: `response.data[].endpoints` **Added**
- * `open_router.models.get()`: `response.data.endpoints` **Added**
- * `open_router.models.list()`: `response.data[].endpoints` **Added**
- * `open_router.models.list_for_user()`: `response.data[].endpoints` **Added**
+ * `open_router.endpoints.list_zdr_endpoints()`: `response.data[].safety_retention` **Added**
diff --git a/.speakeasy/gen.yaml b/.speakeasy/gen.yaml
index 5043924c..c7aee373 100644
--- a/.speakeasy/gen.yaml
+++ b/.speakeasy/gen.yaml
@@ -37,7 +37,7 @@ generation:
documentation: mintlify
preApplyUnionDiscriminators: true
python:
- version: 1.3.103
+ version: 1.3.104
additionalDependencies:
dev:
pytest: '>=8.3'
diff --git a/.speakeasy/out.openapi.yaml b/.speakeasy/out.openapi.yaml
index 0989d60c..95216b7b 100644
--- a/.speakeasy/out.openapi.yaml
+++ b/.speakeasy/out.openapi.yaml
@@ -11001,6 +11001,26 @@ components:
- 'debug'
- 'sequence_number'
type: 'object'
+ Decisions:
+ properties:
+ latency:
+ allOf:
+ - $ref: '#/components/schemas/PercentileStats'
+ - description: 'Latency percentiles in milliseconds for this workload. Image and video generation report full end-to-end generation time, because their raw latency only measures request acknowledgement; every other workload reports time to first token or result.'
+ request_count:
+ description: 'Total requests admitted for this workload in the window.'
+ type:
+ - 'integer'
+ - 'null'
+ throughput:
+ allOf:
+ - $ref: '#/components/schemas/PercentileStats'
+ - description: 'Throughput percentiles in tokens per second; pN is the speed that N% of requests reached or exceeded, so p90 is lower than p50. Only meaningful for text generation; null for workloads without token throughput.'
+ required:
+ - 'latency'
+ - 'throughput'
+ - 'request_count'
+ type: 'object'
DecisionsBoxAnswer:
properties:
box:
@@ -11672,6 +11692,26 @@ components:
- 'code'
- 'message'
type: 'object'
+ Embeddings:
+ properties:
+ latency:
+ allOf:
+ - $ref: '#/components/schemas/PercentileStats'
+ - description: 'Latency percentiles in milliseconds for this workload. Image and video generation report full end-to-end generation time, because their raw latency only measures request acknowledgement; every other workload reports time to first token or result.'
+ request_count:
+ description: 'Total requests admitted for this workload in the window.'
+ type:
+ - 'integer'
+ - 'null'
+ throughput:
+ allOf:
+ - $ref: '#/components/schemas/PercentileStats'
+ - description: 'Throughput percentiles in tokens per second; pN is the speed that N% of requests reached or exceeded, so p90 is lower than p50. Only meaningful for text generation; null for workloads without token throughput.'
+ required:
+ - 'latency'
+ - 'throughput'
+ - 'request_count'
+ type: 'object'
EndpointInfo:
example:
model: 'openai/gpt-4o'
@@ -15181,6 +15221,26 @@ components:
- 'b64_json'
- 'created'
type: 'object'
+ ImageGeneration:
+ properties:
+ latency:
+ allOf:
+ - $ref: '#/components/schemas/PercentileStats'
+ - description: 'Latency percentiles in milliseconds for this workload. Image and video generation report full end-to-end generation time, because their raw latency only measures request acknowledgement; every other workload reports time to first token or result.'
+ request_count:
+ description: 'Total requests admitted for this workload in the window.'
+ type:
+ - 'integer'
+ - 'null'
+ throughput:
+ allOf:
+ - $ref: '#/components/schemas/PercentileStats'
+ - description: 'Throughput percentiles in tokens per second; pN is the speed that N% of requests reached or exceeded, so p90 is lower than p50. Only meaningful for text generation; null for workloads without token throughput.'
+ required:
+ - 'latency'
+ - 'throughput'
+ - 'request_count'
+ type: 'object'
ImageGenerationProviderPreferences:
description: 'Provider routing preferences and provider-specific passthrough configuration.'
example:
@@ -19994,6 +20054,14 @@ components:
- 'description'
- 'tools'
type: 'object'
+ NativeTools:
+ properties:
+ type:
+ description: 'The provider tool type the request is translated to when this tool runs natively, e.g. `web_search_20260209` on Anthropic or `google_search` on Gemini.'
+ type: 'string'
+ required:
+ - 'type'
+ type: 'object'
NotFoundResponse:
description: 'Not Found - Resource does not exist'
example:
@@ -26366,6 +26434,29 @@ components:
- 'number'
- 'null'
type: 'object'
+ PerfLast30mByWorkload:
+ additionalProperties: false
+ description: 'Endpoint performance over the last 30 minutes, keyed by the kind of request served (e.g. `text_generation`, `image_generation`). Additive to the legacy singular latency and throughput fields; image and video generation report end-to-end latency. Only visible when authenticated with an API key or cookie.'
+ properties:
+ decisions:
+ $ref: '#/components/schemas/Decisions'
+ embeddings:
+ $ref: '#/components/schemas/Embeddings'
+ image_generation:
+ $ref: '#/components/schemas/ImageGeneration'
+ rerank:
+ $ref: '#/components/schemas/Rerank'
+ stt:
+ $ref: '#/components/schemas/STT'
+ text_generation:
+ $ref: '#/components/schemas/TextGeneration'
+ tts:
+ $ref: '#/components/schemas/TTS'
+ unknown:
+ $ref: '#/components/schemas/Unknown'
+ video_generation:
+ $ref: '#/components/schemas/VideoGeneration'
+ type: 'object'
PerRequestLimits:
description: 'Per-request token limits'
example:
@@ -26731,6 +26822,63 @@ components:
type:
- 'object'
- 'null'
+ Pricing:
+ properties:
+ audio:
+ description: 'Price in USD per audio input token'
+ type: 'string'
+ audio_output:
+ description: 'Price in USD per audio output token'
+ type: 'string'
+ completion:
+ description: 'Price in USD per token for completion (output) generation'
+ type: 'string'
+ discount:
+ description: 'Fractional discount applied to this endpoint''s pricing; the price is multiplied by (1 - discount) (0 = no discount, 1 = free)'
+ format: 'double'
+ type: 'number'
+ image:
+ description: 'Price in USD per input image'
+ type: 'string'
+ image_output:
+ description: 'Price in USD per output image'
+ type: 'string'
+ image_token:
+ description: 'Price in USD per image token'
+ type: 'string'
+ input_audio_cache:
+ description: 'Price in USD per cached audio input token'
+ type: 'string'
+ input_cache_read:
+ description: 'Price in USD per cached input token (read)'
+ type: 'string'
+ input_cache_write:
+ description: 'Price per cache-write token, in USD per token. For providers with multiple cache TTLs (e.g. Anthropic), this is the default (5-minute) cache-write rate.'
+ type: 'string'
+ input_cache_write_1h:
+ description: 'Price per 1-hour cache-write token, in USD per token. Only present for providers that price an extended (1-hour) cache TTL separately, such as Anthropic.'
+ type: 'string'
+ internal_reasoning:
+ description: 'Price in USD per internal reasoning token'
+ type: 'string'
+ overrides:
+ description: 'Conditional overrides of the base pricing (e.g. long-context or time-based pricing). An entry applies when all of its condition fields (e.g. min_prompt_tokens, or the utc_start/utc_end time window) match the request; among applicable entries, later entries win per key; price keys absent from an entry inherit the base price. The top-level pricing keys always reflect the price that applies under default conditions.'
+ items:
+ $ref: '#/components/schemas/PricingOverride'
+ type: 'array'
+ prompt:
+ description: 'Price in USD per token for prompt (input) processing'
+ type: 'string'
+ request:
+ description: 'Price in USD per request'
+ type: 'string'
+ web_search:
+ description: 'Price in USD per web search'
+ type: 'string'
+ required:
+ - 'prompt'
+ - 'completion'
+ type: 'object'
PricingOverride:
description: 'A conditional override of the base pricing. An entry applies only when all of its condition fields (e.g. min_prompt_tokens, or the utc_start/utc_end time window) match the request; among applicable entries, later entries win per price key; price keys absent from an entry inherit the base price.'
example:
@@ -28609,260 +28757,16 @@ components:
type: 'string'
native_tools:
additionalProperties:
- properties:
- type:
- description: 'The provider tool type the request is translated to when this tool runs natively, e.g. `web_search_20260209` on Anthropic or `google_search` on Gemini.'
- type: 'string'
- required:
- - 'type'
- type: 'object'
+ $ref: '#/components/schemas/NativeTools'
description: 'The server tools this endpoint accepts as the provider''s own built-in tool (`engine: "native"`) instead of an OpenRouter engine, keyed by canonical `openrouter:*` name. Each value names the provider tool type the request is translated to. Where that tool runs (provider-side, or returned to the client as with Anthropic bash) is documented per tool. Empty when the provider has none.'
example:
openrouter:web_search:
type: 'web_search_20260209'
type: 'object'
perf_last_30m_by_workload:
- additionalProperties: false
- description: 'Endpoint performance over the last 30 minutes, keyed by the kind of request served (e.g. `text_generation`, `image_generation`). Additive to the legacy singular latency and throughput fields; image and video generation report end-to-end latency. Only visible when authenticated with an API key or cookie.'
- properties:
- decisions:
- properties:
- latency:
- allOf:
- - $ref: '#/components/schemas/PercentileStats'
- - description: 'Latency percentiles in milliseconds for this workload. Image and video generation report full end-to-end generation time, because their raw latency only measures request acknowledgement; every other workload reports time to first token or result.'
- request_count:
- description: 'Total requests admitted for this workload in the window.'
- type:
- - 'integer'
- - 'null'
- throughput:
- allOf:
- - $ref: '#/components/schemas/PercentileStats'
- - description: 'Throughput percentiles in tokens per second; pN is the speed that N% of requests reached or exceeded, so p90 is lower than p50. Only meaningful for text generation; null for workloads without token throughput.'
- required:
- - 'latency'
- - 'throughput'
- - 'request_count'
- type: 'object'
- embeddings:
- properties:
- latency:
- allOf:
- - $ref: '#/components/schemas/PercentileStats'
- - description: 'Latency percentiles in milliseconds for this workload. Image and video generation report full end-to-end generation time, because their raw latency only measures request acknowledgement; every other workload reports time to first token or result.'
- request_count:
- description: 'Total requests admitted for this workload in the window.'
- type:
- - 'integer'
- - 'null'
- throughput:
- allOf:
- - $ref: '#/components/schemas/PercentileStats'
- - description: 'Throughput percentiles in tokens per second; pN is the speed that N% of requests reached or exceeded, so p90 is lower than p50. Only meaningful for text generation; null for workloads without token throughput.'
- required:
- - 'latency'
- - 'throughput'
- - 'request_count'
- type: 'object'
- image_generation:
- properties:
- latency:
- allOf:
- - $ref: '#/components/schemas/PercentileStats'
- - description: 'Latency percentiles in milliseconds for this workload. Image and video generation report full end-to-end generation time, because their raw latency only measures request acknowledgement; every other workload reports time to first token or result.'
- request_count:
- description: 'Total requests admitted for this workload in the window.'
- type:
- - 'integer'
- - 'null'
- throughput:
- allOf:
- - $ref: '#/components/schemas/PercentileStats'
- - description: 'Throughput percentiles in tokens per second; pN is the speed that N% of requests reached or exceeded, so p90 is lower than p50. Only meaningful for text generation; null for workloads without token throughput.'
- required:
- - 'latency'
- - 'throughput'
- - 'request_count'
- type: 'object'
- rerank:
- properties:
- latency:
- allOf:
- - $ref: '#/components/schemas/PercentileStats'
- - description: 'Latency percentiles in milliseconds for this workload. Image and video generation report full end-to-end generation time, because their raw latency only measures request acknowledgement; every other workload reports time to first token or result.'
- request_count:
- description: 'Total requests admitted for this workload in the window.'
- type:
- - 'integer'
- - 'null'
- throughput:
- allOf:
- - $ref: '#/components/schemas/PercentileStats'
- - description: 'Throughput percentiles in tokens per second; pN is the speed that N% of requests reached or exceeded, so p90 is lower than p50. Only meaningful for text generation; null for workloads without token throughput.'
- required:
- - 'latency'
- - 'throughput'
- - 'request_count'
- type: 'object'
- stt:
- properties:
- latency:
- allOf:
- - $ref: '#/components/schemas/PercentileStats'
- - description: 'Latency percentiles in milliseconds for this workload. Image and video generation report full end-to-end generation time, because their raw latency only measures request acknowledgement; every other workload reports time to first token or result.'
- request_count:
- description: 'Total requests admitted for this workload in the window.'
- type:
- - 'integer'
- - 'null'
- throughput:
- allOf:
- - $ref: '#/components/schemas/PercentileStats'
- - description: 'Throughput percentiles in tokens per second; pN is the speed that N% of requests reached or exceeded, so p90 is lower than p50. Only meaningful for text generation; null for workloads without token throughput.'
- required:
- - 'latency'
- - 'throughput'
- - 'request_count'
- type: 'object'
- text_generation:
- properties:
- latency:
- allOf:
- - $ref: '#/components/schemas/PercentileStats'
- - description: 'Latency percentiles in milliseconds for this workload. Image and video generation report full end-to-end generation time, because their raw latency only measures request acknowledgement; every other workload reports time to first token or result.'
- request_count:
- description: 'Total requests admitted for this workload in the window.'
- type:
- - 'integer'
- - 'null'
- throughput:
- allOf:
- - $ref: '#/components/schemas/PercentileStats'
- - description: 'Throughput percentiles in tokens per second; pN is the speed that N% of requests reached or exceeded, so p90 is lower than p50. Only meaningful for text generation; null for workloads without token throughput.'
- required:
- - 'latency'
- - 'throughput'
- - 'request_count'
- type: 'object'
- tts:
- properties:
- latency:
- allOf:
- - $ref: '#/components/schemas/PercentileStats'
- - description: 'Latency percentiles in milliseconds for this workload. Image and video generation report full end-to-end generation time, because their raw latency only measures request acknowledgement; every other workload reports time to first token or result.'
- request_count:
- description: 'Total requests admitted for this workload in the window.'
- type:
- - 'integer'
- - 'null'
- throughput:
- allOf:
- - $ref: '#/components/schemas/PercentileStats'
- - description: 'Throughput percentiles in tokens per second; pN is the speed that N% of requests reached or exceeded, so p90 is lower than p50. Only meaningful for text generation; null for workloads without token throughput.'
- required:
- - 'latency'
- - 'throughput'
- - 'request_count'
- type: 'object'
- unknown:
- properties:
- latency:
- allOf:
- - $ref: '#/components/schemas/PercentileStats'
- - description: 'Latency percentiles in milliseconds for this workload. Image and video generation report full end-to-end generation time, because their raw latency only measures request acknowledgement; every other workload reports time to first token or result.'
- request_count:
- description: 'Total requests admitted for this workload in the window.'
- type:
- - 'integer'
- - 'null'
- throughput:
- allOf:
- - $ref: '#/components/schemas/PercentileStats'
- - description: 'Throughput percentiles in tokens per second; pN is the speed that N% of requests reached or exceeded, so p90 is lower than p50. Only meaningful for text generation; null for workloads without token throughput.'
- required:
- - 'latency'
- - 'throughput'
- - 'request_count'
- type: 'object'
- video_generation:
- properties:
- latency:
- allOf:
- - $ref: '#/components/schemas/PercentileStats'
- - description: 'Latency percentiles in milliseconds for this workload. Image and video generation report full end-to-end generation time, because their raw latency only measures request acknowledgement; every other workload reports time to first token or result.'
- request_count:
- description: 'Total requests admitted for this workload in the window.'
- type:
- - 'integer'
- - 'null'
- throughput:
- allOf:
- - $ref: '#/components/schemas/PercentileStats'
- - description: 'Throughput percentiles in tokens per second; pN is the speed that N% of requests reached or exceeded, so p90 is lower than p50. Only meaningful for text generation; null for workloads without token throughput.'
- required:
- - 'latency'
- - 'throughput'
- - 'request_count'
- type: 'object'
- type: 'object'
+ $ref: '#/components/schemas/PerfLast30mByWorkload'
pricing:
- properties:
- audio:
- description: 'Price in USD per audio input token'
- type: 'string'
- audio_output:
- description: 'Price in USD per audio output token'
- type: 'string'
- completion:
- description: 'Price in USD per token for completion (output) generation'
- type: 'string'
- discount:
- description: 'Fractional discount applied to this endpoint''s pricing; the price is multiplied by (1 - discount) (0 = no discount, 1 = free)'
- format: 'double'
- type: 'number'
- image:
- description: 'Price in USD per input image'
- type: 'string'
- image_output:
- description: 'Price in USD per output image'
- type: 'string'
- image_token:
- description: 'Price in USD per image token'
- type: 'string'
- input_audio_cache:
- description: 'Price in USD per cached audio input token'
- type: 'string'
- input_cache_read:
- description: 'Price in USD per cached input token (read)'
- type: 'string'
- input_cache_write:
- description: 'Price per cache-write token, in USD per token. For providers with multiple cache TTLs (e.g. Anthropic), this is the default (5-minute) cache-write rate.'
- type: 'string'
- input_cache_write_1h:
- description: 'Price per 1-hour cache-write token, in USD per token. Only present for providers that price an extended (1-hour) cache TTL separately, such as Anthropic.'
- type: 'string'
- internal_reasoning:
- description: 'Price in USD per internal reasoning token'
- type: 'string'
- overrides:
- description: 'Conditional overrides of the base pricing (e.g. long-context or time-based pricing). An entry applies when all of its condition fields (e.g. min_prompt_tokens, or the utc_start/utc_end time window) match the request; among applicable entries, later entries win per key; price keys absent from an entry inherit the base price. The top-level pricing keys always reflect the price that applies under default conditions.'
- items:
- $ref: '#/components/schemas/PricingOverride'
- type: 'array'
- prompt:
- description: 'Price in USD per token for prompt (input) processing'
- type: 'string'
- request:
- description: 'Price in USD per request'
- type: 'string'
- web_search:
- description: 'Price in USD per web search'
- type: 'string'
- required:
- - 'prompt'
- - 'completion'
- type: 'object'
+ $ref: '#/components/schemas/Pricing'
provider_name:
$ref: '#/components/schemas/ProviderName'
quantization:
@@ -29017,6 +28921,56 @@ components:
- 'string'
- 'null'
x-speakeasy-unknown-values: allow
+ PublicZdrEndpoint:
+ allOf:
+ - $ref: '#/components/schemas/PublicEndpoint'
+ - properties:
+ safety_retention:
+ description: 'Whether the endpoint uses Safety Retention: prompts are not retained by default, but the provider may retain prompts its safety classifiers flag. A ZDR-enforced request reaches these endpoints only when the account allows Safety Retention and no applied guardrail disallows it.'
+ example: false
+ type: 'boolean'
+ required:
+ - 'safety_retention'
+ type: 'object'
+ description: 'An endpoint whose data policy does not retain prompts by default'
+ example:
+ context_length: 1048576
+ latency_last_30m: null
+ max_completion_tokens: 65535
+ max_prompt_tokens: null
+ model_id: 'google/gemini-2.5-flash'
+ model_name: 'Gemini 2.5 Flash'
+ name: 'Google: Gemini 2.5 Flash'
+ native_tools: {}
+ pricing:
+ completion: '0.0000025'
+ image: '0'
+ prompt: '0.0000003'
+ request: '0'
+ provider_name: 'Google'
+ quantization: null
+ safety_retention: true
+ service_tier: null
+ status: 0
+ supported_parameters:
+ - 'temperature'
+ - 'top_p'
+ - 'max_tokens'
+ supports_diarization: false
+ supports_image_reference: false
+ supports_implicit_caching: true
+ supports_multiple_audio_references: false
+ supports_tool_choice:
+ auto: true
+ function: true
+ none: true
+ required: true
+ supports_voice_cloning: false
+ tag: 'google-vertex'
+ throughput_last_30m: null
+ uptime_last_1d: 99.8
+ uptime_last_30m: 99.5
+ uptime_last_5m: 100
Quantization:
enum:
- 'int4'
@@ -29563,6 +29517,26 @@ components:
- 'code'
- 'message'
type: 'object'
+ Rerank:
+ properties:
+ latency:
+ allOf:
+ - $ref: '#/components/schemas/PercentileStats'
+ - description: 'Latency percentiles in milliseconds for this workload. Image and video generation report full end-to-end generation time, because their raw latency only measures request acknowledgement; every other workload reports time to first token or result.'
+ request_count:
+ description: 'Total requests admitted for this workload in the window.'
+ type:
+ - 'integer'
+ - 'null'
+ throughput:
+ allOf:
+ - $ref: '#/components/schemas/PercentileStats'
+ - description: 'Throughput percentiles in tokens per second; pN is the speed that N% of requests reached or exceeded, so p90 is lower than p50. Only meaningful for text generation; null for workloads without token throughput.'
+ required:
+ - 'latency'
+ - 'throughput'
+ - 'request_count'
+ type: 'object'
ResponseHealingPlugin:
example:
enabled: true
@@ -31624,6 +31598,26 @@ components:
- 111
logprob: -0.5
token: 'Hello'
+ STT:
+ properties:
+ latency:
+ allOf:
+ - $ref: '#/components/schemas/PercentileStats'
+ - description: 'Latency percentiles in milliseconds for this workload. Image and video generation report full end-to-end generation time, because their raw latency only measures request acknowledgement; every other workload reports time to first token or result.'
+ request_count:
+ description: 'Total requests admitted for this workload in the window.'
+ type:
+ - 'integer'
+ - 'null'
+ throughput:
+ allOf:
+ - $ref: '#/components/schemas/PercentileStats'
+ - description: 'Throughput percentiles in tokens per second; pN is the speed that N% of requests reached or exceeded, so p90 is lower than p50. Only meaningful for text generation; null for workloads without token throughput.'
+ required:
+ - 'latency'
+ - 'throughput'
+ - 'request_count'
+ type: 'object'
STTEntity:
description: 'A detected entity, returned when the provider runs entity detection'
example:
@@ -32474,6 +32468,26 @@ components:
example:
format:
type: 'text'
+ TextGeneration:
+ properties:
+ latency:
+ allOf:
+ - $ref: '#/components/schemas/PercentileStats'
+ - description: 'Latency percentiles in milliseconds for this workload. Image and video generation report full end-to-end generation time, because their raw latency only measures request acknowledgement; every other workload reports time to first token or result.'
+ request_count:
+ description: 'Total requests admitted for this workload in the window.'
+ type:
+ - 'integer'
+ - 'null'
+ throughput:
+ allOf:
+ - $ref: '#/components/schemas/PercentileStats'
+ - description: 'Throughput percentiles in tokens per second; pN is the speed that N% of requests reached or exceeded, so p90 is lower than p50. Only meaningful for text generation; null for workloads without token throughput.'
+ required:
+ - 'latency'
+ - 'throughput'
+ - 'request_count'
+ type: 'object'
TokenExchangeRequest:
description: 'RFC 8693 token exchange request body (application/x-www-form-urlencoded).'
example:
@@ -32923,6 +32937,26 @@ components:
- 'string'
- 'null'
x-speakeasy-unknown-values: allow
+ TTS:
+ properties:
+ latency:
+ allOf:
+ - $ref: '#/components/schemas/PercentileStats'
+ - description: 'Latency percentiles in milliseconds for this workload. Image and video generation report full end-to-end generation time, because their raw latency only measures request acknowledgement; every other workload reports time to first token or result.'
+ request_count:
+ description: 'Total requests admitted for this workload in the window.'
+ type:
+ - 'integer'
+ - 'null'
+ throughput:
+ allOf:
+ - $ref: '#/components/schemas/PercentileStats'
+ - description: 'Throughput percentiles in tokens per second; pN is the speed that N% of requests reached or exceeded, so p90 is lower than p50. Only meaningful for text generation; null for workloads without token throughput.'
+ required:
+ - 'latency'
+ - 'throughput'
+ - 'request_count'
+ type: 'object'
UnauthorizedResponse:
description: 'Unauthorized - Authentication required or invalid credentials'
example:
@@ -33432,6 +33466,26 @@ components:
- 'reasoning_effort'
- 'temperature'
type: 'object'
+ Unknown:
+ properties:
+ latency:
+ allOf:
+ - $ref: '#/components/schemas/PercentileStats'
+ - description: 'Latency percentiles in milliseconds for this workload. Image and video generation report full end-to-end generation time, because their raw latency only measures request acknowledgement; every other workload reports time to first token or result.'
+ request_count:
+ description: 'Total requests admitted for this workload in the window.'
+ type:
+ - 'integer'
+ - 'null'
+ throughput:
+ allOf:
+ - $ref: '#/components/schemas/PercentileStats'
+ - description: 'Throughput percentiles in tokens per second; pN is the speed that N% of requests reached or exceeded, so p90 is lower than p50. Only meaningful for text generation; null for workloads without token throughput.'
+ required:
+ - 'latency'
+ - 'throughput'
+ - 'request_count'
+ type: 'object'
UnprocessableEntityResponse:
description: 'Unprocessable Entity - Semantic validation failure'
example:
@@ -35016,6 +35070,26 @@ components:
- 'value'
- 'hosts'
type: 'object'
+ VideoGeneration:
+ properties:
+ latency:
+ allOf:
+ - $ref: '#/components/schemas/PercentileStats'
+ - description: 'Latency percentiles in milliseconds for this workload. Image and video generation report full end-to-end generation time, because their raw latency only measures request acknowledgement; every other workload reports time to first token or result.'
+ request_count:
+ description: 'Total requests admitted for this workload in the window.'
+ type:
+ - 'integer'
+ - 'null'
+ throughput:
+ allOf:
+ - $ref: '#/components/schemas/PercentileStats'
+ - description: 'Throughput percentiles in tokens per second; pN is the speed that N% of requests reached or exceeded, so p90 is lower than p50. Only meaningful for text generation; null for workloads without token throughput.'
+ required:
+ - 'latency'
+ - 'throughput'
+ - 'request_count'
+ type: 'object'
VideoGenerationRequest:
example:
aspect_ratio: '16:9'
@@ -41094,6 +41168,7 @@ paths:
request: '0'
provider_name: 'OpenAI'
quantization: 'fp16'
+ safety_retention: false
status: 0
supported_parameters:
- 'temperature'
@@ -41135,6 +41210,7 @@ paths:
request: '0'
provider_name: 'OpenAI'
quantization: 'fp16'
+ safety_retention: false
status: 0
supported_parameters:
- 'temperature'
@@ -41157,7 +41233,7 @@ paths:
properties:
data:
items:
- $ref: '#/components/schemas/PublicEndpoint'
+ $ref: '#/components/schemas/PublicZdrEndpoint'
type: 'array'
required:
- 'data'
diff --git a/.speakeasy/workflow.lock b/.speakeasy/workflow.lock
index 537451d7..a929f5df 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:e694f4549e00867798b00834fbd31906ce3579b94a641f0cf0a505160fa427e8
- sourceBlobDigest: sha256:c98e501126c39c5d724e5cf6ccdedb42c9ba794e838f27e7df736e6cbd9b0eff
+ sourceRevisionDigest: sha256:f2ec7c45abce35a4ee889ecf63e1b7205c07047ad07a01b36cc700933c2f7738
+ sourceBlobDigest: sha256:2e4abbb634949f2276fd2e3e2da11e201ba84a654602baf9c60002e28cc8f5f7
tags:
- latest
- 1.0.0
@@ -11,10 +11,10 @@ targets:
open-router:
source: OpenRouter API
sourceNamespace: open-router-chat-completions-api
- sourceRevisionDigest: sha256:e694f4549e00867798b00834fbd31906ce3579b94a641f0cf0a505160fa427e8
- sourceBlobDigest: sha256:c98e501126c39c5d724e5cf6ccdedb42c9ba794e838f27e7df736e6cbd9b0eff
+ sourceRevisionDigest: sha256:f2ec7c45abce35a4ee889ecf63e1b7205c07047ad07a01b36cc700933c2f7738
+ sourceBlobDigest: sha256:2e4abbb634949f2276fd2e3e2da11e201ba84a654602baf9c60002e28cc8f5f7
codeSamplesNamespace: open-router-python-code-samples
- codeSamplesRevisionDigest: sha256:3740a7d9bfd42d34b8191df9db9036b30a241191ab34d95f2fff30bff41e2f19
+ codeSamplesRevisionDigest: sha256:3f4be72cb1b4642b401e6a72de66c4501e20d8b0880c1017f5825f9a033a58af
workflow:
workflowVersion: 1.0.0
speakeasyVersion: 1.803.2
diff --git a/RELEASES.md b/RELEASES.md
index 6c2ca09d..45c4752f 100644
--- a/RELEASES.md
+++ b/RELEASES.md
@@ -3799,4 +3799,14 @@ Based on:
### Generated
- [python v1.3.103] .
### Releases
-- [PyPI v1.3.103] https://pypi.org/project/openrouter/1.3.103 - .
\ No newline at end of file
+- [PyPI v1.3.103] https://pypi.org/project/openrouter/1.3.103 - .
+
+## 2026-10-30 20:23:39
+### Changes
+Based on:
+- OpenAPI Doc
+- Speakeasy CLI 1.803.2 (2.950.13) https://github.com/speakeasy-api/speakeasy
+### Generated
+- [python v1.3.104] .
+### Releases
+- [PyPI v1.3.104] https://pypi.org/project/openrouter/1.3.104 - .
\ No newline at end of file
diff --git a/docs/components/publiczdrendpoint.mdx b/docs/components/publiczdrendpoint.mdx
new file mode 100644
index 00000000..1802fa7f
--- /dev/null
+++ b/docs/components/publiczdrendpoint.mdx
@@ -0,0 +1,38 @@
+---
+title: "PublicZdrEndpoint"
+---
+
+An endpoint whose data policy does not retain prompts by default
+
+
+## Fields
+
+| Field | Type | Required | Description | Example |
+| ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| `context_length` | *int* | ✔️ | N/A | |
+| `latency_last_30m` | [Nullable[components.PercentileStats]](../components/percentilestats.mdx) | ✔️ | Latency percentiles in milliseconds over the last 30 minutes. Latency measures time to first token. Only visible when authenticated with an API key or cookie; returns null for unauthenticated requests. | \{
"p50": 25.5,
"p75": 35.2,
"p90": 48.7,
"p99": 85.3
} |
+| `max_completion_tokens` | *Nullable[int]* | ✔️ | Maximum completion tokens for this endpoint. Input and output tokens share the context window, so the effective maximum output for a request is further limited by the context remaining after input tokens. | |
+| `max_prompt_tokens` | *Nullable[int]* | ✔️ | N/A | |
+| `model_id` | *str* | ✔️ | The unique identifier for the model (permaslug) | openai/gpt-4 |
+| `model_name` | *str* | ✔️ | N/A | |
+| `name` | *str* | ✔️ | N/A | |
+| `native_tools` | Dict[str, [components.NativeTools](../components/nativetools.mdx)] | ✔️ | The server tools this endpoint accepts as the provider's own built-in tool (`engine: "native"`) instead of an OpenRouter engine, keyed by canonical `openrouter:*` name. Each value names the provider tool type the request is translated to. Where that tool runs (provider-side, or returned to the client as with Anthropic bash) is documented per tool. Empty when the provider has none. | \{
"openrouter:web_search": \{
"type": "web_search_20260209"
}
} |
+| `perf_last_30m_by_workload` | [Optional[components.PerfLast30mByWorkload]](../components/perflast30mbyworkload.mdx) | ➖ | Endpoint performance over the last 30 minutes, keyed by the kind of request served (e.g. `text_generation`, `image_generation`). Additive to the legacy singular latency and throughput fields; image and video generation report end-to-end latency. Only visible when authenticated with an API key or cookie. | |
+| `pricing` | [components.Pricing](../components/pricing.mdx) | ✔️ | N/A | |
+| `provider_name` | [components.ProviderName](../components/providername.mdx) | ✔️ | N/A | OpenAI |
+| `quantization` | [Nullable[components.Quantization]](../components/quantization.mdx) | ✔️ | N/A | fp16 |
+| `service_tier` | [Nullable[components.PublicServiceTier]](../components/publicservicetier.mdx) | ✔️ | The service tier this endpoint sells, or null for a standard endpoint. The same value whether the provider selects the tier with a request parameter or with a dedicated model id. Always the canonical tier: priority covers the fast request alias and the turbo, highspeed, and prime provider model-id spellings, none of which this field reports. | priority |
+| `status` | [Optional[components.EndpointStatus]](../components/endpointstatus.mdx) | ➖ | N/A | 0 |
+| `supported_parameters` | List[[components.Parameter](../components/parameter.mdx)] | ✔️ | N/A | |
+| `supports_diarization` | *bool* | ✔️ | Whether this STT endpoint can label each transcript segment with a speaker (speaker diarization). False when the endpoint has not declared support. | |
+| `supports_image_reference` | *Optional[bool]* | ➖ | Whether this TTS endpoint accepts an `image_url` reference describing the desired voice. Requests carrying an image reference are only routed to endpoints where this is true. | |
+| `supports_implicit_caching` | *bool* | ✔️ | N/A | |
+| `supports_multiple_audio_references` | *Optional[bool]* | ➖ | Whether this TTS endpoint accepts more than one `input_audio` reference clip per request. Requests carrying several clips are only routed to endpoints where this is true. | |
+| `supports_tool_choice` | [components.ToolChoiceSupport](../components/toolchoicesupport.mdx) | ✔️ | Per-variant `tool_choice` support. `tool_choice` in `supported_parameters` only says the parameter is accepted; these flags say which of its values passed testing. | \{
"auto": true,
"function": true,
"none": true,
"required": true
} |
+| `supports_voice_cloning` | *Optional[bool]* | ➖ | Whether this TTS endpoint accepts inline reference audio (`input_references`) for stateless voice cloning. Requests carrying reference audio are only routed to endpoints where this is true. | |
+| `tag` | *str* | ✔️ | N/A | |
+| `throughput_last_30m` | [Nullable[components.PercentileStats]](../components/percentilestats.mdx) | ✔️ | N/A | \{
"p50": 25.5,
"p75": 35.2,
"p90": 48.7,
"p99": 85.3
} |
+| `uptime_last_1d` | *Nullable[float]* | ✔️ | Uptime percentage over the last day: the share of minutes in which at least 80% of provider attempts succeeded, counting only minutes with 10 or more attempts. Rate-limited and caller-caused failures are excluded. Null when no minute had enough traffic. | |
+| `uptime_last_30m` | *Nullable[float]* | ✔️ | N/A | |
+| `uptime_last_5m` | *Nullable[float]* | ✔️ | Uptime percentage over the last 5 minutes: the share of minutes in which at least 80% of provider attempts succeeded, counting only minutes with 10 or more attempts. Rate-limited and caller-caused failures are excluded. Null when no minute had enough traffic. | |
+| `safety_retention` | *bool* | ✔️ | Whether the endpoint uses Safety Retention: prompts are not retained by default, but the provider may retain prompts its safety classifiers flag. A ZDR-enforced request reaches these endpoints only when the account allows Safety Retention and no applied guardrail disallows it. | false |
\ No newline at end of file
diff --git a/docs/operations/listendpointszdrresponse.mdx b/docs/operations/listendpointszdrresponse.mdx
index 5fc4002e..574db8c8 100644
--- a/docs/operations/listendpointszdrresponse.mdx
+++ b/docs/operations/listendpointszdrresponse.mdx
@@ -7,6 +7,6 @@ Returns a list of endpoints
## Fields
-| Field | Type | Required | Description |
-| ------------------------------------------------------------------ | ------------------------------------------------------------------ | ------------------------------------------------------------------ | ------------------------------------------------------------------ |
-| `data` | List[[components.PublicEndpoint](../components/publicendpoint.mdx)] | ✔️ | N/A |
\ No newline at end of file
+| Field | Type | Required | Description |
+| ------------------------------------------------------------------------ | ------------------------------------------------------------------------ | ------------------------------------------------------------------------ | ------------------------------------------------------------------------ |
+| `data` | List[[components.PublicZdrEndpoint](../components/publiczdrendpoint.mdx)] | ✔️ | N/A |
\ No newline at end of file
diff --git a/pyproject.toml b/pyproject.toml
index b80981b1..1d7d2dd2 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,6 +1,6 @@
[project]
name = "openrouter"
-version = "1.3.103"
+version = "1.3.104"
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 60a67b36..7c705ab9 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.103"
+__version__: str = "1.3.104"
__openapi_doc_version__: str = "1.0.0"
__gen_version__: str = "2.950.13"
-__user_agent__: str = "speakeasy-sdk/python 1.3.103 2.950.13 1.0.0 openrouter"
+__user_agent__: str = "speakeasy-sdk/python 1.3.104 2.950.13 1.0.0 openrouter"
try:
if __package__ is not None:
diff --git a/src/openrouter/components/__init__.py b/src/openrouter/components/__init__.py
index f74ec63f..47676c45 100644
--- a/src/openrouter/components/__init__.py
+++ b/src/openrouter/components/__init__.py
@@ -1625,6 +1625,7 @@
DebugEventType,
DebugEventTypedDict,
)
+ from .decisions import Decisions, DecisionsTypedDict
from .decisionsboxanswer import (
Box,
BoxTypedDict,
@@ -1794,6 +1795,7 @@
EdgeNetworkTimeoutResponseErrorData,
EdgeNetworkTimeoutResponseErrorDataTypedDict,
)
+ from .embeddings import Embeddings, EmbeddingsTypedDict
from .endpointinfo import EndpointInfo, EndpointInfoTypedDict
from .endpointsmetadata import EndpointsMetadata, EndpointsMetadataTypedDict
from .endpointstatus import EndpointStatus
@@ -2290,6 +2292,7 @@
ImageGenCompletedEventType,
ImageGenCompletedEventTypedDict,
)
+ from .imagegeneration import ImageGeneration, ImageGenerationTypedDict
from .imagegenerationproviderpreferences import (
ImageGenerationProviderPreferences,
ImageGenerationProviderPreferencesIgnore,
@@ -2905,6 +2908,7 @@
NamespaceToolTypedDict,
UnknownNamespaceToolTool,
)
+ from .nativetools import NativeTools, NativeToolsTypedDict
from .notfoundresponseerrordata import (
NotFoundResponseErrorData,
NotFoundResponseErrorDataTypedDict,
@@ -3644,6 +3648,10 @@
PercentileThroughputCutoffs,
PercentileThroughputCutoffsTypedDict,
)
+ from .perflast30mbyworkload import (
+ PerfLast30mByWorkload,
+ PerfLast30mByWorkloadTypedDict,
+ )
from .perrequestlimits import PerRequestLimits, PerRequestLimitsTypedDict
from .pipelinestage import PipelineStage, PipelineStageTypedDict
from .pipelinestagetype import PipelineStageType
@@ -3689,6 +3697,7 @@
PreviewWebSearchUserLocationType,
PreviewWebSearchUserLocationTypedDict,
)
+ from .pricing import Pricing, PricingTypedDict
from .pricingoverride import PricingOverride, PricingOverrideTypedDict, UtcDay
from .privateendpoint import PrivateEndpoint, PrivateEndpointTypedDict
from .privateendpointactivation import (
@@ -3803,36 +3812,10 @@
ProviderSortConfig,
ProviderSortConfigTypedDict,
)
- from .publicendpoint import (
- Decisions,
- DecisionsTypedDict,
- Embeddings,
- EmbeddingsTypedDict,
- ImageGeneration,
- ImageGenerationTypedDict,
- NativeTools,
- NativeToolsTypedDict,
- PerfLast30mByWorkload,
- PerfLast30mByWorkloadTypedDict,
- Pricing,
- PricingTypedDict,
- PublicEndpoint,
- PublicEndpointTypedDict,
- Rerank,
- RerankTypedDict,
- STT,
- STTTypedDict,
- TTS,
- TTSTypedDict,
- TextGeneration,
- TextGenerationTypedDict,
- Unknown,
- UnknownTypedDict,
- VideoGeneration,
- VideoGenerationTypedDict,
- )
+ from .publicendpoint import PublicEndpoint, PublicEndpointTypedDict
from .publicpricing import PublicPricing, PublicPricingTypedDict
from .publicservicetier import PublicServiceTier
+ from .publiczdrendpoint import PublicZdrEndpoint, PublicZdrEndpointTypedDict
from .quantization import Quantization
from .rangecapability import (
RangeCapability,
@@ -3943,6 +3926,7 @@
RequestTimeoutResponseErrorData,
RequestTimeoutResponseErrorDataTypedDict,
)
+ from .rerank import Rerank, RerankTypedDict
from .responsehealingplugin import (
ResponseHealingPlugin,
ResponseHealingPluginID,
@@ -4225,6 +4209,7 @@
StreamLogprobTopLogprob,
StreamLogprobTopLogprobTypedDict,
)
+ from .stt import STT, STTTypedDict
from .sttentity import STTEntity, STTEntityTypedDict
from .sttinlineinputaudio import STTInlineInputAudio, STTInlineInputAudioTypedDict
from .sttinputaudio import STTInputAudio, STTInputAudioTypedDict
@@ -4303,6 +4288,7 @@
TextExtendedConfigTypedDict,
Verbosity,
)
+ from .textgeneration import TextGeneration, TextGenerationTypedDict
from .tokenexchangerequest import (
GrantType,
RequestedTokenType,
@@ -4366,6 +4352,7 @@
from .topproviderinfo import TopProviderInfo, TopProviderInfoTypedDict
from .traceconfig import TraceConfig, TraceConfigTypedDict
from .truncation import Truncation
+ from .tts import TTS, TTSTypedDict
from .unauthorizedresponseerrordata import (
UnauthorizedResponseErrorData,
UnauthorizedResponseErrorDataTypedDict,
@@ -4416,6 +4403,7 @@
UnifiedBenchmarksSearchRunConfig,
UnifiedBenchmarksSearchRunConfigTypedDict,
)
+ from .unknown import Unknown, UnknownTypedDict
from .unprocessableentityresponseerrordata import (
UnprocessableEntityResponseErrorData,
UnprocessableEntityResponseErrorDataTypedDict,
@@ -4591,6 +4579,7 @@
VaultSecretWriteRequest,
VaultSecretWriteRequestTypedDict,
)
+ from .videogeneration import VideoGeneration, VideoGenerationTypedDict
from .videogenerationrequest import (
VideoGenerationRequest,
VideoGenerationRequestAspectRatio,
@@ -7395,6 +7384,8 @@
"PublicPricing",
"PublicPricingTypedDict",
"PublicServiceTier",
+ "PublicZdrEndpoint",
+ "PublicZdrEndpointTypedDict",
"Purpose",
"Quantization",
"Questions",
@@ -9341,6 +9332,8 @@
"DebugEventTimingsTypedDict": ".debugevent",
"DebugEventType": ".debugevent",
"DebugEventTypedDict": ".debugevent",
+ "Decisions": ".decisions",
+ "DecisionsTypedDict": ".decisions",
"Box": ".decisionsboxanswer",
"BoxTypedDict": ".decisionsboxanswer",
"DecisionsBoxAnswer": ".decisionsboxanswer",
@@ -9461,6 +9454,8 @@
"EasyInputMessageTypedDict": ".easyinputmessage",
"EdgeNetworkTimeoutResponseErrorData": ".edgenetworktimeoutresponseerrordata",
"EdgeNetworkTimeoutResponseErrorDataTypedDict": ".edgenetworktimeoutresponseerrordata",
+ "Embeddings": ".embeddings",
+ "EmbeddingsTypedDict": ".embeddings",
"EndpointInfo": ".endpointinfo",
"EndpointInfoTypedDict": ".endpointinfo",
"EndpointsMetadata": ".endpointsmetadata",
@@ -9835,6 +9830,8 @@
"ImageGenCompletedEvent": ".imagegencompletedevent",
"ImageGenCompletedEventType": ".imagegencompletedevent",
"ImageGenCompletedEventTypedDict": ".imagegencompletedevent",
+ "ImageGeneration": ".imagegeneration",
+ "ImageGenerationTypedDict": ".imagegeneration",
"ImageGenerationProviderPreferences": ".imagegenerationproviderpreferences",
"ImageGenerationProviderPreferencesIgnore": ".imagegenerationproviderpreferences",
"ImageGenerationProviderPreferencesIgnoreTypedDict": ".imagegenerationproviderpreferences",
@@ -10335,6 +10332,8 @@
"NamespaceToolType": ".namespacetool",
"NamespaceToolTypedDict": ".namespacetool",
"UnknownNamespaceToolTool": ".namespacetool",
+ "NativeTools": ".nativetools",
+ "NativeToolsTypedDict": ".nativetools",
"NotFoundResponseErrorData": ".notfoundresponseerrordata",
"NotFoundResponseErrorDataTypedDict": ".notfoundresponseerrordata",
"ErrorEnum": ".oautherrorresponse",
@@ -10884,6 +10883,8 @@
"PercentileStatsTypedDict": ".percentilestats",
"PercentileThroughputCutoffs": ".percentilethroughputcutoffs",
"PercentileThroughputCutoffsTypedDict": ".percentilethroughputcutoffs",
+ "PerfLast30mByWorkload": ".perflast30mbyworkload",
+ "PerfLast30mByWorkloadTypedDict": ".perflast30mbyworkload",
"PerRequestLimits": ".perrequestlimits",
"PerRequestLimitsTypedDict": ".perrequestlimits",
"PipelineStage": ".pipelinestage",
@@ -10917,6 +10918,8 @@
"PreviewWebSearchUserLocation": ".preview_websearchuserlocation",
"PreviewWebSearchUserLocationType": ".preview_websearchuserlocation",
"PreviewWebSearchUserLocationTypedDict": ".preview_websearchuserlocation",
+ "Pricing": ".pricing",
+ "PricingTypedDict": ".pricing",
"PricingOverride": ".pricingoverride",
"PricingOverrideTypedDict": ".pricingoverride",
"UtcDay": ".pricingoverride",
@@ -10997,35 +11000,13 @@
"Partition": ".providersortconfig",
"ProviderSortConfig": ".providersortconfig",
"ProviderSortConfigTypedDict": ".providersortconfig",
- "Decisions": ".publicendpoint",
- "DecisionsTypedDict": ".publicendpoint",
- "Embeddings": ".publicendpoint",
- "EmbeddingsTypedDict": ".publicendpoint",
- "ImageGeneration": ".publicendpoint",
- "ImageGenerationTypedDict": ".publicendpoint",
- "NativeTools": ".publicendpoint",
- "NativeToolsTypedDict": ".publicendpoint",
- "PerfLast30mByWorkload": ".publicendpoint",
- "PerfLast30mByWorkloadTypedDict": ".publicendpoint",
- "Pricing": ".publicendpoint",
- "PricingTypedDict": ".publicendpoint",
"PublicEndpoint": ".publicendpoint",
"PublicEndpointTypedDict": ".publicendpoint",
- "Rerank": ".publicendpoint",
- "RerankTypedDict": ".publicendpoint",
- "STT": ".publicendpoint",
- "STTTypedDict": ".publicendpoint",
- "TTS": ".publicendpoint",
- "TTSTypedDict": ".publicendpoint",
- "TextGeneration": ".publicendpoint",
- "TextGenerationTypedDict": ".publicendpoint",
- "Unknown": ".publicendpoint",
- "UnknownTypedDict": ".publicendpoint",
- "VideoGeneration": ".publicendpoint",
- "VideoGenerationTypedDict": ".publicendpoint",
"PublicPricing": ".publicpricing",
"PublicPricingTypedDict": ".publicpricing",
"PublicServiceTier": ".publicservicetier",
+ "PublicZdrEndpoint": ".publiczdrendpoint",
+ "PublicZdrEndpointTypedDict": ".publiczdrendpoint",
"Quantization": ".quantization",
"RangeCapability": ".rangecapability",
"RangeCapabilityType": ".rangecapability",
@@ -11097,6 +11078,8 @@
"RefusalDoneEventTypedDict": ".refusaldoneevent",
"RequestTimeoutResponseErrorData": ".requesttimeoutresponseerrordata",
"RequestTimeoutResponseErrorDataTypedDict": ".requesttimeoutresponseerrordata",
+ "Rerank": ".rerank",
+ "RerankTypedDict": ".rerank",
"ResponseHealingPlugin": ".responsehealingplugin",
"ResponseHealingPluginID": ".responsehealingplugin",
"ResponseHealingPluginTypedDict": ".responsehealingplugin",
@@ -11302,6 +11285,8 @@
"StreamLogprobTypedDict": ".streamlogprob",
"StreamLogprobTopLogprob": ".streamlogprobtoplogprob",
"StreamLogprobTopLogprobTypedDict": ".streamlogprobtoplogprob",
+ "STT": ".stt",
+ "STTTypedDict": ".stt",
"STTEntity": ".sttentity",
"STTEntityTypedDict": ".sttentity",
"STTInlineInputAudio": ".sttinlineinputaudio",
@@ -11366,6 +11351,8 @@
"TextExtendedConfig": ".textextendedconfig",
"TextExtendedConfigTypedDict": ".textextendedconfig",
"Verbosity": ".textextendedconfig",
+ "TextGeneration": ".textgeneration",
+ "TextGenerationTypedDict": ".textgeneration",
"GrantType": ".tokenexchangerequest",
"RequestedTokenType": ".tokenexchangerequest",
"SubjectTokenType": ".tokenexchangerequest",
@@ -11416,6 +11403,8 @@
"TraceConfig": ".traceconfig",
"TraceConfigTypedDict": ".traceconfig",
"Truncation": ".truncation",
+ "TTS": ".tts",
+ "TTSTypedDict": ".tts",
"UnauthorizedResponseErrorData": ".unauthorizedresponseerrordata",
"UnauthorizedResponseErrorDataTypedDict": ".unauthorizedresponseerrordata",
"UnifiedBenchmarkPricing": ".unifiedbenchmarkpricing",
@@ -11448,6 +11437,8 @@
"UnifiedBenchmarksSearchItemTypedDict": ".unifiedbenchmarkssearchitem",
"UnifiedBenchmarksSearchRunConfig": ".unifiedbenchmarkssearchrunconfig",
"UnifiedBenchmarksSearchRunConfigTypedDict": ".unifiedbenchmarkssearchrunconfig",
+ "Unknown": ".unknown",
+ "UnknownTypedDict": ".unknown",
"UnprocessableEntityResponseErrorData": ".unprocessableentityresponseerrordata",
"UnprocessableEntityResponseErrorDataTypedDict": ".unprocessableentityresponseerrordata",
"UpdateBYOKKeyRequest": ".updatebyokkeyrequest",
@@ -11571,6 +11562,8 @@
"VaultSecretResponseTypedDict": ".vaultsecretresponse",
"VaultSecretWriteRequest": ".vaultsecretwriterequest",
"VaultSecretWriteRequestTypedDict": ".vaultsecretwriterequest",
+ "VideoGeneration": ".videogeneration",
+ "VideoGenerationTypedDict": ".videogeneration",
"VideoGenerationRequest": ".videogenerationrequest",
"VideoGenerationRequestAspectRatio": ".videogenerationrequest",
"VideoGenerationRequestOptions": ".videogenerationrequest",
diff --git a/src/openrouter/components/decisions.py b/src/openrouter/components/decisions.py
new file mode 100644
index 00000000..6c5a910e
--- /dev/null
+++ b/src/openrouter/components/decisions.py
@@ -0,0 +1,37 @@
+"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT."""
+
+from __future__ import annotations
+from .percentilestats import PercentileStats, PercentileStatsTypedDict
+from openrouter.types import BaseModel, Nullable, UNSET_SENTINEL
+from pydantic import model_serializer
+from typing_extensions import TypedDict
+
+
+class DecisionsTypedDict(TypedDict):
+ latency: Nullable[PercentileStatsTypedDict]
+ request_count: Nullable[int]
+ r"""Total requests admitted for this workload in the window."""
+ throughput: Nullable[PercentileStatsTypedDict]
+
+
+class Decisions(BaseModel):
+ latency: Nullable[PercentileStats]
+
+ request_count: Nullable[int]
+ r"""Total requests admitted for this workload in the window."""
+
+ throughput: Nullable[PercentileStats]
+
+ @model_serializer(mode="wrap")
+ def serialize_model(self, handler):
+ serialized = handler(self)
+ m = {}
+
+ for n, f in type(self).model_fields.items():
+ k = f.alias or n
+ val = serialized.get(k, serialized.get(n))
+
+ if val != UNSET_SENTINEL:
+ m[k] = val
+
+ return m
diff --git a/src/openrouter/components/embeddings.py b/src/openrouter/components/embeddings.py
new file mode 100644
index 00000000..ade9cf4c
--- /dev/null
+++ b/src/openrouter/components/embeddings.py
@@ -0,0 +1,37 @@
+"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT."""
+
+from __future__ import annotations
+from .percentilestats import PercentileStats, PercentileStatsTypedDict
+from openrouter.types import BaseModel, Nullable, UNSET_SENTINEL
+from pydantic import model_serializer
+from typing_extensions import TypedDict
+
+
+class EmbeddingsTypedDict(TypedDict):
+ latency: Nullable[PercentileStatsTypedDict]
+ request_count: Nullable[int]
+ r"""Total requests admitted for this workload in the window."""
+ throughput: Nullable[PercentileStatsTypedDict]
+
+
+class Embeddings(BaseModel):
+ latency: Nullable[PercentileStats]
+
+ request_count: Nullable[int]
+ r"""Total requests admitted for this workload in the window."""
+
+ throughput: Nullable[PercentileStats]
+
+ @model_serializer(mode="wrap")
+ def serialize_model(self, handler):
+ serialized = handler(self)
+ m = {}
+
+ for n, f in type(self).model_fields.items():
+ k = f.alias or n
+ val = serialized.get(k, serialized.get(n))
+
+ if val != UNSET_SENTINEL:
+ m[k] = val
+
+ return m
diff --git a/src/openrouter/components/imagegeneration.py b/src/openrouter/components/imagegeneration.py
new file mode 100644
index 00000000..fe042dd8
--- /dev/null
+++ b/src/openrouter/components/imagegeneration.py
@@ -0,0 +1,37 @@
+"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT."""
+
+from __future__ import annotations
+from .percentilestats import PercentileStats, PercentileStatsTypedDict
+from openrouter.types import BaseModel, Nullable, UNSET_SENTINEL
+from pydantic import model_serializer
+from typing_extensions import TypedDict
+
+
+class ImageGenerationTypedDict(TypedDict):
+ latency: Nullable[PercentileStatsTypedDict]
+ request_count: Nullable[int]
+ r"""Total requests admitted for this workload in the window."""
+ throughput: Nullable[PercentileStatsTypedDict]
+
+
+class ImageGeneration(BaseModel):
+ latency: Nullable[PercentileStats]
+
+ request_count: Nullable[int]
+ r"""Total requests admitted for this workload in the window."""
+
+ throughput: Nullable[PercentileStats]
+
+ @model_serializer(mode="wrap")
+ def serialize_model(self, handler):
+ serialized = handler(self)
+ m = {}
+
+ for n, f in type(self).model_fields.items():
+ k = f.alias or n
+ val = serialized.get(k, serialized.get(n))
+
+ if val != UNSET_SENTINEL:
+ m[k] = val
+
+ return m
diff --git a/src/openrouter/components/nativetools.py b/src/openrouter/components/nativetools.py
new file mode 100644
index 00000000..8afefba9
--- /dev/null
+++ b/src/openrouter/components/nativetools.py
@@ -0,0 +1,15 @@
+"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT."""
+
+from __future__ import annotations
+from openrouter.types import BaseModel
+from typing_extensions import TypedDict
+
+
+class NativeToolsTypedDict(TypedDict):
+ type: str
+ r"""The provider tool type the request is translated to when this tool runs natively, e.g. `web_search_20260209` on Anthropic or `google_search` on Gemini."""
+
+
+class NativeTools(BaseModel):
+ type: str
+ r"""The provider tool type the request is translated to when this tool runs natively, e.g. `web_search_20260209` on Anthropic or `google_search` on Gemini."""
diff --git a/src/openrouter/components/perflast30mbyworkload.py b/src/openrouter/components/perflast30mbyworkload.py
new file mode 100644
index 00000000..98d5725c
--- /dev/null
+++ b/src/openrouter/components/perflast30mbyworkload.py
@@ -0,0 +1,80 @@
+"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT."""
+
+from __future__ import annotations
+from .decisions import Decisions, DecisionsTypedDict
+from .embeddings import Embeddings, EmbeddingsTypedDict
+from .imagegeneration import ImageGeneration, ImageGenerationTypedDict
+from .rerank import Rerank, RerankTypedDict
+from .stt import STT, STTTypedDict
+from .textgeneration import TextGeneration, TextGenerationTypedDict
+from .tts import TTS, TTSTypedDict
+from .unknown import Unknown, UnknownTypedDict
+from .videogeneration import VideoGeneration, VideoGenerationTypedDict
+from openrouter.types import BaseModel, UNSET_SENTINEL
+from pydantic import model_serializer
+from typing import Optional
+from typing_extensions import NotRequired, TypedDict
+
+
+class PerfLast30mByWorkloadTypedDict(TypedDict):
+ r"""Endpoint performance over the last 30 minutes, keyed by the kind of request served (e.g. `text_generation`, `image_generation`). Additive to the legacy singular latency and throughput fields; image and video generation report end-to-end latency. Only visible when authenticated with an API key or cookie."""
+
+ decisions: NotRequired[DecisionsTypedDict]
+ embeddings: NotRequired[EmbeddingsTypedDict]
+ image_generation: NotRequired[ImageGenerationTypedDict]
+ rerank: NotRequired[RerankTypedDict]
+ stt: NotRequired[STTTypedDict]
+ text_generation: NotRequired[TextGenerationTypedDict]
+ tts: NotRequired[TTSTypedDict]
+ unknown: NotRequired[UnknownTypedDict]
+ video_generation: NotRequired[VideoGenerationTypedDict]
+
+
+class PerfLast30mByWorkload(BaseModel):
+ r"""Endpoint performance over the last 30 minutes, keyed by the kind of request served (e.g. `text_generation`, `image_generation`). Additive to the legacy singular latency and throughput fields; image and video generation report end-to-end latency. Only visible when authenticated with an API key or cookie."""
+
+ decisions: Optional[Decisions] = None
+
+ embeddings: Optional[Embeddings] = None
+
+ image_generation: Optional[ImageGeneration] = None
+
+ rerank: Optional[Rerank] = None
+
+ stt: Optional[STT] = None
+
+ text_generation: Optional[TextGeneration] = None
+
+ tts: Optional[TTS] = None
+
+ unknown: Optional[Unknown] = None
+
+ video_generation: Optional[VideoGeneration] = None
+
+ @model_serializer(mode="wrap")
+ def serialize_model(self, handler):
+ optional_fields = set(
+ [
+ "decisions",
+ "embeddings",
+ "image_generation",
+ "rerank",
+ "stt",
+ "text_generation",
+ "tts",
+ "unknown",
+ "video_generation",
+ ]
+ )
+ serialized = handler(self)
+ m = {}
+
+ for n, f in type(self).model_fields.items():
+ k = f.alias or n
+ val = serialized.get(k, serialized.get(n))
+
+ if val != UNSET_SENTINEL:
+ if val is not None or k not in optional_fields:
+ m[k] = val
+
+ return m
diff --git a/src/openrouter/components/pricing.py b/src/openrouter/components/pricing.py
new file mode 100644
index 00000000..de6dc2a0
--- /dev/null
+++ b/src/openrouter/components/pricing.py
@@ -0,0 +1,126 @@
+"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT."""
+
+from __future__ import annotations
+from .pricingoverride import PricingOverride, PricingOverrideTypedDict
+from openrouter.types import BaseModel, UNSET_SENTINEL
+from pydantic import model_serializer
+from typing import List, Optional
+from typing_extensions import NotRequired, TypedDict
+
+
+class PricingTypedDict(TypedDict):
+ completion: str
+ r"""Price in USD per token for completion (output) generation"""
+ prompt: str
+ r"""Price in USD per token for prompt (input) processing"""
+ audio: NotRequired[str]
+ r"""Price in USD per audio input token"""
+ audio_output: NotRequired[str]
+ r"""Price in USD per audio output token"""
+ discount: NotRequired[float]
+ r"""Fractional discount applied to this endpoint's pricing; the price is multiplied by (1 - discount) (0 = no discount, 1 = free)"""
+ image: NotRequired[str]
+ r"""Price in USD per input image"""
+ image_output: NotRequired[str]
+ r"""Price in USD per output image"""
+ image_token: NotRequired[str]
+ r"""Price in USD per image token"""
+ input_audio_cache: NotRequired[str]
+ r"""Price in USD per cached audio input token"""
+ input_cache_read: NotRequired[str]
+ r"""Price in USD per cached input token (read)"""
+ input_cache_write: NotRequired[str]
+ r"""Price per cache-write token, in USD per token. For providers with multiple cache TTLs (e.g. Anthropic), this is the default (5-minute) cache-write rate."""
+ input_cache_write_1h: NotRequired[str]
+ r"""Price per 1-hour cache-write token, in USD per token. Only present for providers that price an extended (1-hour) cache TTL separately, such as Anthropic."""
+ internal_reasoning: NotRequired[str]
+ r"""Price in USD per internal reasoning token"""
+ overrides: NotRequired[List[PricingOverrideTypedDict]]
+ r"""Conditional overrides of the base pricing (e.g. long-context or time-based pricing). An entry applies when all of its condition fields (e.g. min_prompt_tokens, or the utc_start/utc_end time window) match the request; among applicable entries, later entries win per key; price keys absent from an entry inherit the base price. The top-level pricing keys always reflect the price that applies under default conditions."""
+ request: NotRequired[str]
+ r"""Price in USD per request"""
+ web_search: NotRequired[str]
+ r"""Price in USD per web search"""
+
+
+class Pricing(BaseModel):
+ completion: str
+ r"""Price in USD per token for completion (output) generation"""
+
+ prompt: str
+ r"""Price in USD per token for prompt (input) processing"""
+
+ audio: Optional[str] = None
+ r"""Price in USD per audio input token"""
+
+ audio_output: Optional[str] = None
+ r"""Price in USD per audio output token"""
+
+ discount: Optional[float] = None
+ r"""Fractional discount applied to this endpoint's pricing; the price is multiplied by (1 - discount) (0 = no discount, 1 = free)"""
+
+ image: Optional[str] = None
+ r"""Price in USD per input image"""
+
+ image_output: Optional[str] = None
+ r"""Price in USD per output image"""
+
+ image_token: Optional[str] = None
+ r"""Price in USD per image token"""
+
+ input_audio_cache: Optional[str] = None
+ r"""Price in USD per cached audio input token"""
+
+ input_cache_read: Optional[str] = None
+ r"""Price in USD per cached input token (read)"""
+
+ input_cache_write: Optional[str] = None
+ r"""Price per cache-write token, in USD per token. For providers with multiple cache TTLs (e.g. Anthropic), this is the default (5-minute) cache-write rate."""
+
+ input_cache_write_1h: Optional[str] = None
+ r"""Price per 1-hour cache-write token, in USD per token. Only present for providers that price an extended (1-hour) cache TTL separately, such as Anthropic."""
+
+ internal_reasoning: Optional[str] = None
+ r"""Price in USD per internal reasoning token"""
+
+ overrides: Optional[List[PricingOverride]] = None
+ r"""Conditional overrides of the base pricing (e.g. long-context or time-based pricing). An entry applies when all of its condition fields (e.g. min_prompt_tokens, or the utc_start/utc_end time window) match the request; among applicable entries, later entries win per key; price keys absent from an entry inherit the base price. The top-level pricing keys always reflect the price that applies under default conditions."""
+
+ request: Optional[str] = None
+ r"""Price in USD per request"""
+
+ web_search: Optional[str] = None
+ r"""Price in USD per web search"""
+
+ @model_serializer(mode="wrap")
+ def serialize_model(self, handler):
+ optional_fields = set(
+ [
+ "audio",
+ "audio_output",
+ "discount",
+ "image",
+ "image_output",
+ "image_token",
+ "input_audio_cache",
+ "input_cache_read",
+ "input_cache_write",
+ "input_cache_write_1h",
+ "internal_reasoning",
+ "overrides",
+ "request",
+ "web_search",
+ ]
+ )
+ serialized = handler(self)
+ m = {}
+
+ for n, f in type(self).model_fields.items():
+ k = f.alias or n
+ val = serialized.get(k, serialized.get(n))
+
+ if val != UNSET_SENTINEL:
+ if val is not None or k not in optional_fields:
+ m[k] = val
+
+ return m
diff --git a/src/openrouter/components/publicendpoint.py b/src/openrouter/components/publicendpoint.py
index 60cb7bb3..75eb8e64 100644
--- a/src/openrouter/components/publicendpoint.py
+++ b/src/openrouter/components/publicendpoint.py
@@ -2,9 +2,11 @@
from __future__ import annotations
from .endpointstatus import EndpointStatus
+from .nativetools import NativeTools, NativeToolsTypedDict
from .parameter import Parameter
from .percentilestats import PercentileStats, PercentileStatsTypedDict
-from .pricingoverride import PricingOverride, PricingOverrideTypedDict
+from .perflast30mbyworkload import PerfLast30mByWorkload, PerfLast30mByWorkloadTypedDict
+from .pricing import Pricing, PricingTypedDict
from .providername import ProviderName
from .publicservicetier import PublicServiceTier
from .quantization import Quantization
@@ -15,468 +17,6 @@
from typing_extensions import NotRequired, TypedDict
-class NativeToolsTypedDict(TypedDict):
- type: str
- r"""The provider tool type the request is translated to when this tool runs natively, e.g. `web_search_20260209` on Anthropic or `google_search` on Gemini."""
-
-
-class NativeTools(BaseModel):
- type: str
- r"""The provider tool type the request is translated to when this tool runs natively, e.g. `web_search_20260209` on Anthropic or `google_search` on Gemini."""
-
-
-class DecisionsTypedDict(TypedDict):
- latency: Nullable[PercentileStatsTypedDict]
- request_count: Nullable[int]
- r"""Total requests admitted for this workload in the window."""
- throughput: Nullable[PercentileStatsTypedDict]
-
-
-class Decisions(BaseModel):
- latency: Nullable[PercentileStats]
-
- request_count: Nullable[int]
- r"""Total requests admitted for this workload in the window."""
-
- throughput: Nullable[PercentileStats]
-
- @model_serializer(mode="wrap")
- def serialize_model(self, handler):
- serialized = handler(self)
- m = {}
-
- for n, f in type(self).model_fields.items():
- k = f.alias or n
- val = serialized.get(k, serialized.get(n))
-
- if val != UNSET_SENTINEL:
- m[k] = val
-
- return m
-
-
-class EmbeddingsTypedDict(TypedDict):
- latency: Nullable[PercentileStatsTypedDict]
- request_count: Nullable[int]
- r"""Total requests admitted for this workload in the window."""
- throughput: Nullable[PercentileStatsTypedDict]
-
-
-class Embeddings(BaseModel):
- latency: Nullable[PercentileStats]
-
- request_count: Nullable[int]
- r"""Total requests admitted for this workload in the window."""
-
- throughput: Nullable[PercentileStats]
-
- @model_serializer(mode="wrap")
- def serialize_model(self, handler):
- serialized = handler(self)
- m = {}
-
- for n, f in type(self).model_fields.items():
- k = f.alias or n
- val = serialized.get(k, serialized.get(n))
-
- if val != UNSET_SENTINEL:
- m[k] = val
-
- return m
-
-
-class ImageGenerationTypedDict(TypedDict):
- latency: Nullable[PercentileStatsTypedDict]
- request_count: Nullable[int]
- r"""Total requests admitted for this workload in the window."""
- throughput: Nullable[PercentileStatsTypedDict]
-
-
-class ImageGeneration(BaseModel):
- latency: Nullable[PercentileStats]
-
- request_count: Nullable[int]
- r"""Total requests admitted for this workload in the window."""
-
- throughput: Nullable[PercentileStats]
-
- @model_serializer(mode="wrap")
- def serialize_model(self, handler):
- serialized = handler(self)
- m = {}
-
- for n, f in type(self).model_fields.items():
- k = f.alias or n
- val = serialized.get(k, serialized.get(n))
-
- if val != UNSET_SENTINEL:
- m[k] = val
-
- return m
-
-
-class RerankTypedDict(TypedDict):
- latency: Nullable[PercentileStatsTypedDict]
- request_count: Nullable[int]
- r"""Total requests admitted for this workload in the window."""
- throughput: Nullable[PercentileStatsTypedDict]
-
-
-class Rerank(BaseModel):
- latency: Nullable[PercentileStats]
-
- request_count: Nullable[int]
- r"""Total requests admitted for this workload in the window."""
-
- throughput: Nullable[PercentileStats]
-
- @model_serializer(mode="wrap")
- def serialize_model(self, handler):
- serialized = handler(self)
- m = {}
-
- for n, f in type(self).model_fields.items():
- k = f.alias or n
- val = serialized.get(k, serialized.get(n))
-
- if val != UNSET_SENTINEL:
- m[k] = val
-
- return m
-
-
-class STTTypedDict(TypedDict):
- latency: Nullable[PercentileStatsTypedDict]
- request_count: Nullable[int]
- r"""Total requests admitted for this workload in the window."""
- throughput: Nullable[PercentileStatsTypedDict]
-
-
-class STT(BaseModel):
- latency: Nullable[PercentileStats]
-
- request_count: Nullable[int]
- r"""Total requests admitted for this workload in the window."""
-
- throughput: Nullable[PercentileStats]
-
- @model_serializer(mode="wrap")
- def serialize_model(self, handler):
- serialized = handler(self)
- m = {}
-
- for n, f in type(self).model_fields.items():
- k = f.alias or n
- val = serialized.get(k, serialized.get(n))
-
- if val != UNSET_SENTINEL:
- m[k] = val
-
- return m
-
-
-class TextGenerationTypedDict(TypedDict):
- latency: Nullable[PercentileStatsTypedDict]
- request_count: Nullable[int]
- r"""Total requests admitted for this workload in the window."""
- throughput: Nullable[PercentileStatsTypedDict]
-
-
-class TextGeneration(BaseModel):
- latency: Nullable[PercentileStats]
-
- request_count: Nullable[int]
- r"""Total requests admitted for this workload in the window."""
-
- throughput: Nullable[PercentileStats]
-
- @model_serializer(mode="wrap")
- def serialize_model(self, handler):
- serialized = handler(self)
- m = {}
-
- for n, f in type(self).model_fields.items():
- k = f.alias or n
- val = serialized.get(k, serialized.get(n))
-
- if val != UNSET_SENTINEL:
- m[k] = val
-
- return m
-
-
-class TTSTypedDict(TypedDict):
- latency: Nullable[PercentileStatsTypedDict]
- request_count: Nullable[int]
- r"""Total requests admitted for this workload in the window."""
- throughput: Nullable[PercentileStatsTypedDict]
-
-
-class TTS(BaseModel):
- latency: Nullable[PercentileStats]
-
- request_count: Nullable[int]
- r"""Total requests admitted for this workload in the window."""
-
- throughput: Nullable[PercentileStats]
-
- @model_serializer(mode="wrap")
- def serialize_model(self, handler):
- serialized = handler(self)
- m = {}
-
- for n, f in type(self).model_fields.items():
- k = f.alias or n
- val = serialized.get(k, serialized.get(n))
-
- if val != UNSET_SENTINEL:
- m[k] = val
-
- return m
-
-
-class UnknownTypedDict(TypedDict):
- latency: Nullable[PercentileStatsTypedDict]
- request_count: Nullable[int]
- r"""Total requests admitted for this workload in the window."""
- throughput: Nullable[PercentileStatsTypedDict]
-
-
-class Unknown(BaseModel):
- latency: Nullable[PercentileStats]
-
- request_count: Nullable[int]
- r"""Total requests admitted for this workload in the window."""
-
- throughput: Nullable[PercentileStats]
-
- @model_serializer(mode="wrap")
- def serialize_model(self, handler):
- serialized = handler(self)
- m = {}
-
- for n, f in type(self).model_fields.items():
- k = f.alias or n
- val = serialized.get(k, serialized.get(n))
-
- if val != UNSET_SENTINEL:
- m[k] = val
-
- return m
-
-
-class VideoGenerationTypedDict(TypedDict):
- latency: Nullable[PercentileStatsTypedDict]
- request_count: Nullable[int]
- r"""Total requests admitted for this workload in the window."""
- throughput: Nullable[PercentileStatsTypedDict]
-
-
-class VideoGeneration(BaseModel):
- latency: Nullable[PercentileStats]
-
- request_count: Nullable[int]
- r"""Total requests admitted for this workload in the window."""
-
- throughput: Nullable[PercentileStats]
-
- @model_serializer(mode="wrap")
- def serialize_model(self, handler):
- serialized = handler(self)
- m = {}
-
- for n, f in type(self).model_fields.items():
- k = f.alias or n
- val = serialized.get(k, serialized.get(n))
-
- if val != UNSET_SENTINEL:
- m[k] = val
-
- return m
-
-
-class PerfLast30mByWorkloadTypedDict(TypedDict):
- r"""Endpoint performance over the last 30 minutes, keyed by the kind of request served (e.g. `text_generation`, `image_generation`). Additive to the legacy singular latency and throughput fields; image and video generation report end-to-end latency. Only visible when authenticated with an API key or cookie."""
-
- decisions: NotRequired[DecisionsTypedDict]
- embeddings: NotRequired[EmbeddingsTypedDict]
- image_generation: NotRequired[ImageGenerationTypedDict]
- rerank: NotRequired[RerankTypedDict]
- stt: NotRequired[STTTypedDict]
- text_generation: NotRequired[TextGenerationTypedDict]
- tts: NotRequired[TTSTypedDict]
- unknown: NotRequired[UnknownTypedDict]
- video_generation: NotRequired[VideoGenerationTypedDict]
-
-
-class PerfLast30mByWorkload(BaseModel):
- r"""Endpoint performance over the last 30 minutes, keyed by the kind of request served (e.g. `text_generation`, `image_generation`). Additive to the legacy singular latency and throughput fields; image and video generation report end-to-end latency. Only visible when authenticated with an API key or cookie."""
-
- decisions: Optional[Decisions] = None
-
- embeddings: Optional[Embeddings] = None
-
- image_generation: Optional[ImageGeneration] = None
-
- rerank: Optional[Rerank] = None
-
- stt: Optional[STT] = None
-
- text_generation: Optional[TextGeneration] = None
-
- tts: Optional[TTS] = None
-
- unknown: Optional[Unknown] = None
-
- video_generation: Optional[VideoGeneration] = None
-
- @model_serializer(mode="wrap")
- def serialize_model(self, handler):
- optional_fields = set(
- [
- "decisions",
- "embeddings",
- "image_generation",
- "rerank",
- "stt",
- "text_generation",
- "tts",
- "unknown",
- "video_generation",
- ]
- )
- serialized = handler(self)
- m = {}
-
- for n, f in type(self).model_fields.items():
- k = f.alias or n
- val = serialized.get(k, serialized.get(n))
-
- if val != UNSET_SENTINEL:
- if val is not None or k not in optional_fields:
- m[k] = val
-
- return m
-
-
-class PricingTypedDict(TypedDict):
- completion: str
- r"""Price in USD per token for completion (output) generation"""
- prompt: str
- r"""Price in USD per token for prompt (input) processing"""
- audio: NotRequired[str]
- r"""Price in USD per audio input token"""
- audio_output: NotRequired[str]
- r"""Price in USD per audio output token"""
- discount: NotRequired[float]
- r"""Fractional discount applied to this endpoint's pricing; the price is multiplied by (1 - discount) (0 = no discount, 1 = free)"""
- image: NotRequired[str]
- r"""Price in USD per input image"""
- image_output: NotRequired[str]
- r"""Price in USD per output image"""
- image_token: NotRequired[str]
- r"""Price in USD per image token"""
- input_audio_cache: NotRequired[str]
- r"""Price in USD per cached audio input token"""
- input_cache_read: NotRequired[str]
- r"""Price in USD per cached input token (read)"""
- input_cache_write: NotRequired[str]
- r"""Price per cache-write token, in USD per token. For providers with multiple cache TTLs (e.g. Anthropic), this is the default (5-minute) cache-write rate."""
- input_cache_write_1h: NotRequired[str]
- r"""Price per 1-hour cache-write token, in USD per token. Only present for providers that price an extended (1-hour) cache TTL separately, such as Anthropic."""
- internal_reasoning: NotRequired[str]
- r"""Price in USD per internal reasoning token"""
- overrides: NotRequired[List[PricingOverrideTypedDict]]
- r"""Conditional overrides of the base pricing (e.g. long-context or time-based pricing). An entry applies when all of its condition fields (e.g. min_prompt_tokens, or the utc_start/utc_end time window) match the request; among applicable entries, later entries win per key; price keys absent from an entry inherit the base price. The top-level pricing keys always reflect the price that applies under default conditions."""
- request: NotRequired[str]
- r"""Price in USD per request"""
- web_search: NotRequired[str]
- r"""Price in USD per web search"""
-
-
-class Pricing(BaseModel):
- completion: str
- r"""Price in USD per token for completion (output) generation"""
-
- prompt: str
- r"""Price in USD per token for prompt (input) processing"""
-
- audio: Optional[str] = None
- r"""Price in USD per audio input token"""
-
- audio_output: Optional[str] = None
- r"""Price in USD per audio output token"""
-
- discount: Optional[float] = None
- r"""Fractional discount applied to this endpoint's pricing; the price is multiplied by (1 - discount) (0 = no discount, 1 = free)"""
-
- image: Optional[str] = None
- r"""Price in USD per input image"""
-
- image_output: Optional[str] = None
- r"""Price in USD per output image"""
-
- image_token: Optional[str] = None
- r"""Price in USD per image token"""
-
- input_audio_cache: Optional[str] = None
- r"""Price in USD per cached audio input token"""
-
- input_cache_read: Optional[str] = None
- r"""Price in USD per cached input token (read)"""
-
- input_cache_write: Optional[str] = None
- r"""Price per cache-write token, in USD per token. For providers with multiple cache TTLs (e.g. Anthropic), this is the default (5-minute) cache-write rate."""
-
- input_cache_write_1h: Optional[str] = None
- r"""Price per 1-hour cache-write token, in USD per token. Only present for providers that price an extended (1-hour) cache TTL separately, such as Anthropic."""
-
- internal_reasoning: Optional[str] = None
- r"""Price in USD per internal reasoning token"""
-
- overrides: Optional[List[PricingOverride]] = None
- r"""Conditional overrides of the base pricing (e.g. long-context or time-based pricing). An entry applies when all of its condition fields (e.g. min_prompt_tokens, or the utc_start/utc_end time window) match the request; among applicable entries, later entries win per key; price keys absent from an entry inherit the base price. The top-level pricing keys always reflect the price that applies under default conditions."""
-
- request: Optional[str] = None
- r"""Price in USD per request"""
-
- web_search: Optional[str] = None
- r"""Price in USD per web search"""
-
- @model_serializer(mode="wrap")
- def serialize_model(self, handler):
- optional_fields = set(
- [
- "audio",
- "audio_output",
- "discount",
- "image",
- "image_output",
- "image_token",
- "input_audio_cache",
- "input_cache_read",
- "input_cache_write",
- "input_cache_write_1h",
- "internal_reasoning",
- "overrides",
- "request",
- "web_search",
- ]
- )
- serialized = handler(self)
- m = {}
-
- for n, f in type(self).model_fields.items():
- k = f.alias or n
- val = serialized.get(k, serialized.get(n))
-
- if val != UNSET_SENTINEL:
- if val is not None or k not in optional_fields:
- m[k] = val
-
- return m
-
-
class PublicEndpointTypedDict(TypedDict):
r"""Information about a specific model endpoint"""
diff --git a/src/openrouter/components/publiczdrendpoint.py b/src/openrouter/components/publiczdrendpoint.py
new file mode 100644
index 00000000..ab5747e0
--- /dev/null
+++ b/src/openrouter/components/publiczdrendpoint.py
@@ -0,0 +1,180 @@
+"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT."""
+
+from __future__ import annotations
+from .endpointstatus import EndpointStatus
+from .nativetools import NativeTools, NativeToolsTypedDict
+from .parameter import Parameter
+from .percentilestats import PercentileStats, PercentileStatsTypedDict
+from .perflast30mbyworkload import PerfLast30mByWorkload, PerfLast30mByWorkloadTypedDict
+from .pricing import Pricing, PricingTypedDict
+from .providername import ProviderName
+from .publicservicetier import PublicServiceTier
+from .quantization import Quantization
+from .toolchoicesupport import ToolChoiceSupport, ToolChoiceSupportTypedDict
+from openrouter.types import BaseModel, Nullable, UNSET_SENTINEL
+from pydantic import model_serializer
+from typing import Dict, List, Optional
+from typing_extensions import NotRequired, TypedDict
+
+
+class PublicZdrEndpointTypedDict(TypedDict):
+ r"""An endpoint whose data policy does not retain prompts by default"""
+
+ context_length: int
+ latency_last_30m: Nullable[PercentileStatsTypedDict]
+ r"""Latency percentiles in milliseconds over the last 30 minutes. Latency measures time to first token. Only visible when authenticated with an API key or cookie; returns null for unauthenticated requests."""
+ max_completion_tokens: Nullable[int]
+ r"""Maximum completion tokens for this endpoint. Input and output tokens share the context window, so the effective maximum output for a request is further limited by the context remaining after input tokens."""
+ max_prompt_tokens: Nullable[int]
+ model_id: str
+ r"""The unique identifier for the model (permaslug)"""
+ model_name: str
+ name: str
+ native_tools: Dict[str, NativeToolsTypedDict]
+ r"""The server tools this endpoint accepts as the provider's own built-in tool (`engine: \"native\"`) instead of an OpenRouter engine, keyed by canonical `openrouter:*` name. Each value names the provider tool type the request is translated to. Where that tool runs (provider-side, or returned to the client as with Anthropic bash) is documented per tool. Empty when the provider has none."""
+ pricing: PricingTypedDict
+ provider_name: ProviderName
+ quantization: Nullable[Quantization]
+ service_tier: Nullable[PublicServiceTier]
+ r"""The service tier this endpoint sells, or null for a standard endpoint. The same value whether the provider selects the tier with a request parameter or with a dedicated model id. Always the canonical tier: priority covers the fast request alias and the turbo, highspeed, and prime provider model-id spellings, none of which this field reports."""
+ supported_parameters: List[Parameter]
+ supports_diarization: bool
+ r"""Whether this STT endpoint can label each transcript segment with a speaker (speaker diarization). False when the endpoint has not declared support."""
+ supports_implicit_caching: bool
+ supports_tool_choice: ToolChoiceSupportTypedDict
+ r"""Per-variant `tool_choice` support. `tool_choice` in `supported_parameters` only says the parameter is accepted; these flags say which of its values passed testing."""
+ tag: str
+ throughput_last_30m: Nullable[PercentileStatsTypedDict]
+ uptime_last_1d: Nullable[float]
+ r"""Uptime percentage over the last day: the share of minutes in which at least 80% of provider attempts succeeded, counting only minutes with 10 or more attempts. Rate-limited and caller-caused failures are excluded. Null when no minute had enough traffic."""
+ uptime_last_30m: Nullable[float]
+ uptime_last_5m: Nullable[float]
+ r"""Uptime percentage over the last 5 minutes: the share of minutes in which at least 80% of provider attempts succeeded, counting only minutes with 10 or more attempts. Rate-limited and caller-caused failures are excluded. Null when no minute had enough traffic."""
+ safety_retention: bool
+ r"""Whether the endpoint uses Safety Retention: prompts are not retained by default, but the provider may retain prompts its safety classifiers flag. A ZDR-enforced request reaches these endpoints only when the account allows Safety Retention and no applied guardrail disallows it."""
+ perf_last_30m_by_workload: NotRequired[PerfLast30mByWorkloadTypedDict]
+ r"""Endpoint performance over the last 30 minutes, keyed by the kind of request served (e.g. `text_generation`, `image_generation`). Additive to the legacy singular latency and throughput fields; image and video generation report end-to-end latency. Only visible when authenticated with an API key or cookie."""
+ status: NotRequired[EndpointStatus]
+ supports_image_reference: NotRequired[bool]
+ r"""Whether this TTS endpoint accepts an `image_url` reference describing the desired voice. Requests carrying an image reference are only routed to endpoints where this is true."""
+ supports_multiple_audio_references: NotRequired[bool]
+ r"""Whether this TTS endpoint accepts more than one `input_audio` reference clip per request. Requests carrying several clips are only routed to endpoints where this is true."""
+ supports_voice_cloning: NotRequired[bool]
+ r"""Whether this TTS endpoint accepts inline reference audio (`input_references`) for stateless voice cloning. Requests carrying reference audio are only routed to endpoints where this is true."""
+
+
+class PublicZdrEndpoint(BaseModel):
+ r"""An endpoint whose data policy does not retain prompts by default"""
+
+ context_length: int
+
+ latency_last_30m: Nullable[PercentileStats]
+ r"""Latency percentiles in milliseconds over the last 30 minutes. Latency measures time to first token. Only visible when authenticated with an API key or cookie; returns null for unauthenticated requests."""
+
+ max_completion_tokens: Nullable[int]
+ r"""Maximum completion tokens for this endpoint. Input and output tokens share the context window, so the effective maximum output for a request is further limited by the context remaining after input tokens."""
+
+ max_prompt_tokens: Nullable[int]
+
+ model_id: str
+ r"""The unique identifier for the model (permaslug)"""
+
+ model_name: str
+
+ name: str
+
+ native_tools: Dict[str, NativeTools]
+ r"""The server tools this endpoint accepts as the provider's own built-in tool (`engine: \"native\"`) instead of an OpenRouter engine, keyed by canonical `openrouter:*` name. Each value names the provider tool type the request is translated to. Where that tool runs (provider-side, or returned to the client as with Anthropic bash) is documented per tool. Empty when the provider has none."""
+
+ pricing: Pricing
+
+ provider_name: ProviderName
+
+ quantization: Nullable[Quantization]
+
+ service_tier: Nullable[PublicServiceTier]
+ r"""The service tier this endpoint sells, or null for a standard endpoint. The same value whether the provider selects the tier with a request parameter or with a dedicated model id. Always the canonical tier: priority covers the fast request alias and the turbo, highspeed, and prime provider model-id spellings, none of which this field reports."""
+
+ supported_parameters: List[Parameter]
+
+ supports_diarization: bool
+ r"""Whether this STT endpoint can label each transcript segment with a speaker (speaker diarization). False when the endpoint has not declared support."""
+
+ supports_implicit_caching: bool
+
+ supports_tool_choice: ToolChoiceSupport
+ r"""Per-variant `tool_choice` support. `tool_choice` in `supported_parameters` only says the parameter is accepted; these flags say which of its values passed testing."""
+
+ tag: str
+
+ throughput_last_30m: Nullable[PercentileStats]
+
+ uptime_last_1d: Nullable[float]
+ r"""Uptime percentage over the last day: the share of minutes in which at least 80% of provider attempts succeeded, counting only minutes with 10 or more attempts. Rate-limited and caller-caused failures are excluded. Null when no minute had enough traffic."""
+
+ uptime_last_30m: Nullable[float]
+
+ uptime_last_5m: Nullable[float]
+ r"""Uptime percentage over the last 5 minutes: the share of minutes in which at least 80% of provider attempts succeeded, counting only minutes with 10 or more attempts. Rate-limited and caller-caused failures are excluded. Null when no minute had enough traffic."""
+
+ safety_retention: bool
+ r"""Whether the endpoint uses Safety Retention: prompts are not retained by default, but the provider may retain prompts its safety classifiers flag. A ZDR-enforced request reaches these endpoints only when the account allows Safety Retention and no applied guardrail disallows it."""
+
+ perf_last_30m_by_workload: Optional[PerfLast30mByWorkload] = None
+ r"""Endpoint performance over the last 30 minutes, keyed by the kind of request served (e.g. `text_generation`, `image_generation`). Additive to the legacy singular latency and throughput fields; image and video generation report end-to-end latency. Only visible when authenticated with an API key or cookie."""
+
+ status: Optional[EndpointStatus] = None
+
+ supports_image_reference: Optional[bool] = False
+ r"""Whether this TTS endpoint accepts an `image_url` reference describing the desired voice. Requests carrying an image reference are only routed to endpoints where this is true."""
+
+ supports_multiple_audio_references: Optional[bool] = False
+ r"""Whether this TTS endpoint accepts more than one `input_audio` reference clip per request. Requests carrying several clips are only routed to endpoints where this is true."""
+
+ supports_voice_cloning: Optional[bool] = False
+ r"""Whether this TTS endpoint accepts inline reference audio (`input_references`) for stateless voice cloning. Requests carrying reference audio are only routed to endpoints where this is true."""
+
+ @model_serializer(mode="wrap")
+ def serialize_model(self, handler):
+ optional_fields = set(
+ [
+ "perf_last_30m_by_workload",
+ "status",
+ "supports_image_reference",
+ "supports_multiple_audio_references",
+ "supports_voice_cloning",
+ ]
+ )
+ nullable_fields = set(
+ [
+ "latency_last_30m",
+ "max_completion_tokens",
+ "max_prompt_tokens",
+ "quantization",
+ "service_tier",
+ "throughput_last_30m",
+ "uptime_last_1d",
+ "uptime_last_30m",
+ "uptime_last_5m",
+ ]
+ )
+ serialized = handler(self)
+ m = {}
+
+ for n, f in type(self).model_fields.items():
+ k = f.alias or n
+ val = serialized.get(k, serialized.get(n))
+ is_nullable_and_explicitly_set = (
+ k in nullable_fields
+ and (self.__pydantic_fields_set__.intersection({n})) # pylint: disable=no-member
+ )
+
+ if val != UNSET_SENTINEL:
+ if (
+ val is not None
+ or k not in optional_fields
+ or is_nullable_and_explicitly_set
+ ):
+ m[k] = val
+
+ return m
diff --git a/src/openrouter/components/rerank.py b/src/openrouter/components/rerank.py
new file mode 100644
index 00000000..e3740a8f
--- /dev/null
+++ b/src/openrouter/components/rerank.py
@@ -0,0 +1,37 @@
+"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT."""
+
+from __future__ import annotations
+from .percentilestats import PercentileStats, PercentileStatsTypedDict
+from openrouter.types import BaseModel, Nullable, UNSET_SENTINEL
+from pydantic import model_serializer
+from typing_extensions import TypedDict
+
+
+class RerankTypedDict(TypedDict):
+ latency: Nullable[PercentileStatsTypedDict]
+ request_count: Nullable[int]
+ r"""Total requests admitted for this workload in the window."""
+ throughput: Nullable[PercentileStatsTypedDict]
+
+
+class Rerank(BaseModel):
+ latency: Nullable[PercentileStats]
+
+ request_count: Nullable[int]
+ r"""Total requests admitted for this workload in the window."""
+
+ throughput: Nullable[PercentileStats]
+
+ @model_serializer(mode="wrap")
+ def serialize_model(self, handler):
+ serialized = handler(self)
+ m = {}
+
+ for n, f in type(self).model_fields.items():
+ k = f.alias or n
+ val = serialized.get(k, serialized.get(n))
+
+ if val != UNSET_SENTINEL:
+ m[k] = val
+
+ return m
diff --git a/src/openrouter/components/stt.py b/src/openrouter/components/stt.py
new file mode 100644
index 00000000..2b0b14c1
--- /dev/null
+++ b/src/openrouter/components/stt.py
@@ -0,0 +1,37 @@
+"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT."""
+
+from __future__ import annotations
+from .percentilestats import PercentileStats, PercentileStatsTypedDict
+from openrouter.types import BaseModel, Nullable, UNSET_SENTINEL
+from pydantic import model_serializer
+from typing_extensions import TypedDict
+
+
+class STTTypedDict(TypedDict):
+ latency: Nullable[PercentileStatsTypedDict]
+ request_count: Nullable[int]
+ r"""Total requests admitted for this workload in the window."""
+ throughput: Nullable[PercentileStatsTypedDict]
+
+
+class STT(BaseModel):
+ latency: Nullable[PercentileStats]
+
+ request_count: Nullable[int]
+ r"""Total requests admitted for this workload in the window."""
+
+ throughput: Nullable[PercentileStats]
+
+ @model_serializer(mode="wrap")
+ def serialize_model(self, handler):
+ serialized = handler(self)
+ m = {}
+
+ for n, f in type(self).model_fields.items():
+ k = f.alias or n
+ val = serialized.get(k, serialized.get(n))
+
+ if val != UNSET_SENTINEL:
+ m[k] = val
+
+ return m
diff --git a/src/openrouter/components/textgeneration.py b/src/openrouter/components/textgeneration.py
new file mode 100644
index 00000000..7b2f1c41
--- /dev/null
+++ b/src/openrouter/components/textgeneration.py
@@ -0,0 +1,37 @@
+"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT."""
+
+from __future__ import annotations
+from .percentilestats import PercentileStats, PercentileStatsTypedDict
+from openrouter.types import BaseModel, Nullable, UNSET_SENTINEL
+from pydantic import model_serializer
+from typing_extensions import TypedDict
+
+
+class TextGenerationTypedDict(TypedDict):
+ latency: Nullable[PercentileStatsTypedDict]
+ request_count: Nullable[int]
+ r"""Total requests admitted for this workload in the window."""
+ throughput: Nullable[PercentileStatsTypedDict]
+
+
+class TextGeneration(BaseModel):
+ latency: Nullable[PercentileStats]
+
+ request_count: Nullable[int]
+ r"""Total requests admitted for this workload in the window."""
+
+ throughput: Nullable[PercentileStats]
+
+ @model_serializer(mode="wrap")
+ def serialize_model(self, handler):
+ serialized = handler(self)
+ m = {}
+
+ for n, f in type(self).model_fields.items():
+ k = f.alias or n
+ val = serialized.get(k, serialized.get(n))
+
+ if val != UNSET_SENTINEL:
+ m[k] = val
+
+ return m
diff --git a/src/openrouter/components/tts.py b/src/openrouter/components/tts.py
new file mode 100644
index 00000000..6c89d6bf
--- /dev/null
+++ b/src/openrouter/components/tts.py
@@ -0,0 +1,37 @@
+"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT."""
+
+from __future__ import annotations
+from .percentilestats import PercentileStats, PercentileStatsTypedDict
+from openrouter.types import BaseModel, Nullable, UNSET_SENTINEL
+from pydantic import model_serializer
+from typing_extensions import TypedDict
+
+
+class TTSTypedDict(TypedDict):
+ latency: Nullable[PercentileStatsTypedDict]
+ request_count: Nullable[int]
+ r"""Total requests admitted for this workload in the window."""
+ throughput: Nullable[PercentileStatsTypedDict]
+
+
+class TTS(BaseModel):
+ latency: Nullable[PercentileStats]
+
+ request_count: Nullable[int]
+ r"""Total requests admitted for this workload in the window."""
+
+ throughput: Nullable[PercentileStats]
+
+ @model_serializer(mode="wrap")
+ def serialize_model(self, handler):
+ serialized = handler(self)
+ m = {}
+
+ for n, f in type(self).model_fields.items():
+ k = f.alias or n
+ val = serialized.get(k, serialized.get(n))
+
+ if val != UNSET_SENTINEL:
+ m[k] = val
+
+ return m
diff --git a/src/openrouter/components/unknown.py b/src/openrouter/components/unknown.py
new file mode 100644
index 00000000..b85755f1
--- /dev/null
+++ b/src/openrouter/components/unknown.py
@@ -0,0 +1,37 @@
+"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT."""
+
+from __future__ import annotations
+from .percentilestats import PercentileStats, PercentileStatsTypedDict
+from openrouter.types import BaseModel, Nullable, UNSET_SENTINEL
+from pydantic import model_serializer
+from typing_extensions import TypedDict
+
+
+class UnknownTypedDict(TypedDict):
+ latency: Nullable[PercentileStatsTypedDict]
+ request_count: Nullable[int]
+ r"""Total requests admitted for this workload in the window."""
+ throughput: Nullable[PercentileStatsTypedDict]
+
+
+class Unknown(BaseModel):
+ latency: Nullable[PercentileStats]
+
+ request_count: Nullable[int]
+ r"""Total requests admitted for this workload in the window."""
+
+ throughput: Nullable[PercentileStats]
+
+ @model_serializer(mode="wrap")
+ def serialize_model(self, handler):
+ serialized = handler(self)
+ m = {}
+
+ for n, f in type(self).model_fields.items():
+ k = f.alias or n
+ val = serialized.get(k, serialized.get(n))
+
+ if val != UNSET_SENTINEL:
+ m[k] = val
+
+ return m
diff --git a/src/openrouter/components/videogeneration.py b/src/openrouter/components/videogeneration.py
new file mode 100644
index 00000000..c2f15eb5
--- /dev/null
+++ b/src/openrouter/components/videogeneration.py
@@ -0,0 +1,37 @@
+"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT."""
+
+from __future__ import annotations
+from .percentilestats import PercentileStats, PercentileStatsTypedDict
+from openrouter.types import BaseModel, Nullable, UNSET_SENTINEL
+from pydantic import model_serializer
+from typing_extensions import TypedDict
+
+
+class VideoGenerationTypedDict(TypedDict):
+ latency: Nullable[PercentileStatsTypedDict]
+ request_count: Nullable[int]
+ r"""Total requests admitted for this workload in the window."""
+ throughput: Nullable[PercentileStatsTypedDict]
+
+
+class VideoGeneration(BaseModel):
+ latency: Nullable[PercentileStats]
+
+ request_count: Nullable[int]
+ r"""Total requests admitted for this workload in the window."""
+
+ throughput: Nullable[PercentileStats]
+
+ @model_serializer(mode="wrap")
+ def serialize_model(self, handler):
+ serialized = handler(self)
+ m = {}
+
+ for n, f in type(self).model_fields.items():
+ k = f.alias or n
+ val = serialized.get(k, serialized.get(n))
+
+ if val != UNSET_SENTINEL:
+ m[k] = val
+
+ return m
diff --git a/src/openrouter/operations/listendpointszdr.py b/src/openrouter/operations/listendpointszdr.py
index f5bd1f67..42e3e491 100644
--- a/src/openrouter/operations/listendpointszdr.py
+++ b/src/openrouter/operations/listendpointszdr.py
@@ -1,7 +1,7 @@
"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT."""
from __future__ import annotations
-from openrouter.components import publicendpoint as components_publicendpoint
+from openrouter.components import publiczdrendpoint as components_publiczdrendpoint
from openrouter.types import BaseModel, UNSET_SENTINEL
from openrouter.utils import FieldMetadata, HeaderMetadata
import pydantic
@@ -141,10 +141,10 @@ def serialize_model(self, handler):
class ListEndpointsZdrResponseTypedDict(TypedDict):
r"""Returns a list of endpoints"""
- data: List[components_publicendpoint.PublicEndpointTypedDict]
+ data: List[components_publiczdrendpoint.PublicZdrEndpointTypedDict]
class ListEndpointsZdrResponse(BaseModel):
r"""Returns a list of endpoints"""
- data: List[components_publicendpoint.PublicEndpoint]
+ data: List[components_publiczdrendpoint.PublicZdrEndpoint]
diff --git a/uv.lock b/uv.lock
index d64d302a..4d199f01 100644
--- a/uv.lock
+++ b/uv.lock
@@ -231,7 +231,7 @@ wheels = [
[[package]]
name = "openrouter"
-version = "1.3.103"
+version = "1.3.104"
source = { editable = "." }
dependencies = [
{ name = "httpcore" },