diff --git a/.speakeasy/gen.lock b/.speakeasy/gen.lock
index 8a9384a2..cb8600db 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: 8ed3bce5631ad96347bbc340ae00f480
+ docChecksum: d664cceac37f153c342d57d88340d3d7
docVersion: 1.0.0
speakeasyVersion: 1.787.0
generationVersion: 2.914.0
- releaseVersion: 1.1.70
- configChecksum: 05133456c74de87129259578572364ae
+ releaseVersion: 1.1.71
+ configChecksum: be09f1b7b3d40d9514d0173b2520cf47
repoURL: https://github.com/OpenRouterTeam/python-sdk.git
installationURL: https://github.com/OpenRouterTeam/python-sdk.git
published: true
persistentEdits:
- generation_id: 9c81eba8-3edd-490b-88fe-c604f9d912d0
- pristine_commit_hash: 2e7ce19453dd4bb87f46f0122a5e5a4dc981c8a6
- pristine_tree_hash: 763f77ddad320d306a8a22a9aa70f22a315c9bef
+ generation_id: 429ea40d-52a2-4a40-80ed-19c66adcb71e
+ pristine_commit_hash: 87b0c7e42555161909c4035cf8f185620f82415b
+ pristine_tree_hash: 746b5e522470828ad8816313de83fafe9ead8a08
features:
python:
acceptHeaders: 3.0.0
@@ -1546,8 +1546,8 @@ trackedFiles:
pristine_git_object: 753493b8d505e9317dcaca6fc897da7e30e91d0c
docs/components/createbyokkeyrequest.mdx:
id: 2af3019aa2a7
- last_write_checksum: sha1:8043e06630237922eaccbf4f0cea0d9c306116ad
- pristine_git_object: 1bb9f670ee89c79fa917de5d75960818e91a237a
+ last_write_checksum: sha1:a61a6569552f17904c29e6ed273c6e0faef04926
+ pristine_git_object: 4be6d94868a20068bb37cc469a87b9e07fd7d406
docs/components/createbyokkeyresponse.mdx:
id: 73f247dc0e33
last_write_checksum: sha1:c4dbcd1ccaf3465a42c9370ce785d1be420eda5c
@@ -5458,8 +5458,8 @@ trackedFiles:
pristine_git_object: 5a7e1816ae9370995ad90941ba4ba288d170d421
docs/components/updatebyokkeyrequest.mdx:
id: db0862ec6814
- last_write_checksum: sha1:455ef2d62d3a47dc683e611a1e5b9943173f41d0
- pristine_git_object: fcdb0bb2f50a9c63912e5dd911039e1f5d3b05a8
+ last_write_checksum: sha1:39b6ffc8a8ef18dd316deb68a2f4c5f91797d058
+ pristine_git_object: 2aa03a8b47c8d8b7f21d98d24384a64ea3d7fb1d
docs/components/updatebyokkeyresponse.mdx:
id: 9b4490c340b4
last_write_checksum: sha1:e80cd233e3de3358ea447fc32844fabb9ba121bf
@@ -7154,8 +7154,8 @@ trackedFiles:
pristine_git_object: 08ef8d73c050b6baab18ef6e246a1d074179b21f
docs/sdks/byok/README.mdx:
id: 17792f3b180d
- last_write_checksum: sha1:1520e531278af50a90ab6fb38e06a36fad90138f
- pristine_git_object: d86220a274db607e8f15025c7e173563e47f3794
+ last_write_checksum: sha1:d9948090ea7d2de3f60ea1743d3285056b44dbee
+ pristine_git_object: ff69431d7a24ef8ed82244feb3553257a86d78c6
docs/sdks/chat/README.mdx:
id: 1dd859c23fe1
last_write_checksum: sha1:75cf7ecf14bdaae4b3e2c767dc3d2c9d9e41d31c
@@ -7254,8 +7254,8 @@ trackedFiles:
pristine_git_object: 3e38f1a929f7d6b1d6de74604aa87e3d8f010544
pyproject.toml:
id: 5d07e7d72637
- last_write_checksum: sha1:c62d176755cb2c7889ba3c916373b6da5467d6ab
- pristine_git_object: ef0adf665003d73a26729beb01928d60e3312d4c
+ last_write_checksum: sha1:42baab7c320fb18f069970f37e2fd74f58945876
+ pristine_git_object: 9ca49fb9d0250444611fcc98af9283825a924da8
scripts/prepare_readme.py:
id: e0c5957a6035
last_write_checksum: sha1:77f44b60b98bc126557ec27391f91dfba764bb54
@@ -7282,8 +7282,8 @@ trackedFiles:
pristine_git_object: 86713cfea633e09d33b3d4e65281071fe20e6137
src/openrouter/_version.py:
id: d8d15ad6c586
- last_write_checksum: sha1:bca2b6914d6368541bcd4305996eb835294ccba8
- pristine_git_object: 10b7f60d3125567d78817aa3431998e8f3df6261
+ last_write_checksum: sha1:4be82d99f28e1fc9d893a231a8fa3057458b05ff
+ pristine_git_object: 047bec54394175afee6aff5c79012fb2f911ce34
src/openrouter/analytics.py:
id: cb406b5aaabb
last_write_checksum: sha1:1e0004d8d1d5d797e2b54cd1cabeb7f9489d08e9
@@ -7310,8 +7310,8 @@ trackedFiles:
pristine_git_object: 412aed86e32b1fd166d27e06e562463fa2b04395
src/openrouter/byok.py:
id: bec352462ae1
- last_write_checksum: sha1:cc8870e008a6a2b86ca173a99800792d06097205
- pristine_git_object: 627c6084130e7c8a9821950b9dd62ae0f5ac1281
+ last_write_checksum: sha1:53ccad720a80810d843e241aff4b5ac457d4c8f5
+ pristine_git_object: 0d8c44d7b7d19d3b28b615723eed5a08340f489d
src/openrouter/chat.py:
id: 723fdce15c1d
last_write_checksum: sha1:1a4e5375fb95884be6db0f508e1c2c9cda27b20e
@@ -8002,8 +8002,8 @@ trackedFiles:
pristine_git_object: dbafc2878cb3185fac34919e2f789b26dc86f70e
src/openrouter/components/createbyokkeyrequest.py:
id: 238e868445b4
- last_write_checksum: sha1:71d253f65eb95fd04de90ef120623375708592f7
- pristine_git_object: d79f38d162da4661affe6dddc4eaf9e956b79582
+ last_write_checksum: sha1:5320d73056ed0e00b264e7dda3d7f6086fc6664a
+ pristine_git_object: 7d41b9f96d153a26a1ff101b9003abf4c4a5d38a
src/openrouter/components/createbyokkeyresponse.py:
id: 2b6c5e13270a
last_write_checksum: sha1:a7a2a40b9ac16a975a4c5ecc8802fc0b7785691c
@@ -9610,8 +9610,8 @@ trackedFiles:
pristine_git_object: 696d3c578c6b09f9768e52a7dd000284fb62f1b7
src/openrouter/components/updatebyokkeyrequest.py:
id: 5edad69c278d
- last_write_checksum: sha1:c4c5bb57979e5251e5423cfe19b22036a6f8cb54
- pristine_git_object: 865262ac26028a07c34a2d678882320af9f674fc
+ last_write_checksum: sha1:272d6d4f106330f1bec5b5b0d60efb9bbbb81755
+ pristine_git_object: c3c764755f4ea1b37dbcf12ac5a966ab4052e66b
src/openrouter/components/updatebyokkeyresponse.py:
id: 31338080f7cc
last_write_checksum: sha1:794d77355ae37451076a6b5754c6c8cc77063047
@@ -12175,3 +12175,7 @@ examples:
"500":
application/json: {"error": {"code": 500, "message": "Internal Server Error"}}
examplesVersion: 1.0.2
+releaseNotes: |
+ ## Python SDK Changes:
+ * `open_router.byok.create()`: `request.allowed_api_key_hashes` **Added**
+ * `open_router.byok.update()`: `request.allowed_api_key_hashes` **Added**
diff --git a/.speakeasy/gen.yaml b/.speakeasy/gen.yaml
index a9ef9d60..3d974ce7 100644
--- a/.speakeasy/gen.yaml
+++ b/.speakeasy/gen.yaml
@@ -36,7 +36,7 @@ generation:
documentation: mintlify
preApplyUnionDiscriminators: true
python:
- version: 1.1.70
+ version: 1.1.71
additionalDependencies:
dev: {}
main: {}
diff --git a/.speakeasy/out.openapi.yaml b/.speakeasy/out.openapi.yaml
index 2224f71c..a07d9058 100644
--- a/.speakeasy/out.openapi.yaml
+++ b/.speakeasy/out.openapi.yaml
@@ -6974,6 +6974,18 @@ components:
name: 'Production OpenAI Key'
provider: 'openai'
properties:
+ allowed_api_key_hashes:
+ description: 'Optional allowlist of OpenRouter API key hashes (`api_keys.hash`) that may use this credential. `null` means no restriction. Must contain at least one hash if provided. Hashes that do not belong to your account return a 400.'
+ example:
+ - 'f01d52606dc8f0a8303a7b5cc3fa07109c2e346cec7c0a16b40de462992ce943'
+ items:
+ pattern: '^[a-f0-9]{64}$'
+ type: 'string'
+ maxItems: 100
+ minItems: 1
+ type:
+ - 'array'
+ - 'null'
allowed_models:
description: 'Optional allowlist of model slugs this credential may be used for. `null` means no restriction.'
example: null
@@ -24958,6 +24970,18 @@ components:
disabled: false
name: 'Updated OpenAI Key'
properties:
+ allowed_api_key_hashes:
+ description: 'Optional allowlist of OpenRouter API key hashes (`api_keys.hash`) that may use this credential. `null` clears the restriction. Must contain at least one hash if provided. Hashes that do not belong to your account return a 400.'
+ example:
+ - 'f01d52606dc8f0a8303a7b5cc3fa07109c2e346cec7c0a16b40de462992ce943'
+ items:
+ pattern: '^[a-f0-9]{64}$'
+ type: 'string'
+ maxItems: 100
+ minItems: 1
+ type:
+ - 'array'
+ - 'null'
allowed_models:
description: 'Optional allowlist of model slugs this credential may be used for. `null` means no restriction.'
example: null
@@ -28242,7 +28266,7 @@ paths:
results: '$.data'
type: 'offsetLimit'
post:
- description: 'Create a new bring-your-own-key (BYOK) provider credential. The raw key is encrypted at rest and never returned in API responses. When `workspace_id` is omitted, the credential is created in the default workspace; if that default has been deleted, the request returns a 400 and you must pass `workspace_id` explicitly. Treat the raw key as write-only; it is never returned after creation. [Management key](/docs/guides/overview/auth/management-api-keys) required.'
+ description: 'Create a new bring-your-own-key (BYOK) provider credential. The raw key is encrypted at rest and never returned in API responses. When `workspace_id` is omitted, the credential is created in the default workspace; if that default has been deleted, the request returns a 400 and you must pass `workspace_id` explicitly. Treat the raw key as write-only; it is never returned after creation. Use `allowed_api_key_hashes` to restrict the credential to specific OpenRouter API keys. [Management key](/docs/guides/overview/auth/management-api-keys) required.'
operationId: 'createBYOKKey'
requestBody:
content:
@@ -28449,7 +28473,7 @@ paths:
- 'BYOK'
x-speakeasy-name-override: 'get'
patch:
- description: 'Update an existing bring-your-own-key (BYOK) provider credential by its `id`. Include the `key` field to rotate the raw provider API key in-place (the previous key material is overwritten). [Management key](/docs/guides/overview/auth/management-api-keys) required.'
+ description: 'Update an existing bring-your-own-key (BYOK) provider credential by its `id`. Include the `key` field to rotate the raw provider API key in-place (the previous key material is overwritten). Use `allowed_api_key_hashes` to restrict the credential to specific OpenRouter API keys (`null` clears the restriction). [Management key](/docs/guides/overview/auth/management-api-keys) required.'
operationId: 'updateBYOKKey'
parameters:
- description: 'The BYOK credential ID (UUID).'
diff --git a/.speakeasy/workflow.lock b/.speakeasy/workflow.lock
index 6f631c95..66c30e36 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:5e5a4db069d541e4b682c5b887778b9a3ad48f930306ac76e7aa78e0dab79808
- sourceBlobDigest: sha256:01364ffa74202e8f1e3ba7de276cc8e72f25593b7e498fe0f38052325ae7c561
+ sourceRevisionDigest: sha256:2bce355f397f2478126ed11211e0ba94469a608eb9a1021bb0be516e18cff9a0
+ sourceBlobDigest: sha256:dbb75107e44d9e615dd69a6347dee396d2dce265f9d8af7ebabf6f2a1f1a9613
tags:
- latest
- 1.0.0
@@ -11,10 +11,10 @@ targets:
open-router:
source: OpenRouter API
sourceNamespace: open-router-chat-completions-api
- sourceRevisionDigest: sha256:5e5a4db069d541e4b682c5b887778b9a3ad48f930306ac76e7aa78e0dab79808
- sourceBlobDigest: sha256:01364ffa74202e8f1e3ba7de276cc8e72f25593b7e498fe0f38052325ae7c561
+ sourceRevisionDigest: sha256:2bce355f397f2478126ed11211e0ba94469a608eb9a1021bb0be516e18cff9a0
+ sourceBlobDigest: sha256:dbb75107e44d9e615dd69a6347dee396d2dce265f9d8af7ebabf6f2a1f1a9613
codeSamplesNamespace: open-router-python-code-samples
- codeSamplesRevisionDigest: sha256:ee83d11c70c4aeee1b7060bd300018acab0bf4f98099057e14c020f03e18b59d
+ codeSamplesRevisionDigest: sha256:8d9e2fc0b054d14a13254ae9d129fd24818afd388ce7bd97b40df5bce63a49c0
workflow:
workflowVersion: 1.0.0
speakeasyVersion: 1.787.0
diff --git a/RELEASES.md b/RELEASES.md
index 9ef1a35d..94944448 100644
--- a/RELEASES.md
+++ b/RELEASES.md
@@ -1489,4 +1489,14 @@ Based on:
### Generated
- [python v1.1.70] .
### Releases
-- [PyPI v1.1.70] https://pypi.org/project/openrouter/1.1.70 - .
\ No newline at end of file
+- [PyPI v1.1.70] https://pypi.org/project/openrouter/1.1.70 - .
+
+## 2026-08-21 06:09:01
+### Changes
+Based on:
+- OpenAPI Doc
+- Speakeasy CLI 1.787.0 (2.914.0) https://github.com/speakeasy-api/speakeasy
+### Generated
+- [python v1.1.71] .
+### Releases
+- [PyPI v1.1.71] https://pypi.org/project/openrouter/1.1.71 - .
\ No newline at end of file
diff --git a/docs/components/createbyokkeyrequest.mdx b/docs/components/createbyokkeyrequest.mdx
index 1bb9f670..4be6d948 100644
--- a/docs/components/createbyokkeyrequest.mdx
+++ b/docs/components/createbyokkeyrequest.mdx
@@ -6,6 +6,7 @@ title: "CreateBYOKKeyRequest"
| Field | Type | Required | Description | Example |
| -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| `allowed_api_key_hashes` | List[*str*] | :heavy_minus_sign: | Optional allowlist of OpenRouter API key hashes (`api_keys.hash`) that may use this credential. `null` means no restriction. Must contain at least one hash if provided. Hashes that do not belong to your account return a 400. | [
"f01d52606dc8f0a8303a7b5cc3fa07109c2e346cec7c0a16b40de462992ce943"
] |
| `allowed_models` | List[*str*] | :heavy_minus_sign: | Optional allowlist of model slugs this credential may be used for. `null` means no restriction. | null |
| `allowed_user_ids` | List[*str*] | :heavy_minus_sign: | Optional allowlist of user IDs that may use this credential. `null` means no restriction. | null |
| `disabled` | *Optional[bool]* | :heavy_minus_sign: | Whether this credential should be created in a disabled state. | false |
diff --git a/docs/components/updatebyokkeyrequest.mdx b/docs/components/updatebyokkeyrequest.mdx
index fcdb0bb2..2aa03a8b 100644
--- a/docs/components/updatebyokkeyrequest.mdx
+++ b/docs/components/updatebyokkeyrequest.mdx
@@ -4,11 +4,12 @@ title: "UpdateBYOKKeyRequest"
## Fields
-| Field | Type | Required | Description | Example |
-| -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| `allowed_models` | List[*str*] | :heavy_minus_sign: | Optional allowlist of model slugs this credential may be used for. `null` means no restriction. | null |
-| `allowed_user_ids` | List[*str*] | :heavy_minus_sign: | Optional allowlist of user IDs that may use this credential. `null` means no restriction. | null |
-| `disabled` | *Optional[bool]* | :heavy_minus_sign: | Whether this credential is disabled. | false |
-| `is_fallback` | *Optional[bool]* | :heavy_minus_sign: | Whether this credential is treated as a fallback — used only after non-fallback keys for the same provider have been tried. | false |
-| `key` | *Optional[str]* | :heavy_minus_sign: | A new raw provider API key to rotate the credential in-place. The previous key material is overwritten and the masked label is regenerated. Encrypted at rest and never returned in API responses. | sk-proj-newkey456... |
-| `name` | *OptionalNullable[str]* | :heavy_minus_sign: | Optional human-readable name for the credential. | Updated OpenAI Key |
\ No newline at end of file
+| Field | Type | Required | Description | Example |
+| ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| `allowed_api_key_hashes` | List[*str*] | :heavy_minus_sign: | Optional allowlist of OpenRouter API key hashes (`api_keys.hash`) that may use this credential. `null` clears the restriction. Must contain at least one hash if provided. Hashes that do not belong to your account return a 400. | [
"f01d52606dc8f0a8303a7b5cc3fa07109c2e346cec7c0a16b40de462992ce943"
] |
+| `allowed_models` | List[*str*] | :heavy_minus_sign: | Optional allowlist of model slugs this credential may be used for. `null` means no restriction. | null |
+| `allowed_user_ids` | List[*str*] | :heavy_minus_sign: | Optional allowlist of user IDs that may use this credential. `null` means no restriction. | null |
+| `disabled` | *Optional[bool]* | :heavy_minus_sign: | Whether this credential is disabled. | false |
+| `is_fallback` | *Optional[bool]* | :heavy_minus_sign: | Whether this credential is treated as a fallback — used only after non-fallback keys for the same provider have been tried. | false |
+| `key` | *Optional[str]* | :heavy_minus_sign: | A new raw provider API key to rotate the credential in-place. The previous key material is overwritten and the masked label is regenerated. Encrypted at rest and never returned in API responses. | sk-proj-newkey456... |
+| `name` | *OptionalNullable[str]* | :heavy_minus_sign: | Optional human-readable name for the credential. | Updated OpenAI Key |
\ No newline at end of file
diff --git a/docs/sdks/byok/README.mdx b/docs/sdks/byok/README.mdx
index d86220a2..ff69431d 100644
--- a/docs/sdks/byok/README.mdx
+++ b/docs/sdks/byok/README.mdx
@@ -70,7 +70,7 @@ with OpenRouter(
## create
-Create a new bring-your-own-key (BYOK) provider credential. The raw key is encrypted at rest and never returned in API responses. When `workspace_id` is omitted, the credential is created in the default workspace; if that default has been deleted, the request returns a 400 and you must pass `workspace_id` explicitly. Treat the raw key as write-only; it is never returned after creation. [Management key](/docs/guides/overview/auth/management-api-keys) required.
+Create a new bring-your-own-key (BYOK) provider credential. The raw key is encrypted at rest and never returned in API responses. When `workspace_id` is omitted, the credential is created in the default workspace; if that default has been deleted, the request returns a 400 and you must pass `workspace_id` explicitly. Treat the raw key as write-only; it is never returned after creation. Use `allowed_api_key_hashes` to restrict the credential to specific OpenRouter API keys. [Management key](/docs/guides/overview/auth/management-api-keys) required.
### Example Usage
@@ -102,6 +102,7 @@ with OpenRouter(
| `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.
| |
+| `allowed_api_key_hashes` | List[*str*] | :heavy_minus_sign: | Optional allowlist of OpenRouter API key hashes (`api_keys.hash`) that may use this credential. `null` means no restriction. Must contain at least one hash if provided. Hashes that do not belong to your account return a 400. | [
"f01d52606dc8f0a8303a7b5cc3fa07109c2e346cec7c0a16b40de462992ce943"
] |
| `allowed_models` | List[*str*] | :heavy_minus_sign: | Optional allowlist of model slugs this credential may be used for. `null` means no restriction. | null |
| `allowed_user_ids` | List[*str*] | :heavy_minus_sign: | Optional allowlist of user IDs that may use this credential. `null` means no restriction. | null |
| `disabled` | *Optional[bool]* | :heavy_minus_sign: | Whether this credential should be created in a disabled state. | false |
@@ -222,7 +223,7 @@ with OpenRouter(
## update
-Update an existing bring-your-own-key (BYOK) provider credential by its `id`. Include the `key` field to rotate the raw provider API key in-place (the previous key material is overwritten). [Management key](/docs/guides/overview/auth/management-api-keys) required.
+Update an existing bring-your-own-key (BYOK) provider credential by its `id`. Include the `key` field to rotate the raw provider API key in-place (the previous key material is overwritten). Use `allowed_api_key_hashes` to restrict the credential to specific OpenRouter API keys (`null` clears the restriction). [Management key](/docs/guides/overview/auth/management-api-keys) required.
### Example Usage
@@ -247,19 +248,20 @@ with OpenRouter(
### Parameters
-| Parameter | Type | Required | Description | Example |
-| -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| `id` | *str* | :heavy_check_mark: | The BYOK credential ID (UUID). | 11111111-2222-3333-4444-555555555555 |
-| `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.
| |
-| `allowed_models` | List[*str*] | :heavy_minus_sign: | Optional allowlist of model slugs this credential may be used for. `null` means no restriction. | null |
-| `allowed_user_ids` | List[*str*] | :heavy_minus_sign: | Optional allowlist of user IDs that may use this credential. `null` means no restriction. | null |
-| `disabled` | *Optional[bool]* | :heavy_minus_sign: | Whether this credential is disabled. | false |
-| `is_fallback` | *Optional[bool]* | :heavy_minus_sign: | Whether this credential is treated as a fallback — used only after non-fallback keys for the same provider have been tried. | false |
-| `key` | *Optional[str]* | :heavy_minus_sign: | A new raw provider API key to rotate the credential in-place. The previous key material is overwritten and the masked label is regenerated. Encrypted at rest and never returned in API responses. | sk-proj-newkey456... |
-| `name` | *OptionalNullable[str]* | :heavy_minus_sign: | Optional human-readable name for the credential. | Updated OpenAI Key |
-| `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 |
+| ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| `id` | *str* | :heavy_check_mark: | The BYOK credential ID (UUID). | 11111111-2222-3333-4444-555555555555 |
+| `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.
| |
+| `allowed_api_key_hashes` | List[*str*] | :heavy_minus_sign: | Optional allowlist of OpenRouter API key hashes (`api_keys.hash`) that may use this credential. `null` clears the restriction. Must contain at least one hash if provided. Hashes that do not belong to your account return a 400. | [
"f01d52606dc8f0a8303a7b5cc3fa07109c2e346cec7c0a16b40de462992ce943"
] |
+| `allowed_models` | List[*str*] | :heavy_minus_sign: | Optional allowlist of model slugs this credential may be used for. `null` means no restriction. | null |
+| `allowed_user_ids` | List[*str*] | :heavy_minus_sign: | Optional allowlist of user IDs that may use this credential. `null` means no restriction. | null |
+| `disabled` | *Optional[bool]* | :heavy_minus_sign: | Whether this credential is disabled. | false |
+| `is_fallback` | *Optional[bool]* | :heavy_minus_sign: | Whether this credential is treated as a fallback — used only after non-fallback keys for the same provider have been tried. | false |
+| `key` | *Optional[str]* | :heavy_minus_sign: | A new raw provider API key to rotate the credential in-place. The previous key material is overwritten and the masked label is regenerated. Encrypted at rest and never returned in API responses. | sk-proj-newkey456... |
+| `name` | *OptionalNullable[str]* | :heavy_minus_sign: | Optional human-readable name for the credential. | Updated OpenAI Key |
+| `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 ef0adf66..9ca49fb9 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,6 +1,6 @@
[project]
name = "openrouter"
-version = "1.1.70"
+version = "1.1.71"
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 10b7f60d..047bec54 100644
--- a/src/openrouter/_version.py
+++ b/src/openrouter/_version.py
@@ -3,10 +3,10 @@
import importlib.metadata
__title__: str = "openrouter"
-__version__: str = "1.1.70"
+__version__: str = "1.1.71"
__openapi_doc_version__: str = "1.0.0"
__gen_version__: str = "2.914.0"
-__user_agent__: str = "speakeasy-sdk/python 1.1.70 2.914.0 1.0.0 openrouter"
+__user_agent__: str = "speakeasy-sdk/python 1.1.71 2.914.0 1.0.0 openrouter"
try:
if __package__ is not None:
diff --git a/src/openrouter/byok.py b/src/openrouter/byok.py
index 627c6084..0d8c44d7 100644
--- a/src/openrouter/byok.py
+++ b/src/openrouter/byok.py
@@ -366,6 +366,7 @@ def create(
http_referer: Optional[str] = None,
x_open_router_title: Optional[str] = None,
x_open_router_categories: Optional[str] = None,
+ allowed_api_key_hashes: OptionalNullable[Iterable[str]] = UNSET,
allowed_models: OptionalNullable[Iterable[str]] = UNSET,
allowed_user_ids: OptionalNullable[Iterable[str]] = UNSET,
disabled: Optional[bool] = None,
@@ -379,7 +380,7 @@ def create(
) -> components.CreateBYOKKeyResponse:
r"""Create a BYOK provider credential
- Create a new bring-your-own-key (BYOK) provider credential. The raw key is encrypted at rest and never returned in API responses. When `workspace_id` is omitted, the credential is created in the default workspace; if that default has been deleted, the request returns a 400 and you must pass `workspace_id` explicitly. Treat the raw key as write-only; it is never returned after creation. [Management key](/docs/guides/overview/auth/management-api-keys) required.
+ Create a new bring-your-own-key (BYOK) provider credential. The raw key is encrypted at rest and never returned in API responses. When `workspace_id` is omitted, the credential is created in the default workspace; if that default has been deleted, the request returns a 400 and you must pass `workspace_id` explicitly. Treat the raw key as write-only; it is never returned after creation. Use `allowed_api_key_hashes` to restrict the credential to specific OpenRouter API keys. [Management key](/docs/guides/overview/auth/management-api-keys) required.
:param key: The raw provider API key or credential. This value is encrypted at rest and never returned in API responses.
:param provider: The upstream provider this credential authenticates against, as a lowercase slug (e.g. `openai`, `anthropic`, `amazon-bedrock`).
@@ -390,6 +391,7 @@ def create(
:param x_open_router_categories: Comma-separated list of app categories (e.g. \"cli-agent,cloud-agent\"). Used for marketplace rankings.
+ :param allowed_api_key_hashes: Optional allowlist of OpenRouter API key hashes (`api_keys.hash`) that may use this credential. `null` means no restriction. Must contain at least one hash if provided. Hashes that do not belong to your account return a 400.
:param allowed_models: Optional allowlist of model slugs this credential may be used for. `null` means no restriction.
:param allowed_user_ids: Optional allowlist of user IDs that may use this credential. `null` means no restriction.
:param disabled: Whether this credential should be created in a disabled state.
@@ -416,6 +418,9 @@ def create(
x_open_router_title=x_open_router_title,
x_open_router_categories=x_open_router_categories,
create_byok_key_request=components.CreateBYOKKeyRequest(
+ allowed_api_key_hashes=utils.unmarshal(
+ allowed_api_key_hashes, OptionalNullable[List[str]]
+ ),
allowed_models=utils.unmarshal(
allowed_models, OptionalNullable[List[str]]
),
@@ -533,6 +538,7 @@ async def create_async(
http_referer: Optional[str] = None,
x_open_router_title: Optional[str] = None,
x_open_router_categories: Optional[str] = None,
+ allowed_api_key_hashes: OptionalNullable[Iterable[str]] = UNSET,
allowed_models: OptionalNullable[Iterable[str]] = UNSET,
allowed_user_ids: OptionalNullable[Iterable[str]] = UNSET,
disabled: Optional[bool] = None,
@@ -546,7 +552,7 @@ async def create_async(
) -> components.CreateBYOKKeyResponse:
r"""Create a BYOK provider credential
- Create a new bring-your-own-key (BYOK) provider credential. The raw key is encrypted at rest and never returned in API responses. When `workspace_id` is omitted, the credential is created in the default workspace; if that default has been deleted, the request returns a 400 and you must pass `workspace_id` explicitly. Treat the raw key as write-only; it is never returned after creation. [Management key](/docs/guides/overview/auth/management-api-keys) required.
+ Create a new bring-your-own-key (BYOK) provider credential. The raw key is encrypted at rest and never returned in API responses. When `workspace_id` is omitted, the credential is created in the default workspace; if that default has been deleted, the request returns a 400 and you must pass `workspace_id` explicitly. Treat the raw key as write-only; it is never returned after creation. Use `allowed_api_key_hashes` to restrict the credential to specific OpenRouter API keys. [Management key](/docs/guides/overview/auth/management-api-keys) required.
:param key: The raw provider API key or credential. This value is encrypted at rest and never returned in API responses.
:param provider: The upstream provider this credential authenticates against, as a lowercase slug (e.g. `openai`, `anthropic`, `amazon-bedrock`).
@@ -557,6 +563,7 @@ async def create_async(
:param x_open_router_categories: Comma-separated list of app categories (e.g. \"cli-agent,cloud-agent\"). Used for marketplace rankings.
+ :param allowed_api_key_hashes: Optional allowlist of OpenRouter API key hashes (`api_keys.hash`) that may use this credential. `null` means no restriction. Must contain at least one hash if provided. Hashes that do not belong to your account return a 400.
:param allowed_models: Optional allowlist of model slugs this credential may be used for. `null` means no restriction.
:param allowed_user_ids: Optional allowlist of user IDs that may use this credential. `null` means no restriction.
:param disabled: Whether this credential should be created in a disabled state.
@@ -583,6 +590,9 @@ async def create_async(
x_open_router_title=x_open_router_title,
x_open_router_categories=x_open_router_categories,
create_byok_key_request=components.CreateBYOKKeyRequest(
+ allowed_api_key_hashes=utils.unmarshal(
+ allowed_api_key_hashes, OptionalNullable[List[str]]
+ ),
allowed_models=utils.unmarshal(
allowed_models, OptionalNullable[List[str]]
),
@@ -1211,6 +1221,7 @@ def update(
http_referer: Optional[str] = None,
x_open_router_title: Optional[str] = None,
x_open_router_categories: Optional[str] = None,
+ allowed_api_key_hashes: OptionalNullable[Iterable[str]] = UNSET,
allowed_models: OptionalNullable[Iterable[str]] = UNSET,
allowed_user_ids: OptionalNullable[Iterable[str]] = UNSET,
disabled: Optional[bool] = None,
@@ -1224,7 +1235,7 @@ def update(
) -> components.UpdateBYOKKeyResponse:
r"""Update a BYOK provider credential
- Update an existing bring-your-own-key (BYOK) provider credential by its `id`. Include the `key` field to rotate the raw provider API key in-place (the previous key material is overwritten). [Management key](/docs/guides/overview/auth/management-api-keys) required.
+ Update an existing bring-your-own-key (BYOK) provider credential by its `id`. Include the `key` field to rotate the raw provider API key in-place (the previous key material is overwritten). Use `allowed_api_key_hashes` to restrict the credential to specific OpenRouter API keys (`null` clears the restriction). [Management key](/docs/guides/overview/auth/management-api-keys) required.
:param id: The BYOK credential ID (UUID).
:param http_referer: The app identifier should be your app's URL and is used as the primary identifier for rankings.
@@ -1234,6 +1245,7 @@ def update(
:param x_open_router_categories: Comma-separated list of app categories (e.g. \"cli-agent,cloud-agent\"). Used for marketplace rankings.
+ :param allowed_api_key_hashes: Optional allowlist of OpenRouter API key hashes (`api_keys.hash`) that may use this credential. `null` clears the restriction. Must contain at least one hash if provided. Hashes that do not belong to your account return a 400.
:param allowed_models: Optional allowlist of model slugs this credential may be used for. `null` means no restriction.
:param allowed_user_ids: Optional allowlist of user IDs that may use this credential. `null` means no restriction.
:param disabled: Whether this credential is disabled.
@@ -1261,6 +1273,9 @@ def update(
x_open_router_categories=x_open_router_categories,
id=id,
update_byok_key_request=components.UpdateBYOKKeyRequest(
+ allowed_api_key_hashes=utils.unmarshal(
+ allowed_api_key_hashes, OptionalNullable[List[str]]
+ ),
allowed_models=utils.unmarshal(
allowed_models, OptionalNullable[List[str]]
),
@@ -1375,6 +1390,7 @@ async def update_async(
http_referer: Optional[str] = None,
x_open_router_title: Optional[str] = None,
x_open_router_categories: Optional[str] = None,
+ allowed_api_key_hashes: OptionalNullable[Iterable[str]] = UNSET,
allowed_models: OptionalNullable[Iterable[str]] = UNSET,
allowed_user_ids: OptionalNullable[Iterable[str]] = UNSET,
disabled: Optional[bool] = None,
@@ -1388,7 +1404,7 @@ async def update_async(
) -> components.UpdateBYOKKeyResponse:
r"""Update a BYOK provider credential
- Update an existing bring-your-own-key (BYOK) provider credential by its `id`. Include the `key` field to rotate the raw provider API key in-place (the previous key material is overwritten). [Management key](/docs/guides/overview/auth/management-api-keys) required.
+ Update an existing bring-your-own-key (BYOK) provider credential by its `id`. Include the `key` field to rotate the raw provider API key in-place (the previous key material is overwritten). Use `allowed_api_key_hashes` to restrict the credential to specific OpenRouter API keys (`null` clears the restriction). [Management key](/docs/guides/overview/auth/management-api-keys) required.
:param id: The BYOK credential ID (UUID).
:param http_referer: The app identifier should be your app's URL and is used as the primary identifier for rankings.
@@ -1398,6 +1414,7 @@ async def update_async(
:param x_open_router_categories: Comma-separated list of app categories (e.g. \"cli-agent,cloud-agent\"). Used for marketplace rankings.
+ :param allowed_api_key_hashes: Optional allowlist of OpenRouter API key hashes (`api_keys.hash`) that may use this credential. `null` clears the restriction. Must contain at least one hash if provided. Hashes that do not belong to your account return a 400.
:param allowed_models: Optional allowlist of model slugs this credential may be used for. `null` means no restriction.
:param allowed_user_ids: Optional allowlist of user IDs that may use this credential. `null` means no restriction.
:param disabled: Whether this credential is disabled.
@@ -1425,6 +1442,9 @@ async def update_async(
x_open_router_categories=x_open_router_categories,
id=id,
update_byok_key_request=components.UpdateBYOKKeyRequest(
+ allowed_api_key_hashes=utils.unmarshal(
+ allowed_api_key_hashes, OptionalNullable[List[str]]
+ ),
allowed_models=utils.unmarshal(
allowed_models, OptionalNullable[List[str]]
),
diff --git a/src/openrouter/components/createbyokkeyrequest.py b/src/openrouter/components/createbyokkeyrequest.py
index d79f38d1..7d41b9f9 100644
--- a/src/openrouter/components/createbyokkeyrequest.py
+++ b/src/openrouter/components/createbyokkeyrequest.py
@@ -19,6 +19,8 @@ class CreateBYOKKeyRequestTypedDict(TypedDict):
r"""The raw provider API key or credential. This value is encrypted at rest and never returned in API responses."""
provider: BYOKProviderSlug
r"""The upstream provider this credential authenticates against, as a lowercase slug (e.g. `openai`, `anthropic`, `amazon-bedrock`)."""
+ allowed_api_key_hashes: NotRequired[Nullable[List[str]]]
+ r"""Optional allowlist of OpenRouter API key hashes (`api_keys.hash`) that may use this credential. `null` means no restriction. Must contain at least one hash if provided. Hashes that do not belong to your account return a 400."""
allowed_models: NotRequired[Nullable[List[str]]]
r"""Optional allowlist of model slugs this credential may be used for. `null` means no restriction."""
allowed_user_ids: NotRequired[Nullable[List[str]]]
@@ -40,6 +42,9 @@ class CreateBYOKKeyRequest(BaseModel):
provider: BYOKProviderSlug
r"""The upstream provider this credential authenticates against, as a lowercase slug (e.g. `openai`, `anthropic`, `amazon-bedrock`)."""
+ allowed_api_key_hashes: OptionalNullable[List[str]] = UNSET
+ r"""Optional allowlist of OpenRouter API key hashes (`api_keys.hash`) that may use this credential. `null` means no restriction. Must contain at least one hash if provided. Hashes that do not belong to your account return a 400."""
+
allowed_models: OptionalNullable[List[str]] = UNSET
r"""Optional allowlist of model slugs this credential may be used for. `null` means no restriction."""
@@ -62,6 +67,7 @@ class CreateBYOKKeyRequest(BaseModel):
def serialize_model(self, handler):
optional_fields = set(
[
+ "allowed_api_key_hashes",
"allowed_models",
"allowed_user_ids",
"disabled",
@@ -70,7 +76,9 @@ def serialize_model(self, handler):
"workspace_id",
]
)
- nullable_fields = set(["allowed_models", "allowed_user_ids", "name"])
+ nullable_fields = set(
+ ["allowed_api_key_hashes", "allowed_models", "allowed_user_ids", "name"]
+ )
serialized = handler(self)
m = {}
diff --git a/src/openrouter/components/updatebyokkeyrequest.py b/src/openrouter/components/updatebyokkeyrequest.py
index 865262ac..c3c76475 100644
--- a/src/openrouter/components/updatebyokkeyrequest.py
+++ b/src/openrouter/components/updatebyokkeyrequest.py
@@ -14,6 +14,8 @@
class UpdateBYOKKeyRequestTypedDict(TypedDict):
+ allowed_api_key_hashes: NotRequired[Nullable[List[str]]]
+ r"""Optional allowlist of OpenRouter API key hashes (`api_keys.hash`) that may use this credential. `null` clears the restriction. Must contain at least one hash if provided. Hashes that do not belong to your account return a 400."""
allowed_models: NotRequired[Nullable[List[str]]]
r"""Optional allowlist of model slugs this credential may be used for. `null` means no restriction."""
allowed_user_ids: NotRequired[Nullable[List[str]]]
@@ -29,6 +31,9 @@ class UpdateBYOKKeyRequestTypedDict(TypedDict):
class UpdateBYOKKeyRequest(BaseModel):
+ allowed_api_key_hashes: OptionalNullable[List[str]] = UNSET
+ r"""Optional allowlist of OpenRouter API key hashes (`api_keys.hash`) that may use this credential. `null` clears the restriction. Must contain at least one hash if provided. Hashes that do not belong to your account return a 400."""
+
allowed_models: OptionalNullable[List[str]] = UNSET
r"""Optional allowlist of model slugs this credential may be used for. `null` means no restriction."""
@@ -51,6 +56,7 @@ class UpdateBYOKKeyRequest(BaseModel):
def serialize_model(self, handler):
optional_fields = set(
[
+ "allowed_api_key_hashes",
"allowed_models",
"allowed_user_ids",
"disabled",
@@ -59,7 +65,9 @@ def serialize_model(self, handler):
"name",
]
)
- nullable_fields = set(["allowed_models", "allowed_user_ids", "name"])
+ nullable_fields = set(
+ ["allowed_api_key_hashes", "allowed_models", "allowed_user_ids", "name"]
+ )
serialized = handler(self)
m = {}
diff --git a/uv.lock b/uv.lock
index d4ecd9ab..bbcb275f 100644
--- a/uv.lock
+++ b/uv.lock
@@ -213,7 +213,7 @@ wheels = [
[[package]]
name = "openrouter"
-version = "1.1.70"
+version = "1.1.71"
source = { editable = "." }
dependencies = [
{ name = "httpcore" },