diff --git a/.speakeasy/gen.lock b/.speakeasy/gen.lock
index 8319c3bf..e6a97b36 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: 7dee79d06858c3877d9e3d05e5614cde
+ docChecksum: aaa7d4a75666f6d910431ccff64692b5
docVersion: 1.0.0
speakeasyVersion: 1.787.0
generationVersion: 2.914.0
- releaseVersion: 1.2.27
- configChecksum: 4a0681d5fa9d5dff4c80dfd7c16e3caf
+ releaseVersion: 1.2.28
+ configChecksum: 79af06c5b64804f84ca14bbeb1a2b789
repoURL: https://github.com/OpenRouterTeam/python-sdk.git
installationURL: https://github.com/OpenRouterTeam/python-sdk.git
published: true
persistentEdits:
- generation_id: 7787c28d-aa9e-440e-948a-98b6c018b499
- pristine_commit_hash: 0bcff2f200e5921ae70581dd4cbd597c609b8c97
- pristine_tree_hash: f255f10672de49b394769fcd4e0b3a01ba82c6d5
+ generation_id: c2e564a7-f9f9-4620-b18c-32f209645c9b
+ pristine_commit_hash: 4994453781c2d4211c9d4aa1c668ff05ae6fda99
+ pristine_tree_hash: ab24309cad6866631f246b0bd6ee01d6c62020e8
features:
python:
acceptHeaders: 3.0.0
@@ -4919,8 +4919,8 @@ trackedFiles:
pristine_git_object: be1e5af9301ba917704f25fdafed31c152485abf
docs/components/publicendpoint.mdx:
id: ec4843ef5d86
- last_write_checksum: sha1:23aab4f17e54311ce27a585548fef94c997def7c
- pristine_git_object: 78fc661608b214ddacd52d640660ea7e27cf3c73
+ last_write_checksum: sha1:54822f1b82fe3c0d91cf214773a1b52a6e7cf3a3
+ pristine_git_object: fc7a3507a210a8409cfe9d528972e8d4b68b67a1
docs/components/publicpricing.mdx:
id: 61fb18b7ff94
last_write_checksum: sha1:e241420249fcbd1bf515b0f5e84934de0b207948
@@ -5407,32 +5407,44 @@ trackedFiles:
pristine_git_object: 5d617cac37f7b364f4dd0640246e97c34351d824
docs/components/speechinputreference.mdx:
id: eb5af16936c7
- last_write_checksum: sha1:7c6f3859c9f24efd0787a34f951d85fbe71eac29
- pristine_git_object: 79204829325eb4f74a711c7edc1c782b8df12aaa
+ last_write_checksum: sha1:ab545b03da2161ae1ad449714b6861cd55ae66df
+ pristine_git_object: 7303b4f78166679c086effde5fd5b6ab875d580d
docs/components/speechinputreferenceaudio.mdx:
id: be120390be39
- last_write_checksum: sha1:2bade388b0b8cb5458c4f1bf0f790fdca724c0ec
- pristine_git_object: c69013daa1490e363dbbd66ee5a849eb946e7325
+ last_write_checksum: sha1:4abc3f8a18880605e3802670e48d114cde250070
+ pristine_git_object: f00281d13b6d61ad5496ebdcb3ec34dcc834a9d0
docs/components/speechinputreferenceaudioinput.mdx:
id: 5fc8d05d280c
- last_write_checksum: sha1:c28160bb5c9a47d9b95fccf3e834e5705b863a14
- pristine_git_object: fa10a1fbb2b79c1f46da48595119d9a5ed8f9e1e
+ last_write_checksum: sha1:046a2f438968786be605f7b37dd85d3e6d069a6f
+ pristine_git_object: c16ea82c8c24655bba86bd9c8de13f91e79a9c3e
docs/components/speechinputreferenceaudiotype.mdx:
id: 058d6a67e101
last_write_checksum: sha1:4af157ebbeebbfa18cc110c3ac32f8ff78a69ce2
pristine_git_object: 99478c90d4d43c6e23cbe275f97998502c2378ae
+ docs/components/speechinputreferenceimage.mdx:
+ id: 8e77f64c57a8
+ last_write_checksum: sha1:586ef478d847509339873a7e5bbc7134d38f1b36
+ pristine_git_object: 068290f70f3496c0a6a3b030ce6f5cb384550fb9
+ docs/components/speechinputreferenceimageinput.mdx:
+ id: 04884f13e007
+ last_write_checksum: sha1:fb6443433e5735e00e7264c3dfee8389af295339
+ pristine_git_object: 127f005a602cda6872f4ce9aed15e1d032024e6b
+ docs/components/speechinputreferenceimagetype.mdx:
+ id: b9da823bf7a8
+ last_write_checksum: sha1:500c0d9827d91ed7591910328db819e3549ee970
+ pristine_git_object: b40df3d3d04538e5328895c3d02481db6b273261
docs/components/speechinputreferencetext.mdx:
id: c16449cda36e
- last_write_checksum: sha1:b5099e4b7f20460e2dd9609e998491841305a9fb
- pristine_git_object: ff25c4928b7e6ecaeaee0a23255f3b001219de85
+ last_write_checksum: sha1:ed437a992026eb4169008b59ade634dcc41e765d
+ pristine_git_object: af437e9f376058bc571531b1d3019d06d2d62863
docs/components/speechinputreferencetexttype.mdx:
id: 469b6fa8fe52
last_write_checksum: sha1:47783070359618513e2d6c3b963e507cf1320b70
pristine_git_object: 34f4f07fb3008df83646fa3d88ce04009274246a
docs/components/speechrequest.mdx:
id: 06e81b0433f6
- last_write_checksum: sha1:5076534e37775a644db8326988169e8315cd4298
- pristine_git_object: a9c5cb0175063b4abd1ca036420a20c527f7ae22
+ last_write_checksum: sha1:9750d04360830c6aa909c67c8278a2d76e5c78cc
+ pristine_git_object: 2c86114409b77d9cd1f7d32ca8bfe505da0a0226
docs/components/speechrequestprovider.mdx:
id: 4f78ed0394c4
last_write_checksum: sha1:99d94c6b01dbd3e875c213584f97c7dca545a6a9
@@ -8235,8 +8247,8 @@ trackedFiles:
pristine_git_object: fc7688ebea8e973bebc0525a820ba246b6491f81
docs/sdks/tts/README.mdx:
id: cd1132543884
- last_write_checksum: sha1:37918eb124f9ae0234e8047be7ec07a955458cbc
- pristine_git_object: bc53071afea2d5c822b7d8bea60e486d72447e1c
+ last_write_checksum: sha1:5a8e24e62e0b41a781f38f22eed4369e4feaa960
+ pristine_git_object: 2d7b6d76d80b07c4720ff5984742b9ca5b097f1c
docs/sdks/vault/README.mdx:
id: 3738c6722acd
last_write_checksum: sha1:2b26b8c7e7c88dc4aee023f518b7d8e94f1649f9
@@ -8255,8 +8267,8 @@ trackedFiles:
pristine_git_object: 3e38f1a929f7d6b1d6de74604aa87e3d8f010544
pyproject.toml:
id: 5d07e7d72637
- last_write_checksum: sha1:2182755c8b37ffe89d33640d78d15eded50c963f
- pristine_git_object: 3cfb53504b33635caaaa5e59ba31aced74918a2b
+ last_write_checksum: sha1:a1f5febefe9ab41f16f33ee654083f9643575ebf
+ pristine_git_object: 08d4dd47159e38b401c96d12fcbb9ab119899f26
scripts/prepare_readme.py:
id: e0c5957a6035
last_write_checksum: sha1:77f44b60b98bc126557ec27391f91dfba764bb54
@@ -8283,8 +8295,8 @@ trackedFiles:
pristine_git_object: 86713cfea633e09d33b3d4e65281071fe20e6137
src/openrouter/_version.py:
id: d8d15ad6c586
- last_write_checksum: sha1:a5e896d58791d6d48c64dfaf9fc3d68c9b887ae4
- pristine_git_object: e3bd110d9f3eebe44728fd0f917865ae6bc7c26b
+ last_write_checksum: sha1:a6f6ff6b2bae032b308a2440d0e07aa418db58f4
+ pristine_git_object: 39525f896b5f75a8287a9069e88b5d3a5712b81d
src/openrouter/alpha.py:
id: 306c4d93308d
last_write_checksum: sha1:30f55a360f41376ab194b9ea725fe4e001a5ae1a
@@ -8327,8 +8339,8 @@ trackedFiles:
pristine_git_object: ad3d247954547814054c01989a2dff3d12b3e4e1
src/openrouter/components/__init__.py:
id: 81754e97b3f4
- last_write_checksum: sha1:286c1a4c6b8272e410a0da94c48d29719f989186
- pristine_git_object: 7300d1852826e3c47d7a155151cc5a473e14f56e
+ last_write_checksum: sha1:0fe14e50afa7072a2c6c47dbfdbfad4967d06f62
+ pristine_git_object: 471fad91d8163a89e5a53d074eff798df191ef83
src/openrouter/components/aabenchmarkentry.py:
id: e2e0f0b48c82
last_write_checksum: sha1:fab4d9a24d2cea937bb749d46c5f83941e99d65c
@@ -10419,8 +10431,8 @@ trackedFiles:
pristine_git_object: 5f4a4186a9c98767217546b6b87d238fbc0155f3
src/openrouter/components/publicendpoint.py:
id: 848aa2ef9129
- last_write_checksum: sha1:42707d2210be0e29267c85b4454676dfd56164b9
- pristine_git_object: 7830ec36d3bd2bcd575007c61910165ebe0f2952
+ last_write_checksum: sha1:9df37e60706796b35acd7fd36a2ac1aa082c2904
+ pristine_git_object: cfa5b51c2a31c34b96413bc44e70f629796f3ad2
src/openrouter/components/publicpricing.py:
id: 96d115d83cc5
last_write_checksum: sha1:fd8c320ac83b282eaf2405045329b55076d4311a
@@ -10659,24 +10671,32 @@ trackedFiles:
pristine_git_object: 418953ba7366a6015934bf8795178d79adb03b89
src/openrouter/components/speechinputreference.py:
id: 8e2b63f83354
- last_write_checksum: sha1:9692e7a4c71a1afec612ee7303b4b8202e313b39
- pristine_git_object: 9f490fecdd4b480cbe4b7f2ab6c5fe15aa207f12
+ last_write_checksum: sha1:b2ebc68fae64644f8bfca9b555ca7d2a7b46c9e1
+ pristine_git_object: 0881593ad73af3e97f5d3a6a2aeb6cfe5ffe687e
src/openrouter/components/speechinputreferenceaudio.py:
id: 72d940d3f6a2
- last_write_checksum: sha1:f5c3ecd689121fb02903cd869323fbebee033ad3
- pristine_git_object: 7341493f9a8745299e004ccf4e2b672f624fad4f
+ last_write_checksum: sha1:efd262edae0cb4b4b5052680ffc798f6fd5833d8
+ pristine_git_object: 3f346893a5b7da55fa1d1eb437d989d0ec74545f
src/openrouter/components/speechinputreferenceaudioinput.py:
id: 2e2aeb5ee50f
- last_write_checksum: sha1:9712952578b85c2049549cb3c36fd11630405ef3
- pristine_git_object: c6e21210786537b19ca5ba99b48d7a8b61dfcdb1
+ last_write_checksum: sha1:7b390e8f08f740cfad113a2f64b0a0b24b940944
+ pristine_git_object: 33d35ab0c8d110d9253331c790c4b78b920660f3
+ src/openrouter/components/speechinputreferenceimage.py:
+ id: 644d542991a7
+ last_write_checksum: sha1:1e9923984145ab1fa0ced2ccccdba8997e2bba11
+ pristine_git_object: 6129f2f1ecb2c8883a1d998e2ac976d54c90ee94
+ src/openrouter/components/speechinputreferenceimageinput.py:
+ id: 91a49498faa8
+ last_write_checksum: sha1:b8f5ae40360a7d96de4128d730b042bcd0d2d8e8
+ pristine_git_object: f962606705fc3ba8799a2f39b97c1ea5916d8196
src/openrouter/components/speechinputreferencetext.py:
id: d9cd9e42ac40
- last_write_checksum: sha1:1bad63b5cff8b3b522dbebdaafb9495d3ddfab61
- pristine_git_object: e1703efe8ac18c7aea925375ddfa6ef74c31193b
+ last_write_checksum: sha1:3acdadbccb53ffe81cf7221c5f13ef031436adb7
+ pristine_git_object: 4633e5d7658c500aa903ce8caa8ef86cc97b78eb
src/openrouter/components/speechrequest.py:
id: 2a9400167112
- last_write_checksum: sha1:3dbce6755f21e37ab2949daef2c02c530396ddb1
- pristine_git_object: e38473a545f990c87e71007577cf9b6a691fd99a
+ last_write_checksum: sha1:ac6c30caa9222c55133d8fe5a206c6429010e1af
+ pristine_git_object: 877daa6a52ae8c1ae4105d860b03fce8e5474c06
src/openrouter/components/stopservertoolswhencondition.py:
id: 2deeda4209ac
last_write_checksum: sha1:581e0ee62776d42bf598b9f68b998faabfecd3ce
@@ -11823,8 +11843,8 @@ trackedFiles:
pristine_git_object: aac5cbef3468a6b9c9fe04c3bd6c86e23de4b4e9
src/openrouter/tts.py:
id: 5055d4b95f1d
- last_write_checksum: sha1:cdeb84948a22d150b582c65b63a53bfab5c13109
- pristine_git_object: 7903797cbdcfced8f4a868feaa0b15b9b44512bb
+ last_write_checksum: sha1:505003b62781347ac707761c8d082f3b2738025d
+ pristine_git_object: 7fd842bd10805bae6281913c77e4826a188cd01e
src/openrouter/types/__init__.py:
id: 5eab536205b7
last_write_checksum: sha1:f9ad14217f832e74f594285960125add50324be9
@@ -12173,7 +12193,7 @@ examples:
slug: "gpt-4"
responses:
"200":
- application/json: {"data": {"architecture": {"input_modalities": ["text"], "instruct_type": "chatml", "modality": "text->text", "output_modalities": ["text"], "tokenizer": "GPT"}, "created": 1692901234, "description": "GPT-4 is a large multimodal model that can solve difficult problems with greater accuracy.", "endpoints": [{"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", "pricing": {"completion": "0.00006", "prompt": "0.00003"}, "provider_name": "OpenAI", "quantization": "fp16", "supported_parameters": ["temperature", "top_p", "max_tokens"], "supports_implicit_caching": true, "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}], "id": "openai/gpt-4", "name": "GPT-4"}}
+ application/json: {"data": {"architecture": {"input_modalities": ["text"], "instruct_type": "chatml", "modality": "text->text", "output_modalities": ["text"], "tokenizer": "GPT"}, "created": 1692901234, "description": "GPT-4 is a large multimodal model that can solve difficult problems with greater accuracy.", "endpoints": [{"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", "pricing": {"completion": "0.00006", "prompt": "0.00003"}, "provider_name": "OpenAI", "quantization": "fp16", "supported_parameters": ["temperature", "top_p", "max_tokens"], "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}], "id": "openai/gpt-4", "name": "GPT-4"}}
"404":
application/json: {"error": {"code": 404, "message": "Resource not found"}}
"500":
@@ -12184,7 +12204,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", "pricing": {"completion": "0.00006", "prompt": "0.00003"}, "provider_name": "OpenAI", "quantization": "fp16", "supported_parameters": ["temperature", "top_p", "max_tokens"], "supports_implicit_caching": true, "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", "pricing": {"completion": "0.00006", "prompt": "0.00003"}, "provider_name": "OpenAI", "quantization": "fp16", "supported_parameters": ["temperature", "top_p", "max_tokens"], "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}]}
"500":
application/json: {"error": {"code": 500, "message": "Internal Server Error"}}
"403":
@@ -15162,6 +15182,4 @@ examples:
"500":
application/json: {"error": {"code": 404, "message": "Intern not found"}}
examplesVersion: 1.0.2
-releaseNotes: |
- ## Python SDK Changes:
- * `open_router.interns.get_intern_daemon_access()`: `error.status[429]` **Removed** (Breaking ⚠️)
+releaseNotes: "## Python SDK Changes:\n* `open_router.tts.create_speech()`: \n * `request.input_references[]` **Changed**\n* `open_router.endpoints.list_zdr_endpoints()`: `response.data[]` **Changed**\n* `open_router.endpoints.list()`: `response.data.endpoints[]` **Changed**\n"
diff --git a/.speakeasy/gen.yaml b/.speakeasy/gen.yaml
index 24840779..57690f43 100644
--- a/.speakeasy/gen.yaml
+++ b/.speakeasy/gen.yaml
@@ -36,7 +36,7 @@ generation:
documentation: mintlify
preApplyUnionDiscriminators: true
python:
- version: 1.2.27
+ version: 1.2.28
additionalDependencies:
dev: {}
main: {}
diff --git a/.speakeasy/out.openapi.yaml b/.speakeasy/out.openapi.yaml
index 3381824e..f66acf24 100644
--- a/.speakeasy/out.openapi.yaml
+++ b/.speakeasy/out.openapi.yaml
@@ -23967,7 +23967,9 @@ components:
- 'temperature'
- 'top_p'
- 'max_tokens'
+ supports_image_reference: false
supports_implicit_caching: true
+ supports_multiple_audio_references: false
supports_tool_choice:
auto: true
function: true
@@ -24259,8 +24261,16 @@ components:
items:
$ref: '#/components/schemas/Parameter'
type: 'array'
+ supports_image_reference:
+ default: false
+ description: '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.'
+ type: 'boolean'
supports_implicit_caching:
type: 'boolean'
+ supports_multiple_audio_references:
+ default: false
+ description: '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.'
+ type: 'boolean'
supports_tool_choice:
$ref: '#/components/schemas/ToolChoiceSupport'
supports_voice_cloning:
@@ -25925,17 +25935,19 @@ components:
- $ref: '#/components/schemas/ContainerAutoEnvironment'
- $ref: '#/components/schemas/ContainerReferenceEnvironment'
SpeechInputReference:
- description: 'Reference content part for stateless voice cloning'
+ description: 'Reference content part for stateless voice cloning or voice design'
discriminator:
mapping:
+ image_url: '#/components/schemas/SpeechInputReferenceImage'
input_audio: '#/components/schemas/SpeechInputReferenceAudio'
text: '#/components/schemas/SpeechInputReferenceText'
propertyName: 'type'
oneOf:
- $ref: '#/components/schemas/SpeechInputReferenceAudio'
- $ref: '#/components/schemas/SpeechInputReferenceText'
+ - $ref: '#/components/schemas/SpeechInputReferenceImage'
SpeechInputReferenceAudio:
- description: 'Reference audio input for stateless voice cloning'
+ description: 'Reference audio input for stateless voice cloning. Up to three parts per request; the Nth audio part is addressable from `input` as `@AudioN` on providers that support multiple references.'
example:
input_audio:
data: 'data:audio/wav;base64,UklGRuQXDABXQVZF...'
@@ -25955,7 +25967,7 @@ components:
description: 'Reference audio input object'
properties:
data:
- description: 'Base64-encoded reference audio (optionally a data URI). Supported audio formats are provider-specific. Limited to 20 MiB of base64 (15 MiB of decoded audio).'
+ description: 'Base64-encoded reference audio (optionally a data URI). Supported audio formats are provider-specific. Limited to 20 MiB of base64 (15 MiB of decoded audio). Exactly one of `data` or `url` is required.'
example: 'data:audio/wav;base64,UklGRuQXDABXQVZF...'
maxLength: 20971520
minLength: 1
@@ -25964,17 +25976,50 @@ components:
description: 'Audio format of the reference audio (e.g., wav, mp3). Optional; most providers detect the format from the audio bytes.'
example: 'wav'
type: 'string'
+ url:
+ description: 'Public http(s) URL of the reference audio. OpenRouter downloads it (15 MiB max) and forwards the bytes, never the URL. Exactly one of `data` or `url` is required.'
+ example: 'https://example.com/reference.wav'
+ format: 'uri'
+ maxLength: 2048
+ type: 'string'
+ type: 'object'
+ SpeechInputReferenceImage:
+ description: 'Reference image describing the desired voice. Cannot be combined with `input_audio` parts. Only routed to endpoints that support image references.'
+ example:
+ image_url:
+ url: 'data:image/png;base64,iVBORw0KGgo...'
+ type: 'image_url'
+ properties:
+ image_url:
+ $ref: '#/components/schemas/SpeechInputReferenceImageInput'
+ type:
+ enum:
+ - 'image_url'
+ type: 'string'
required:
- - 'data'
+ - 'type'
+ - 'image_url'
+ type: 'object'
+ SpeechInputReferenceImageInput:
+ description: 'Reference image input object'
+ properties:
+ url:
+ description: 'JPEG, PNG, or WebP reference image as a base64 data URI or a public http(s) URL. Remote images are downloaded (15 MiB max) and forwarded as bytes, never as the URL.'
+ example: 'data:image/png;base64,iVBORw0KGgo...'
+ maxLength: 20971520
+ minLength: 1
+ type: 'string'
+ required:
+ - 'url'
type: 'object'
SpeechInputReferenceText:
- description: 'Transcript of the accompanying reference audio'
+ description: 'Transcript of an `input_audio` part'
example:
text: 'I used to rule the world.'
type: 'text'
properties:
text:
- description: 'Transcript of the accompanying reference audio.'
+ description: 'Transcript of an `input_audio` part. With a single clip it may appear before or after the clip; with multiple clips it must immediately follow the clip it transcribes.'
example: 'I used to rule the world.'
maxLength: 10000
type: 'string'
@@ -26000,7 +26045,7 @@ components:
example: 'Hello world'
type: 'string'
input_references:
- description: 'Reference content for stateless voice cloning: one `input_audio` part carrying the voice sample, optionally accompanied by one `text` part with its transcript. Only routed to endpoints that support voice cloning.'
+ description: 'Reference content for stateless voice cloning or voice design. Audio mode: one to three `input_audio` parts, each optionally paired with a `text` part carrying its transcript (a single clip accepts its transcript before or after it; with multiple clips each transcript immediately follows its clip); only routed to endpoints that support voice cloning (and multiple references when more than one part is sent). Image mode: exactly one `image_url` part; only routed to endpoints that support image references. The two modes cannot be mixed. An empty array is treated as no reference.'
example:
- input_audio:
data: 'data:audio/wav;base64,UklGRuQXDABXQVZF...'
@@ -34214,7 +34259,9 @@ paths:
- 'temperature'
- 'top_p'
- 'max_tokens'
+ supports_image_reference: false
supports_implicit_caching: true
+ supports_multiple_audio_references: false
supports_voice_cloning: false
tag: 'openai'
throughput_last_30m:
@@ -34251,7 +34298,9 @@ paths:
- 'temperature'
- 'top_p'
- 'max_tokens'
+ supports_image_reference: false
supports_implicit_caching: true
+ supports_multiple_audio_references: false
supports_voice_cloning: false
tag: 'openai'
throughput_last_30m:
diff --git a/.speakeasy/workflow.lock b/.speakeasy/workflow.lock
index 19e5c899..16752744 100644
--- a/.speakeasy/workflow.lock
+++ b/.speakeasy/workflow.lock
@@ -2,8 +2,8 @@ speakeasyVersion: 1.787.0
sources:
OpenRouter API:
sourceNamespace: open-router-chat-completions-api
- sourceRevisionDigest: sha256:ebf6e311e185cd80a5e5643606d4def285c2e8f30aa4cbd1f3622e7a9366036b
- sourceBlobDigest: sha256:aa51ea5e2f170565c5063fbc4d3b316de3928f9953bbb2683fe6275df1ef56e2
+ sourceRevisionDigest: sha256:3300acddd2fd2bf4dd86533707050dd422c7297bccfa3b38546c88df69667864
+ sourceBlobDigest: sha256:3a6c855be1c0b1e5ed3c4d831d2b5da76fe0d92432a3fbf6d2edfec6aab84c40
tags:
- latest
- 1.0.0
@@ -11,10 +11,10 @@ targets:
open-router:
source: OpenRouter API
sourceNamespace: open-router-chat-completions-api
- sourceRevisionDigest: sha256:ebf6e311e185cd80a5e5643606d4def285c2e8f30aa4cbd1f3622e7a9366036b
- sourceBlobDigest: sha256:aa51ea5e2f170565c5063fbc4d3b316de3928f9953bbb2683fe6275df1ef56e2
+ sourceRevisionDigest: sha256:3300acddd2fd2bf4dd86533707050dd422c7297bccfa3b38546c88df69667864
+ sourceBlobDigest: sha256:3a6c855be1c0b1e5ed3c4d831d2b5da76fe0d92432a3fbf6d2edfec6aab84c40
codeSamplesNamespace: open-router-python-code-samples
- codeSamplesRevisionDigest: sha256:f88e970e6e4f54ca7fe848f85ee986e35301d2119907e87407aafe55a531f301
+ codeSamplesRevisionDigest: sha256:d618ed63247c77943456f9506235eca0ac64da62ade8439196342cfac374e221
workflow:
workflowVersion: 1.0.0
speakeasyVersion: 1.787.0
diff --git a/RELEASES.md b/RELEASES.md
index da874028..df50d511 100644
--- a/RELEASES.md
+++ b/RELEASES.md
@@ -2679,4 +2679,14 @@ Based on:
### Generated
- [python v1.2.27] .
### Releases
-- [PyPI v1.2.27] https://pypi.org/project/openrouter/1.2.27 - .
\ No newline at end of file
+- [PyPI v1.2.27] https://pypi.org/project/openrouter/1.2.27 - .
+
+## 2026-09-25 19:39:53
+### Changes
+Based on:
+- OpenAPI Doc
+- Speakeasy CLI 1.787.0 (2.914.0) https://github.com/speakeasy-api/speakeasy
+### Generated
+- [python v1.2.28] .
+### Releases
+- [PyPI v1.2.28] https://pypi.org/project/openrouter/1.2.28 - .
\ No newline at end of file
diff --git a/docs/components/publicendpoint.mdx b/docs/components/publicendpoint.mdx
index 78fc6616..fc7a3507 100644
--- a/docs/components/publicendpoint.mdx
+++ b/docs/components/publicendpoint.mdx
@@ -22,7 +22,9 @@ Information about a specific model endpoint
| `quantization` | [Nullable[components.Quantization]](../components/quantization.mdx) | :heavy_check_mark: | N/A | fp16 |
| `status` | [Optional[components.EndpointStatus]](../components/endpointstatus.mdx) | :heavy_minus_sign: | N/A | 0 |
| `supported_parameters` | List[[components.Parameter](../components/parameter.mdx)] | :heavy_check_mark: | N/A | |
+| `supports_image_reference` | *Optional[bool]* | :heavy_minus_sign: | 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* | :heavy_check_mark: | N/A | |
+| `supports_multiple_audio_references` | *Optional[bool]* | :heavy_minus_sign: | 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) | :heavy_check_mark: | 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]* | :heavy_minus_sign: | 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* | :heavy_check_mark: | N/A | |
diff --git a/docs/components/speechinputreference.mdx b/docs/components/speechinputreference.mdx
index 79204829..7303b4f7 100644
--- a/docs/components/speechinputreference.mdx
+++ b/docs/components/speechinputreference.mdx
@@ -2,11 +2,17 @@
title: "SpeechInputReference"
---
-Reference content part for stateless voice cloning
+Reference content part for stateless voice cloning or voice design
## Supported Types
+### `components.SpeechInputReferenceImage`
+
+```python
+value: components.SpeechInputReferenceImage = /* values here */
+```
+
### `components.SpeechInputReferenceAudio`
```python
diff --git a/docs/components/speechinputreferenceaudio.mdx b/docs/components/speechinputreferenceaudio.mdx
index c69013da..f00281d1 100644
--- a/docs/components/speechinputreferenceaudio.mdx
+++ b/docs/components/speechinputreferenceaudio.mdx
@@ -2,7 +2,7 @@
title: "SpeechInputReferenceAudio"
---
-Reference audio input for stateless voice cloning
+Reference audio input for stateless voice cloning. Up to three parts per request; the Nth audio part is addressable from `input` as `@AudioN` on providers that support multiple references.
## Fields
diff --git a/docs/components/speechinputreferenceaudioinput.mdx b/docs/components/speechinputreferenceaudioinput.mdx
index fa10a1fb..c16ea82c 100644
--- a/docs/components/speechinputreferenceaudioinput.mdx
+++ b/docs/components/speechinputreferenceaudioinput.mdx
@@ -7,7 +7,8 @@ Reference audio input object
## Fields
-| Field | Type | Required | Description | Example |
-| ------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| `data` | *str* | :heavy_check_mark: | Base64-encoded reference audio (optionally a data URI). Supported audio formats are provider-specific. Limited to 20 MiB of base64 (15 MiB of decoded audio). | data:audio/wav;base64,UklGRuQXDABXQVZF... |
-| `format_` | *Optional[str]* | :heavy_minus_sign: | Audio format of the reference audio (e.g., wav, mp3). Optional; most providers detect the format from the audio bytes. | wav |
\ No newline at end of file
+| Field | Type | Required | Description | Example |
+| --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| `data` | *Optional[str]* | :heavy_minus_sign: | Base64-encoded reference audio (optionally a data URI). Supported audio formats are provider-specific. Limited to 20 MiB of base64 (15 MiB of decoded audio). Exactly one of `data` or `url` is required. | data:audio/wav;base64,UklGRuQXDABXQVZF... |
+| `format_` | *Optional[str]* | :heavy_minus_sign: | Audio format of the reference audio (e.g., wav, mp3). Optional; most providers detect the format from the audio bytes. | wav |
+| `url` | *Optional[str]* | :heavy_minus_sign: | Public http(s) URL of the reference audio. OpenRouter downloads it (15 MiB max) and forwards the bytes, never the URL. Exactly one of `data` or `url` is required. | https://example.com/reference.wav |
\ No newline at end of file
diff --git a/docs/components/speechinputreferenceimage.mdx b/docs/components/speechinputreferenceimage.mdx
new file mode 100644
index 00000000..068290f7
--- /dev/null
+++ b/docs/components/speechinputreferenceimage.mdx
@@ -0,0 +1,13 @@
+---
+title: "SpeechInputReferenceImage"
+---
+
+Reference image describing the desired voice. Cannot be combined with `input_audio` parts. Only routed to endpoints that support image references.
+
+
+## Fields
+
+| Field | Type | Required | Description |
+| -------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------- |
+| `image_url` | [components.SpeechInputReferenceImageInput](../components/speechinputreferenceimageinput.mdx) | :heavy_check_mark: | Reference image input object |
+| `type` | [components.SpeechInputReferenceImageType](../components/speechinputreferenceimagetype.mdx) | :heavy_check_mark: | N/A |
\ No newline at end of file
diff --git a/docs/components/speechinputreferenceimageinput.mdx b/docs/components/speechinputreferenceimageinput.mdx
new file mode 100644
index 00000000..127f005a
--- /dev/null
+++ b/docs/components/speechinputreferenceimageinput.mdx
@@ -0,0 +1,12 @@
+---
+title: "SpeechInputReferenceImageInput"
+---
+
+Reference image input object
+
+
+## Fields
+
+| Field | Type | Required | Description | Example |
+| -------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| `url` | *str* | :heavy_check_mark: | JPEG, PNG, or WebP reference image as a base64 data URI or a public http(s) URL. Remote images are downloaded (15 MiB max) and forwarded as bytes, never as the URL. | data:image/png;base64,iVBORw0KGgo... |
\ No newline at end of file
diff --git a/docs/components/speechinputreferenceimagetype.mdx b/docs/components/speechinputreferenceimagetype.mdx
new file mode 100644
index 00000000..b40df3d3
--- /dev/null
+++ b/docs/components/speechinputreferenceimagetype.mdx
@@ -0,0 +1,15 @@
+---
+title: "SpeechInputReferenceImageType"
+---
+
+## Example Usage
+
+```python
+from openrouter.components import SpeechInputReferenceImageType
+value: SpeechInputReferenceImageType = "image_url"
+```
+
+
+## Values
+
+- `"image_url"`
diff --git a/docs/components/speechinputreferencetext.mdx b/docs/components/speechinputreferencetext.mdx
index ff25c492..af437e9f 100644
--- a/docs/components/speechinputreferencetext.mdx
+++ b/docs/components/speechinputreferencetext.mdx
@@ -2,12 +2,12 @@
title: "SpeechInputReferenceText"
---
-Transcript of the accompanying reference audio
+Transcript of an `input_audio` part
## Fields
-| Field | Type | Required | Description | Example |
-| ---------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------- |
-| `text` | *str* | :heavy_check_mark: | Transcript of the accompanying reference audio. | I used to rule the world. |
-| `type` | [components.SpeechInputReferenceTextType](../components/speechinputreferencetexttype.mdx) | :heavy_check_mark: | N/A | |
\ No newline at end of file
+| Field | Type | Required | Description | Example |
+| ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| `text` | *str* | :heavy_check_mark: | Transcript of an `input_audio` part. With a single clip it may appear before or after the clip; with multiple clips it must immediately follow the clip it transcribes. | I used to rule the world. |
+| `type` | [components.SpeechInputReferenceTextType](../components/speechinputreferencetexttype.mdx) | :heavy_check_mark: | N/A | |
\ No newline at end of file
diff --git a/docs/components/speechrequest.mdx b/docs/components/speechrequest.mdx
index a9c5cb01..2c861144 100644
--- a/docs/components/speechrequest.mdx
+++ b/docs/components/speechrequest.mdx
@@ -7,15 +7,15 @@ Text-to-speech request input
## Fields
-| Field | Type | Required | Description | Example |
-| ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| `input` | *str* | :heavy_check_mark: | Text to synthesize | Hello world |
-| `input_references` | List[[components.SpeechInputReference](../components/speechinputreference.mdx)] | :heavy_minus_sign: | Reference content for stateless voice cloning: one `input_audio` part carrying the voice sample, optionally accompanied by one `text` part with its transcript. Only routed to endpoints that support voice cloning. | [
\{
"input_audio": \{
"data": "data:audio/wav;base64,UklGRuQXDABXQVZF..."
},
"type": "input_audio"
},
\{
"text": "I used to rule the world.",
"type": "text"
}
] |
-| `model` | *str* | :heavy_check_mark: | TTS model identifier | mistralai/voxtral-mini-tts-2603 |
-| `provider` | [Optional[components.SpeechRequestProvider]](../components/speechrequestprovider.mdx) | :heavy_minus_sign: | Provider-specific passthrough configuration | |
-| `response_format` | [Optional[components.SpeechRequestResponseFormat]](../components/speechrequestresponseformat.mdx) | :heavy_minus_sign: | Audio output format | pcm |
-| `session_id` | *Optional[str]* | :heavy_minus_sign: | A unique identifier for grouping related requests (e.g., a conversation or agent workflow). Used for observability grouping in Broadcast and private logging; never sent to the provider. If provided in both the request body and the x-session-id header, the body value takes precedence. Maximum of 256 characters. | session-1234 |
-| `speed` | *Optional[float]* | :heavy_minus_sign: | Playback speed multiplier. Only used by models that support it (e.g. OpenAI TTS). Ignored by other providers. | 1 |
-| `trace` | [Optional[components.TraceConfig]](../components/traceconfig.mdx) | :heavy_minus_sign: | Metadata for observability and tracing. Known keys (trace_id, trace_name, span_name, generation_name, parent_span_id) have special handling. Additional keys are passed through as custom metadata to configured broadcast destinations. | \{
"trace_id": "trace-abc123",
"trace_name": "my-app-trace"
} |
-| `user` | *Optional[str]* | :heavy_minus_sign: | A unique identifier representing your end-user. Forwarded to Broadcast and private logging as the end-user id; never sent to the provider. | user-1234 |
-| `voice` | *Optional[str]* | :heavy_minus_sign: | Voice identifier (provider-specific). | en_paul_neutral |
\ No newline at end of file
+| Field | Type | Required | Description | Example |
+| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
+| `input` | *str* | :heavy_check_mark: | Text to synthesize | Hello world |
+| `input_references` | List[[components.SpeechInputReference](../components/speechinputreference.mdx)] | :heavy_minus_sign: | Reference content for stateless voice cloning or voice design. Audio mode: one to three `input_audio` parts, each optionally paired with a `text` part carrying its transcript (a single clip accepts its transcript before or after it; with multiple clips each transcript immediately follows its clip); only routed to endpoints that support voice cloning (and multiple references when more than one part is sent). Image mode: exactly one `image_url` part; only routed to endpoints that support image references. The two modes cannot be mixed. An empty array is treated as no reference. | [
\{
"input_audio": \{
"data": "data:audio/wav;base64,UklGRuQXDABXQVZF..."
},
"type": "input_audio"
},
\{
"text": "I used to rule the world.",
"type": "text"
}
] |
+| `model` | *str* | :heavy_check_mark: | TTS model identifier | mistralai/voxtral-mini-tts-2603 |
+| `provider` | [Optional[components.SpeechRequestProvider]](../components/speechrequestprovider.mdx) | :heavy_minus_sign: | Provider-specific passthrough configuration | |
+| `response_format` | [Optional[components.SpeechRequestResponseFormat]](../components/speechrequestresponseformat.mdx) | :heavy_minus_sign: | Audio output format | pcm |
+| `session_id` | *Optional[str]* | :heavy_minus_sign: | A unique identifier for grouping related requests (e.g., a conversation or agent workflow). Used for observability grouping in Broadcast and private logging; never sent to the provider. If provided in both the request body and the x-session-id header, the body value takes precedence. Maximum of 256 characters. | session-1234 |
+| `speed` | *Optional[float]* | :heavy_minus_sign: | Playback speed multiplier. Only used by models that support it (e.g. OpenAI TTS). Ignored by other providers. | 1 |
+| `trace` | [Optional[components.TraceConfig]](../components/traceconfig.mdx) | :heavy_minus_sign: | Metadata for observability and tracing. Known keys (trace_id, trace_name, span_name, generation_name, parent_span_id) have special handling. Additional keys are passed through as custom metadata to configured broadcast destinations. | \{
"trace_id": "trace-abc123",
"trace_name": "my-app-trace"
} |
+| `user` | *Optional[str]* | :heavy_minus_sign: | A unique identifier representing your end-user. Forwarded to Broadcast and private logging as the end-user id; never sent to the provider. | user-1234 |
+| `voice` | *Optional[str]* | :heavy_minus_sign: | Voice identifier (provider-specific). | en_paul_neutral |
\ No newline at end of file
diff --git a/docs/sdks/tts/README.mdx b/docs/sdks/tts/README.mdx
index bc53071a..2d7b6d76 100644
--- a/docs/sdks/tts/README.mdx
+++ b/docs/sdks/tts/README.mdx
@@ -38,22 +38,22 @@ with OpenRouter(
### Parameters
-| Parameter | Type | Required | Description | Example |
-| ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| `input` | *str* | :heavy_check_mark: | Text to synthesize | Hello world |
-| `model` | *str* | :heavy_check_mark: | TTS model identifier | mistralai/voxtral-mini-tts-2603 |
-| `http_referer` | *Optional[str]* | :heavy_minus_sign: | The app identifier should be your app's URL and is used as the primary identifier for rankings.
This is used to track API usage per application.
| |
-| `x_open_router_title` | *Optional[str]* | :heavy_minus_sign: | The app display name allows you to customize how your app appears in OpenRouter's dashboard.
| |
-| `x_open_router_categories` | *Optional[str]* | :heavy_minus_sign: | Comma-separated list of app categories (e.g. "cli-agent,cloud-agent"). Used for marketplace rankings.
| |
-| `input_references` | List[[components.SpeechInputReference](../../components/speechinputreference.mdx)] | :heavy_minus_sign: | Reference content for stateless voice cloning: one `input_audio` part carrying the voice sample, optionally accompanied by one `text` part with its transcript. Only routed to endpoints that support voice cloning. | [
\{
"input_audio": \{
"data": "data:audio/wav;base64,UklGRuQXDABXQVZF..."
},
"type": "input_audio"
},
\{
"text": "I used to rule the world.",
"type": "text"
}
] |
-| `provider` | [Optional[components.SpeechRequestProvider]](../../components/speechrequestprovider.mdx) | :heavy_minus_sign: | Provider-specific passthrough configuration | |
-| `response_format` | [Optional[components.SpeechRequestResponseFormat]](../../components/speechrequestresponseformat.mdx) | :heavy_minus_sign: | Audio output format | pcm |
-| `session_id` | *Optional[str]* | :heavy_minus_sign: | A unique identifier for grouping related requests (e.g., a conversation or agent workflow). Used for observability grouping in Broadcast and private logging; never sent to the provider. If provided in both the request body and the x-session-id header, the body value takes precedence. Maximum of 256 characters. | session-1234 |
-| `speed` | *Optional[float]* | :heavy_minus_sign: | Playback speed multiplier. Only used by models that support it (e.g. OpenAI TTS). Ignored by other providers. | 1 |
-| `trace` | [Optional[components.TraceConfig]](../../components/traceconfig.mdx) | :heavy_minus_sign: | Metadata for observability and tracing. Known keys (trace_id, trace_name, span_name, generation_name, parent_span_id) have special handling. Additional keys are passed through as custom metadata to configured broadcast destinations. | \{
"trace_id": "trace-abc123",
"trace_name": "my-app-trace"
} |
-| `user` | *Optional[str]* | :heavy_minus_sign: | A unique identifier representing your end-user. Forwarded to Broadcast and private logging as the end-user id; never sent to the provider. | user-1234 |
-| `voice` | *Optional[str]* | :heavy_minus_sign: | Voice identifier (provider-specific). | en_paul_neutral |
-| `retries` | [Optional[utils.RetryConfig]](../../models/utils/retryconfig.mdx) | :heavy_minus_sign: | Configuration to override the default retry behavior of the client. | |
+| Parameter | Type | Required | Description | Example |
+| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
+| `input` | *str* | :heavy_check_mark: | Text to synthesize | Hello world |
+| `model` | *str* | :heavy_check_mark: | TTS model identifier | mistralai/voxtral-mini-tts-2603 |
+| `http_referer` | *Optional[str]* | :heavy_minus_sign: | The app identifier should be your app's URL and is used as the primary identifier for rankings.
This is used to track API usage per application.
| |
+| `x_open_router_title` | *Optional[str]* | :heavy_minus_sign: | The app display name allows you to customize how your app appears in OpenRouter's dashboard.
| |
+| `x_open_router_categories` | *Optional[str]* | :heavy_minus_sign: | Comma-separated list of app categories (e.g. "cli-agent,cloud-agent"). Used for marketplace rankings.
| |
+| `input_references` | List[[components.SpeechInputReference](../../components/speechinputreference.mdx)] | :heavy_minus_sign: | Reference content for stateless voice cloning or voice design. Audio mode: one to three `input_audio` parts, each optionally paired with a `text` part carrying its transcript (a single clip accepts its transcript before or after it; with multiple clips each transcript immediately follows its clip); only routed to endpoints that support voice cloning (and multiple references when more than one part is sent). Image mode: exactly one `image_url` part; only routed to endpoints that support image references. The two modes cannot be mixed. An empty array is treated as no reference. | [
\{
"input_audio": \{
"data": "data:audio/wav;base64,UklGRuQXDABXQVZF..."
},
"type": "input_audio"
},
\{
"text": "I used to rule the world.",
"type": "text"
}
] |
+| `provider` | [Optional[components.SpeechRequestProvider]](../../components/speechrequestprovider.mdx) | :heavy_minus_sign: | Provider-specific passthrough configuration | |
+| `response_format` | [Optional[components.SpeechRequestResponseFormat]](../../components/speechrequestresponseformat.mdx) | :heavy_minus_sign: | Audio output format | pcm |
+| `session_id` | *Optional[str]* | :heavy_minus_sign: | A unique identifier for grouping related requests (e.g., a conversation or agent workflow). Used for observability grouping in Broadcast and private logging; never sent to the provider. If provided in both the request body and the x-session-id header, the body value takes precedence. Maximum of 256 characters. | session-1234 |
+| `speed` | *Optional[float]* | :heavy_minus_sign: | Playback speed multiplier. Only used by models that support it (e.g. OpenAI TTS). Ignored by other providers. | 1 |
+| `trace` | [Optional[components.TraceConfig]](../../components/traceconfig.mdx) | :heavy_minus_sign: | Metadata for observability and tracing. Known keys (trace_id, trace_name, span_name, generation_name, parent_span_id) have special handling. Additional keys are passed through as custom metadata to configured broadcast destinations. | \{
"trace_id": "trace-abc123",
"trace_name": "my-app-trace"
} |
+| `user` | *Optional[str]* | :heavy_minus_sign: | A unique identifier representing your end-user. Forwarded to Broadcast and private logging as the end-user id; never sent to the provider. | user-1234 |
+| `voice` | *Optional[str]* | :heavy_minus_sign: | Voice identifier (provider-specific). | en_paul_neutral |
+| `retries` | [Optional[utils.RetryConfig]](../../models/utils/retryconfig.mdx) | :heavy_minus_sign: | Configuration to override the default retry behavior of the client. | |
### Response
diff --git a/pyproject.toml b/pyproject.toml
index 3cfb5350..08d4dd47 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,6 +1,6 @@
[project]
name = "openrouter"
-version = "1.2.27"
+version = "1.2.28"
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 e3bd110d..39525f89 100644
--- a/src/openrouter/_version.py
+++ b/src/openrouter/_version.py
@@ -3,10 +3,10 @@
import importlib.metadata
__title__: str = "openrouter"
-__version__: str = "1.2.27"
+__version__: str = "1.2.28"
__openapi_doc_version__: str = "1.0.0"
__gen_version__: str = "2.914.0"
-__user_agent__: str = "speakeasy-sdk/python 1.2.27 2.914.0 1.0.0 openrouter"
+__user_agent__: str = "speakeasy-sdk/python 1.2.28 2.914.0 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 7300d185..471fad91 100644
--- a/src/openrouter/components/__init__.py
+++ b/src/openrouter/components/__init__.py
@@ -3069,6 +3069,15 @@
SpeechInputReferenceAudioInput,
SpeechInputReferenceAudioInputTypedDict,
)
+ from .speechinputreferenceimage import (
+ SpeechInputReferenceImage,
+ SpeechInputReferenceImageType,
+ SpeechInputReferenceImageTypedDict,
+ )
+ from .speechinputreferenceimageinput import (
+ SpeechInputReferenceImageInput,
+ SpeechInputReferenceImageInputTypedDict,
+ )
from .speechinputreferencetext import (
SpeechInputReferenceText,
SpeechInputReferenceTextType,
@@ -5656,6 +5665,11 @@
"SpeechInputReferenceAudioInputTypedDict",
"SpeechInputReferenceAudioType",
"SpeechInputReferenceAudioTypedDict",
+ "SpeechInputReferenceImage",
+ "SpeechInputReferenceImageInput",
+ "SpeechInputReferenceImageInputTypedDict",
+ "SpeechInputReferenceImageType",
+ "SpeechInputReferenceImageTypedDict",
"SpeechInputReferenceText",
"SpeechInputReferenceTextType",
"SpeechInputReferenceTextTypedDict",
@@ -8328,6 +8342,11 @@
"SpeechInputReferenceAudioTypedDict": ".speechinputreferenceaudio",
"SpeechInputReferenceAudioInput": ".speechinputreferenceaudioinput",
"SpeechInputReferenceAudioInputTypedDict": ".speechinputreferenceaudioinput",
+ "SpeechInputReferenceImage": ".speechinputreferenceimage",
+ "SpeechInputReferenceImageType": ".speechinputreferenceimage",
+ "SpeechInputReferenceImageTypedDict": ".speechinputreferenceimage",
+ "SpeechInputReferenceImageInput": ".speechinputreferenceimageinput",
+ "SpeechInputReferenceImageInputTypedDict": ".speechinputreferenceimageinput",
"SpeechInputReferenceText": ".speechinputreferencetext",
"SpeechInputReferenceTextType": ".speechinputreferencetext",
"SpeechInputReferenceTextTypedDict": ".speechinputreferencetext",
diff --git a/src/openrouter/components/publicendpoint.py b/src/openrouter/components/publicendpoint.py
index 7830ec36..cfa5b51c 100644
--- a/src/openrouter/components/publicendpoint.py
+++ b/src/openrouter/components/publicendpoint.py
@@ -496,6 +496,10 @@ class PublicEndpointTypedDict(TypedDict):
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."""
@@ -550,13 +554,25 @@ class PublicEndpoint(BaseModel):
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_voice_cloning"]
+ [
+ "perf_last_30m_by_workload",
+ "status",
+ "supports_image_reference",
+ "supports_multiple_audio_references",
+ "supports_voice_cloning",
+ ]
)
nullable_fields = set(
[
diff --git a/src/openrouter/components/speechinputreference.py b/src/openrouter/components/speechinputreference.py
index 9f490fec..0881593a 100644
--- a/src/openrouter/components/speechinputreference.py
+++ b/src/openrouter/components/speechinputreference.py
@@ -5,6 +5,10 @@
SpeechInputReferenceAudio,
SpeechInputReferenceAudioTypedDict,
)
+from .speechinputreferenceimage import (
+ SpeechInputReferenceImage,
+ SpeechInputReferenceImageTypedDict,
+)
from .speechinputreferencetext import (
SpeechInputReferenceText,
SpeechInputReferenceTextTypedDict,
@@ -17,16 +21,21 @@
SpeechInputReferenceTypedDict = TypeAliasType(
"SpeechInputReferenceTypedDict",
- Union[SpeechInputReferenceAudioTypedDict, SpeechInputReferenceTextTypedDict],
+ Union[
+ SpeechInputReferenceAudioTypedDict,
+ SpeechInputReferenceTextTypedDict,
+ SpeechInputReferenceImageTypedDict,
+ ],
)
-r"""Reference content part for stateless voice cloning"""
+r"""Reference content part for stateless voice cloning or voice design"""
SpeechInputReference = Annotated[
Union[
+ Annotated[SpeechInputReferenceImage, Tag("image_url")],
Annotated[SpeechInputReferenceAudio, Tag("input_audio")],
Annotated[SpeechInputReferenceText, Tag("text")],
],
Discriminator(lambda m: get_discriminator(m, "type", "type")),
]
-r"""Reference content part for stateless voice cloning"""
+r"""Reference content part for stateless voice cloning or voice design"""
diff --git a/src/openrouter/components/speechinputreferenceaudio.py b/src/openrouter/components/speechinputreferenceaudio.py
index 7341493f..3f346893 100644
--- a/src/openrouter/components/speechinputreferenceaudio.py
+++ b/src/openrouter/components/speechinputreferenceaudio.py
@@ -14,7 +14,7 @@
class SpeechInputReferenceAudioTypedDict(TypedDict):
- r"""Reference audio input for stateless voice cloning"""
+ r"""Reference audio input for stateless voice cloning. Up to three parts per request; the Nth audio part is addressable from `input` as `@AudioN` on providers that support multiple references."""
input_audio: SpeechInputReferenceAudioInputTypedDict
r"""Reference audio input object"""
@@ -22,7 +22,7 @@ class SpeechInputReferenceAudioTypedDict(TypedDict):
class SpeechInputReferenceAudio(BaseModel):
- r"""Reference audio input for stateless voice cloning"""
+ r"""Reference audio input for stateless voice cloning. Up to three parts per request; the Nth audio part is addressable from `input` as `@AudioN` on providers that support multiple references."""
input_audio: SpeechInputReferenceAudioInput
r"""Reference audio input object"""
diff --git a/src/openrouter/components/speechinputreferenceaudioinput.py b/src/openrouter/components/speechinputreferenceaudioinput.py
index c6e21210..33d35ab0 100644
--- a/src/openrouter/components/speechinputreferenceaudioinput.py
+++ b/src/openrouter/components/speechinputreferenceaudioinput.py
@@ -11,24 +11,29 @@
class SpeechInputReferenceAudioInputTypedDict(TypedDict):
r"""Reference audio input object"""
- data: str
- r"""Base64-encoded reference audio (optionally a data URI). Supported audio formats are provider-specific. Limited to 20 MiB of base64 (15 MiB of decoded audio)."""
+ data: NotRequired[str]
+ r"""Base64-encoded reference audio (optionally a data URI). Supported audio formats are provider-specific. Limited to 20 MiB of base64 (15 MiB of decoded audio). Exactly one of `data` or `url` is required."""
format_: NotRequired[str]
r"""Audio format of the reference audio (e.g., wav, mp3). Optional; most providers detect the format from the audio bytes."""
+ url: NotRequired[str]
+ r"""Public http(s) URL of the reference audio. OpenRouter downloads it (15 MiB max) and forwards the bytes, never the URL. Exactly one of `data` or `url` is required."""
class SpeechInputReferenceAudioInput(BaseModel):
r"""Reference audio input object"""
- data: str
- r"""Base64-encoded reference audio (optionally a data URI). Supported audio formats are provider-specific. Limited to 20 MiB of base64 (15 MiB of decoded audio)."""
+ data: Optional[str] = None
+ r"""Base64-encoded reference audio (optionally a data URI). Supported audio formats are provider-specific. Limited to 20 MiB of base64 (15 MiB of decoded audio). Exactly one of `data` or `url` is required."""
format_: Annotated[Optional[str], pydantic.Field(alias="format")] = None
r"""Audio format of the reference audio (e.g., wav, mp3). Optional; most providers detect the format from the audio bytes."""
+ url: Optional[str] = None
+ r"""Public http(s) URL of the reference audio. OpenRouter downloads it (15 MiB max) and forwards the bytes, never the URL. Exactly one of `data` or `url` is required."""
+
@model_serializer(mode="wrap")
def serialize_model(self, handler):
- optional_fields = set(["format"])
+ optional_fields = set(["data", "format", "url"])
serialized = handler(self)
m = {}
diff --git a/src/openrouter/components/speechinputreferenceimage.py b/src/openrouter/components/speechinputreferenceimage.py
new file mode 100644
index 00000000..6129f2f1
--- /dev/null
+++ b/src/openrouter/components/speechinputreferenceimage.py
@@ -0,0 +1,30 @@
+"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT."""
+
+from __future__ import annotations
+from .speechinputreferenceimageinput import (
+ SpeechInputReferenceImageInput,
+ SpeechInputReferenceImageInputTypedDict,
+)
+from openrouter.types import BaseModel
+from typing import Literal
+from typing_extensions import TypedDict
+
+
+SpeechInputReferenceImageType = Literal["image_url",]
+
+
+class SpeechInputReferenceImageTypedDict(TypedDict):
+ r"""Reference image describing the desired voice. Cannot be combined with `input_audio` parts. Only routed to endpoints that support image references."""
+
+ image_url: SpeechInputReferenceImageInputTypedDict
+ r"""Reference image input object"""
+ type: SpeechInputReferenceImageType
+
+
+class SpeechInputReferenceImage(BaseModel):
+ r"""Reference image describing the desired voice. Cannot be combined with `input_audio` parts. Only routed to endpoints that support image references."""
+
+ image_url: SpeechInputReferenceImageInput
+ r"""Reference image input object"""
+
+ type: SpeechInputReferenceImageType
diff --git a/src/openrouter/components/speechinputreferenceimageinput.py b/src/openrouter/components/speechinputreferenceimageinput.py
new file mode 100644
index 00000000..f9626067
--- /dev/null
+++ b/src/openrouter/components/speechinputreferenceimageinput.py
@@ -0,0 +1,19 @@
+"""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 SpeechInputReferenceImageInputTypedDict(TypedDict):
+ r"""Reference image input object"""
+
+ url: str
+ r"""JPEG, PNG, or WebP reference image as a base64 data URI or a public http(s) URL. Remote images are downloaded (15 MiB max) and forwarded as bytes, never as the URL."""
+
+
+class SpeechInputReferenceImageInput(BaseModel):
+ r"""Reference image input object"""
+
+ url: str
+ r"""JPEG, PNG, or WebP reference image as a base64 data URI or a public http(s) URL. Remote images are downloaded (15 MiB max) and forwarded as bytes, never as the URL."""
diff --git a/src/openrouter/components/speechinputreferencetext.py b/src/openrouter/components/speechinputreferencetext.py
index e1703efe..4633e5d7 100644
--- a/src/openrouter/components/speechinputreferencetext.py
+++ b/src/openrouter/components/speechinputreferencetext.py
@@ -10,17 +10,17 @@
class SpeechInputReferenceTextTypedDict(TypedDict):
- r"""Transcript of the accompanying reference audio"""
+ r"""Transcript of an `input_audio` part"""
text: str
- r"""Transcript of the accompanying reference audio."""
+ r"""Transcript of an `input_audio` part. With a single clip it may appear before or after the clip; with multiple clips it must immediately follow the clip it transcribes."""
type: SpeechInputReferenceTextType
class SpeechInputReferenceText(BaseModel):
- r"""Transcript of the accompanying reference audio"""
+ r"""Transcript of an `input_audio` part"""
text: str
- r"""Transcript of the accompanying reference audio."""
+ r"""Transcript of an `input_audio` part. With a single clip it may appear before or after the clip; with multiple clips it must immediately follow the clip it transcribes."""
type: SpeechInputReferenceTextType
diff --git a/src/openrouter/components/speechrequest.py b/src/openrouter/components/speechrequest.py
index e38473a5..877daa6a 100644
--- a/src/openrouter/components/speechrequest.py
+++ b/src/openrouter/components/speechrequest.py
@@ -58,7 +58,7 @@ class SpeechRequestTypedDict(TypedDict):
model: str
r"""TTS model identifier"""
input_references: NotRequired[List[SpeechInputReferenceTypedDict]]
- r"""Reference content for stateless voice cloning: one `input_audio` part carrying the voice sample, optionally accompanied by one `text` part with its transcript. Only routed to endpoints that support voice cloning."""
+ r"""Reference content for stateless voice cloning or voice design. Audio mode: one to three `input_audio` parts, each optionally paired with a `text` part carrying its transcript (a single clip accepts its transcript before or after it; with multiple clips each transcript immediately follows its clip); only routed to endpoints that support voice cloning (and multiple references when more than one part is sent). Image mode: exactly one `image_url` part; only routed to endpoints that support image references. The two modes cannot be mixed. An empty array is treated as no reference."""
provider: NotRequired[SpeechRequestProviderTypedDict]
r"""Provider-specific passthrough configuration"""
response_format: NotRequired[SpeechRequestResponseFormat]
@@ -85,7 +85,7 @@ class SpeechRequest(BaseModel):
r"""TTS model identifier"""
input_references: Optional[List[SpeechInputReference]] = None
- r"""Reference content for stateless voice cloning: one `input_audio` part carrying the voice sample, optionally accompanied by one `text` part with its transcript. Only routed to endpoints that support voice cloning."""
+ r"""Reference content for stateless voice cloning or voice design. Audio mode: one to three `input_audio` parts, each optionally paired with a `text` part carrying its transcript (a single clip accepts its transcript before or after it; with multiple clips each transcript immediately follows its clip); only routed to endpoints that support voice cloning (and multiple references when more than one part is sent). Image mode: exactly one `image_url` part; only routed to endpoints that support image references. The two modes cannot be mixed. An empty array is treated as no reference."""
provider: Optional[SpeechRequestProvider] = None
r"""Provider-specific passthrough configuration"""
diff --git a/src/openrouter/tts.py b/src/openrouter/tts.py
index 7903797c..7fd842bd 100644
--- a/src/openrouter/tts.py
+++ b/src/openrouter/tts.py
@@ -59,7 +59,7 @@ def create_speech(
:param x_open_router_categories: Comma-separated list of app categories (e.g. \"cli-agent,cloud-agent\"). Used for marketplace rankings.
- :param input_references: Reference content for stateless voice cloning: one `input_audio` part carrying the voice sample, optionally accompanied by one `text` part with its transcript. Only routed to endpoints that support voice cloning.
+ :param input_references: Reference content for stateless voice cloning or voice design. Audio mode: one to three `input_audio` parts, each optionally paired with a `text` part carrying its transcript (a single clip accepts its transcript before or after it; with multiple clips each transcript immediately follows its clip); only routed to endpoints that support voice cloning (and multiple references when more than one part is sent). Image mode: exactly one `image_url` part; only routed to endpoints that support image references. The two modes cannot be mixed. An empty array is treated as no reference.
:param provider: Provider-specific passthrough configuration
:param response_format: Audio output format
:param session_id: A unique identifier for grouping related requests (e.g., a conversation or agent workflow). Used for observability grouping in Broadcast and private logging; never sent to the provider. If provided in both the request body and the x-session-id header, the body value takes precedence. Maximum of 256 characters.
@@ -312,7 +312,7 @@ async def create_speech_async(
:param x_open_router_categories: Comma-separated list of app categories (e.g. \"cli-agent,cloud-agent\"). Used for marketplace rankings.
- :param input_references: Reference content for stateless voice cloning: one `input_audio` part carrying the voice sample, optionally accompanied by one `text` part with its transcript. Only routed to endpoints that support voice cloning.
+ :param input_references: Reference content for stateless voice cloning or voice design. Audio mode: one to three `input_audio` parts, each optionally paired with a `text` part carrying its transcript (a single clip accepts its transcript before or after it; with multiple clips each transcript immediately follows its clip); only routed to endpoints that support voice cloning (and multiple references when more than one part is sent). Image mode: exactly one `image_url` part; only routed to endpoints that support image references. The two modes cannot be mixed. An empty array is treated as no reference.
:param provider: Provider-specific passthrough configuration
:param response_format: Audio output format
:param session_id: A unique identifier for grouping related requests (e.g., a conversation or agent workflow). Used for observability grouping in Broadcast and private logging; never sent to the provider. If provided in both the request body and the x-session-id header, the body value takes precedence. Maximum of 256 characters.
diff --git a/uv.lock b/uv.lock
index 9059cede..0f644753 100644
--- a/uv.lock
+++ b/uv.lock
@@ -213,7 +213,7 @@ wheels = [
[[package]]
name = "openrouter"
-version = "1.2.27"
+version = "1.2.28"
source = { editable = "." }
dependencies = [
{ name = "httpcore" },