diff --git a/.speakeasy/gen.lock b/.speakeasy/gen.lock
index 5b240863..0f009fa5 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: 5e32c54953ba574d9ee698feec69132b
+ docChecksum: eafdf0a15ea851c11321f795d9eaeae6
docVersion: 1.0.0
speakeasyVersion: 1.787.0
generationVersion: 2.914.0
- releaseVersion: 0.11.19
- configChecksum: 68995e9d0f9c16d2db0f9967edfb3af3
+ releaseVersion: 0.11.20
+ configChecksum: 5415321126f7b1b42de92ec1c213d0d4
repoURL: https://github.com/OpenRouterTeam/python-sdk.git
installationURL: https://github.com/OpenRouterTeam/python-sdk.git
published: true
persistentEdits:
- generation_id: 1d141ee6-3f2d-4871-9848-c0b44ce3fc81
- pristine_commit_hash: 5d90a57f4c2fe856a5bdf25892ac7645ace722dc
- pristine_tree_hash: 79eec5b9a9eebb656a47a973193134b0f2f61d67
+ generation_id: 11b03c28-423b-4cf5-8a75-334f53189839
+ pristine_commit_hash: 78f9f7be2b502d7c7b11ec27fd701fa26a7834b2
+ pristine_tree_hash: a0a6f9597055f659340cba4c2f03acf2a76d857a
features:
python:
acceptHeaders: 3.0.0
@@ -5312,6 +5312,22 @@ trackedFiles:
id: db4a10e02011
last_write_checksum: sha1:07a2b233999d732b3559f431337d40cbfb8acb18
pristine_git_object: de22a4c7b44e291012ca85daacc77bde58afbfa4
+ docs/operations/classifierdimensions.mdx:
+ id: 5e48dede0ae4
+ last_write_checksum: sha1:9aea7af347af4565daaebcfced2f96f8957dfd1a
+ pristine_git_object: f7cf34faf7a89ceaeb2c20f9fd37f76e102defba
+ docs/operations/classifierfilters.mdx:
+ id: bf2b4d539ad0
+ last_write_checksum: sha1:882166611599b6921a6ec342986fe18bf78cf524
+ pristine_git_object: db4dbe946e875ad7189725a020f7ea2631a8adf3
+ docs/operations/classifierfiltersfilter.mdx:
+ id: 4c60b258249e
+ last_write_checksum: sha1:98efc2e7262b521d268dd591b08cb90a3406fabc
+ pristine_git_object: f09e983a0daa403ee6d2cfca1604906f44a42ee2
+ docs/operations/classifierfiltersvalue.mdx:
+ id: 0701a4bb73c4
+ last_write_checksum: sha1:077df057506e544243ecc2e6ab055cadee049035
+ pristine_git_object: 47e7dc4e537b1c7392c04f36a7c6c8f45847ee29
docs/operations/content.mdx:
id: 6f64feb2d798
last_write_checksum: sha1:329d9719c9e25478666963df7b79710aa626d988
@@ -6286,8 +6302,8 @@ trackedFiles:
pristine_git_object: 5b3c7c98d8cee9aa77138996c3d9af3e2bd3127a
docs/operations/queryanalyticsrequestbody.mdx:
id: 1b8d33b6ac1b
- last_write_checksum: sha1:bd5e4998875dd2b73f5b04749ae013f108119a50
- pristine_git_object: 79876b7e840eb330cecb69b748c1dc80bbb7d14e
+ last_write_checksum: sha1:b100dcb3db6adf543fddf53977874d3d793c99b4
+ pristine_git_object: ceec61fa2f3ad3a903475827003f6b4bbfd771c8
docs/operations/queryanalyticsresponse.mdx:
id: 26c4b637ce33
last_write_checksum: sha1:3f778b3125815a89ceae9aaa735ffc846fef3de8
@@ -6452,6 +6468,10 @@ trackedFiles:
id: ebf32fddf22e
last_write_checksum: sha1:18f440dbfdcb2498771fe53a98b054d4d76f283c
pristine_git_object: f72dd54a6f1db3e758a924691b07ec17f38bc01e
+ docs/operations/valueclassifierfilters.mdx:
+ id: 258cd046e559
+ last_write_checksum: sha1:013f0a03f199fa6d2b2a256acd8af403fdd51c5a
+ pristine_git_object: 9280541b880980bbf528c00ea7c3eb3cc7b4f54c
docs/operations/valuetype.mdx:
id: 29a8210305d2
last_write_checksum: sha1:5ea5c9a100089970356c552e3d9792c6657d0143
@@ -6478,8 +6498,8 @@ trackedFiles:
pristine_git_object: 072d78b5b5aedcdc34724557e76cc0fa03994fba
docs/sdks/betaanalytics/README.mdx:
id: 239279ebf01b
- last_write_checksum: sha1:721b90a76008fa9876ce046a84a7b54bae0dcef8
- pristine_git_object: 716e4631b3b48e11081ed70ca5acc5826b8a6383
+ last_write_checksum: sha1:5a76d28d77f68efe34ebbcb72850e6a87c74d3b1
+ pristine_git_object: 6e4b06ff97f02da5d31d78f478094db32dfdaa6f
docs/sdks/byok/README.mdx:
id: 17792f3b180d
last_write_checksum: sha1:18692d1b1454837b1592113fe1aaba1b1d37a805
@@ -6578,8 +6598,8 @@ trackedFiles:
pristine_git_object: 3e38f1a929f7d6b1d6de74604aa87e3d8f010544
pyproject.toml:
id: 5d07e7d72637
- last_write_checksum: sha1:cbe4db46712b81214486e0f26d72f9384a264b7e
- pristine_git_object: 9c5d4bfdf21ef61dcb7441889ce4f49cbdba7881
+ last_write_checksum: sha1:8914993a8cce928e2718682d649405beb44a32de
+ pristine_git_object: 91166b893131a18020578ab19889176d7a128370
scripts/prepare_readme.py:
id: e0c5957a6035
last_write_checksum: sha1:77f44b60b98bc126557ec27391f91dfba764bb54
@@ -6606,8 +6626,8 @@ trackedFiles:
pristine_git_object: 86713cfea633e09d33b3d4e65281071fe20e6137
src/openrouter/_version.py:
id: d8d15ad6c586
- last_write_checksum: sha1:fac5e109f7e32666cc375872e0a411749b13533e
- pristine_git_object: 085782e387bd5ce779b4220e2c549eb621a203f3
+ last_write_checksum: sha1:2c94535d48a1494c22eff12e1255c7528b1aa324
+ pristine_git_object: f5a0e56d914e266d29449c5d3e1a7ec635f26424
src/openrouter/analytics.py:
id: cb406b5aaabb
last_write_checksum: sha1:9e709b71dd0611056dc0cec6150b578defe32841
@@ -6630,8 +6650,8 @@ trackedFiles:
pristine_git_object: 9c02cc64163adf027507af763e7b612d3b704adb
src/openrouter/beta_analytics.py:
id: 81988b170188
- last_write_checksum: sha1:91cc3d033be8ad49f3d2a67e9dd1ead470c4016f
- pristine_git_object: bcf5829eba6df16f8984b756a46c8836b799dc98
+ last_write_checksum: sha1:517ca1b0d4b94343e7728f156230e653f43c4641
+ pristine_git_object: 1b01f0c081ffc8a42fa56d335f95ec3121e4b5e6
src/openrouter/byok.py:
id: bec352462ae1
last_write_checksum: sha1:14ffff34cdb97e81dd5ef9d7ba0f105b09b7ba48
@@ -8982,8 +9002,8 @@ trackedFiles:
pristine_git_object: a1dea9b45650cc42a6f60447c032fa46b102839a
src/openrouter/operations/__init__.py:
id: 9afcea1e7161
- last_write_checksum: sha1:23cba14efcf42e3a94779c6c259362a6f8a97deb
- pristine_git_object: 3ee6fd4deecd7fcc382a5256db8e43c6f7e719ca
+ last_write_checksum: sha1:d5a5875a32fab4fc32e68a7c4036483701797944
+ pristine_git_object: 134f9b320535b89c7904427ca69322f9507e7ac2
src/openrouter/operations/bulkaddworkspacemembers.py:
id: e0ed56117619
last_write_checksum: sha1:5c44eb0d40fdece3ac084615f6c6082be4cf1d5a
@@ -9298,8 +9318,8 @@ trackedFiles:
pristine_git_object: a242ff323f23dfadad254b76440114e66db4e744
src/openrouter/operations/queryanalytics.py:
id: d76c63ff66f6
- last_write_checksum: sha1:7866c71f371c0dbf9e1cda9be336bbf1d0e30ac5
- pristine_git_object: 705a3eaf0ce3e1b7cc9af6f96dbbed4fe0f67f50
+ last_write_checksum: sha1:b184adfb9d438f443c1fd6c4e749aff3188e9496
+ pristine_git_object: 23f2f9398884b3ab38b7e3ade20cafee40dc97f3
src/openrouter/operations/sendchatcompletionrequest.py:
id: d9fee71bb577
last_write_checksum: sha1:0cba4011b8e305270ac30f88cb7ab59b6aefe619
@@ -10961,4 +10981,6 @@ examples:
"500":
application/json: {"error": {"code": 500, "message": "Internal Server Error"}}
examplesVersion: 1.0.2
-releaseNotes: "## Python SDK Changes:\n* `open_router.beta.responses.send()`: \n * `request.input.union(Array<>)[]` **Changed**\n* `open_router.presets.create_presets_responses()`: \n * `request.input.union(Array<>)[]` **Changed**\n"
+releaseNotes: |
+ ## Python SDK Changes:
+ * `open_router.beta.analytics.query_analytics()`: `request` **Changed**
diff --git a/.speakeasy/gen.yaml b/.speakeasy/gen.yaml
index fccd8e6f..ba5806d5 100644
--- a/.speakeasy/gen.yaml
+++ b/.speakeasy/gen.yaml
@@ -36,7 +36,7 @@ generation:
documentation: mintlify
preApplyUnionDiscriminators: true
python:
- version: 0.11.19
+ version: 0.11.20
additionalDependencies:
dev: {}
main: {}
diff --git a/.speakeasy/out.openapi.yaml b/.speakeasy/out.openapi.yaml
index cd49a8b9..5cf1144f 100644
--- a/.speakeasy/out.openapi.yaml
+++ b/.speakeasy/out.openapi.yaml
@@ -23893,6 +23893,78 @@ paths:
start: '2025-01-01T00:00:00Z'
schema:
properties:
+ classifier_dimensions:
+ description: >-
+ Group results by custom classifier tags, breaking down metrics by the specified dimension values. Requires an active classifier on the workspace.
+ properties:
+ classifier_id:
+ description: UUID of the classifier whose tags to group by.
+ example: 550e8400-e29b-41d4-a716-446655440000
+ format: uuid
+ type: string
+ dimension_names:
+ items:
+ description: >-
+ Classifier dimension name (snake_case identifier). When exactly one name is provided, the response uses it as the column key; with multiple names or none, the response uses `clf_dimension_name`/`clf_dimension_value` columns.
+ example: department
+ type: string
+ maxItems: 10
+ type: array
+ include_nulls:
+ description: >-
+ When true, also include generations that have no tag from this classifier. Defaults to false, which returns only classified generations.
+ type: boolean
+ required:
+ - classifier_id
+ type: object
+ classifier_filters:
+ description: >-
+ Filter results to generations with specific classifier tag values. Can be combined with classifier_dimensions (must use the same classifier_id) or used independently with standard dimensions.
+ properties:
+ classifier_id:
+ description: >-
+ UUID of the classifier whose tags to filter by. Must match classifier_dimensions.classifier_id when both are specified.
+ example: 550e8400-e29b-41d4-a716-446655440000
+ format: uuid
+ type: string
+ filters:
+ items:
+ properties:
+ field:
+ description: >-
+ Classifier dimension name to filter on (snake_case identifier, e.g. "department", "work_type").
+ example: department
+ type: string
+ operator:
+ description: >-
+ Filter operator. Only equality/set operators are supported (eq, neq, in, not_in) — ordered comparisons are not available because classification values are strings.
+ example: eq
+ type: string
+ value:
+ anyOf:
+ - type: string
+ - format: double
+ type: number
+ - items:
+ anyOf:
+ - type: string
+ - format: double
+ type: number
+ type: array
+ description: Filter value. Use a scalar (string or number) for eq/neq, or an array for in/not_in.
+ example: Engineering
+ required:
+ - field
+ - operator
+ - value
+ type: object
+ maxItems: 10
+ minItems: 1
+ type: array
+ required:
+ - classifier_id
+ - filters
+ type: object
dimensions:
items:
description: Dimension to group by (up to 2). Use the /meta endpoint for available dimensions.
diff --git a/.speakeasy/workflow.lock b/.speakeasy/workflow.lock
index c9ecd113..c41786db 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:046e876891ba57af72f3f26e8394a517ea258cecf8c2d8f885357e7796516f2d
- sourceBlobDigest: sha256:a38421ec1aa0fb81cf260b96096fb44a9f31543b4b49d700280b2b58460671d1
+ sourceRevisionDigest: sha256:0244558823b6088d1e3032984eebb7034080c88012d9246accc6d9e62ff608e2
+ sourceBlobDigest: sha256:639b41e906b5ebc304974d4516f56048e8243c71765c59435484287dad1a05ac
tags:
- latest
- 1.0.0
@@ -11,10 +11,10 @@ targets:
open-router:
source: OpenRouter API
sourceNamespace: open-router-chat-completions-api
- sourceRevisionDigest: sha256:046e876891ba57af72f3f26e8394a517ea258cecf8c2d8f885357e7796516f2d
- sourceBlobDigest: sha256:a38421ec1aa0fb81cf260b96096fb44a9f31543b4b49d700280b2b58460671d1
+ sourceRevisionDigest: sha256:0244558823b6088d1e3032984eebb7034080c88012d9246accc6d9e62ff608e2
+ sourceBlobDigest: sha256:639b41e906b5ebc304974d4516f56048e8243c71765c59435484287dad1a05ac
codeSamplesNamespace: open-router-python-code-samples
- codeSamplesRevisionDigest: sha256:0eccbc2f8f6e176d5a67e24ec42aee8a70ef63fdf3da3c2a2fbb8b78587bfd8b
+ codeSamplesRevisionDigest: sha256:a012a1304c56f93a4aeaea74f847db642667113fb8489a88981091d34fc6e4ab
workflow:
workflowVersion: 1.0.0
speakeasyVersion: 1.787.0
diff --git a/RELEASES.md b/RELEASES.md
index 127b4ff6..f2ca288f 100644
--- a/RELEASES.md
+++ b/RELEASES.md
@@ -298,4 +298,14 @@ Based on:
### Generated
- [python v0.11.19] .
### Releases
-- [PyPI v0.11.19] https://pypi.org/project/openrouter/0.11.19 - .
\ No newline at end of file
+- [PyPI v0.11.19] https://pypi.org/project/openrouter/0.11.19 - .
+
+## 2026-07-10 20:14:59
+### Changes
+Based on:
+- OpenAPI Doc
+- Speakeasy CLI 1.787.0 (2.914.0) https://github.com/speakeasy-api/speakeasy
+### Generated
+- [python v0.11.20] .
+### Releases
+- [PyPI v0.11.20] https://pypi.org/project/openrouter/0.11.20 - .
\ No newline at end of file
diff --git a/docs/operations/classifierdimensions.mdx b/docs/operations/classifierdimensions.mdx
new file mode 100644
index 00000000..f7cf34fa
--- /dev/null
+++ b/docs/operations/classifierdimensions.mdx
@@ -0,0 +1,14 @@
+---
+title: "ClassifierDimensions"
+---
+
+Group results by custom classifier tags, breaking down metrics by the specified dimension values. Requires an active classifier on the workspace.
+
+
+## Fields
+
+| Field | Type | Required | Description | Example |
+| ---------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------- |
+| `classifier_id` | *str* | :heavy_check_mark: | UUID of the classifier whose tags to group by. | 550e8400-e29b-41d4-a716-446655440000 |
+| `dimension_names` | List[*str*] | :heavy_minus_sign: | N/A | |
+| `include_nulls` | *Optional[bool]* | :heavy_minus_sign: | When true, also include generations that have no tag from this classifier. Defaults to false, which returns only classified generations. | |
\ No newline at end of file
diff --git a/docs/operations/classifierfilters.mdx b/docs/operations/classifierfilters.mdx
new file mode 100644
index 00000000..db4dbe94
--- /dev/null
+++ b/docs/operations/classifierfilters.mdx
@@ -0,0 +1,13 @@
+---
+title: "ClassifierFilters"
+---
+
+Filter results to generations with specific classifier tag values. Can be combined with classifier_dimensions (must use the same classifier_id) or used independently with standard dimensions.
+
+
+## Fields
+
+| Field | Type | Required | Description | Example |
+| ----------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------- |
+| `classifier_id` | *str* | :heavy_check_mark: | UUID of the classifier whose tags to filter by. Must match classifier_dimensions.classifier_id when both are specified. | 550e8400-e29b-41d4-a716-446655440000 |
+| `filters` | List[[operations.ClassifierFiltersFilter](../operations/classifierfiltersfilter.mdx)] | :heavy_check_mark: | N/A | |
\ No newline at end of file
diff --git a/docs/operations/classifierfiltersfilter.mdx b/docs/operations/classifierfiltersfilter.mdx
new file mode 100644
index 00000000..f09e983a
--- /dev/null
+++ b/docs/operations/classifierfiltersfilter.mdx
@@ -0,0 +1,11 @@
+---
+title: "ClassifierFiltersFilter"
+---
+
+## Fields
+
+| Field | Type | Required | Description | Example |
+| ------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| `field` | *str* | :heavy_check_mark: | Classifier dimension name to filter on (snake_case identifier, e.g. "department", "work_type"). | department |
+| `operator` | *str* | :heavy_check_mark: | Filter operator. Only equality/set operators are supported (eq, neq, in, not_in) — ordered comparisons are not available because classification values are strings. | eq |
+| `value` | [operations.ClassifierFiltersValue](../operations/classifierfiltersvalue.mdx) | :heavy_check_mark: | Filter value. Use a scalar (string or number) for eq/neq, or an array for in/not_in. | Engineering |
\ No newline at end of file
diff --git a/docs/operations/classifierfiltersvalue.mdx b/docs/operations/classifierfiltersvalue.mdx
new file mode 100644
index 00000000..47e7dc4e
--- /dev/null
+++ b/docs/operations/classifierfiltersvalue.mdx
@@ -0,0 +1,27 @@
+---
+title: "ClassifierFiltersValue"
+---
+
+Filter value. Use a scalar (string or number) for eq/neq, or an array for in/not_in.
+
+
+## Supported Types
+
+### `str`
+
+```python
+value: str = /* values here */
+```
+
+### `float`
+
+```python
+value: float = /* values here */
+```
+
+### `List[operations.ValueClassifierFilters]`
+
+```python
+value: List[operations.ValueClassifierFilters] = /* values here */
+```
+
diff --git a/docs/operations/queryanalyticsrequestbody.mdx b/docs/operations/queryanalyticsrequestbody.mdx
index 79876b7e..ceec61fa 100644
--- a/docs/operations/queryanalyticsrequestbody.mdx
+++ b/docs/operations/queryanalyticsrequestbody.mdx
@@ -6,6 +6,8 @@ title: "QueryAnalyticsRequestBody"
| Field | Type | Required | Description | Example |
| --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| `classifier_dimensions` | [Optional[operations.ClassifierDimensions]](../operations/classifierdimensions.mdx) | :heavy_minus_sign: | Group results by custom classifier tags, breaking down metrics by the specified dimension values. Requires an active classifier on the workspace. | |
+| `classifier_filters` | [Optional[operations.ClassifierFilters]](../operations/classifierfilters.mdx) | :heavy_minus_sign: | Filter results to generations with specific classifier tag values. Can be combined with classifier_dimensions (must use the same classifier_id) or used independently with standard dimensions. | |
| `dimensions` | List[*str*] | :heavy_minus_sign: | N/A | |
| `filters` | List[[operations.Filter](../operations/filter_.mdx)] | :heavy_minus_sign: | N/A | |
| `granularity` | *Optional[str]* | :heavy_minus_sign: | Time granularity | day |
diff --git a/docs/operations/valueclassifierfilters.mdx b/docs/operations/valueclassifierfilters.mdx
new file mode 100644
index 00000000..9280541b
--- /dev/null
+++ b/docs/operations/valueclassifierfilters.mdx
@@ -0,0 +1,18 @@
+---
+title: "ValueClassifierFilters"
+---
+
+## Supported Types
+
+### `str`
+
+```python
+value: str = /* values here */
+```
+
+### `float`
+
+```python
+value: float = /* values here */
+```
+
diff --git a/docs/sdks/betaanalytics/README.mdx b/docs/sdks/betaanalytics/README.mdx
index 716e4631..6e4b06ff 100644
--- a/docs/sdks/betaanalytics/README.mdx
+++ b/docs/sdks/betaanalytics/README.mdx
@@ -100,6 +100,8 @@ 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.
| |
+| `classifier_dimensions` | [Optional[operations.ClassifierDimensions]](../../operations/classifierdimensions.mdx) | :heavy_minus_sign: | Group results by custom classifier tags, breaking down metrics by the specified dimension values. Requires an active classifier on the workspace. | |
+| `classifier_filters` | [Optional[operations.ClassifierFilters]](../../operations/classifierfilters.mdx) | :heavy_minus_sign: | Filter results to generations with specific classifier tag values. Can be combined with classifier_dimensions (must use the same classifier_id) or used independently with standard dimensions. | |
| `dimensions` | List[*str*] | :heavy_minus_sign: | N/A | |
| `filters` | List[[operations.Filter](../../operations/filter_.mdx)] | :heavy_minus_sign: | N/A | |
| `granularity` | *Optional[str]* | :heavy_minus_sign: | Time granularity | day |
diff --git a/pyproject.toml b/pyproject.toml
index 9c5d4bfd..91166b89 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,6 +1,6 @@
[project]
name = "openrouter"
-version = "0.11.19"
+version = "0.11.20"
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 085782e3..f5a0e56d 100644
--- a/src/openrouter/_version.py
+++ b/src/openrouter/_version.py
@@ -3,10 +3,10 @@
import importlib.metadata
__title__: str = "openrouter"
-__version__: str = "0.11.19"
+__version__: str = "0.11.20"
__openapi_doc_version__: str = "1.0.0"
__gen_version__: str = "2.914.0"
-__user_agent__: str = "speakeasy-sdk/python 0.11.19 2.914.0 1.0.0 openrouter"
+__user_agent__: str = "speakeasy-sdk/python 0.11.20 2.914.0 1.0.0 openrouter"
try:
if __package__ is not None:
diff --git a/src/openrouter/beta_analytics.py b/src/openrouter/beta_analytics.py
index bcf5829e..1b01f0c0 100644
--- a/src/openrouter/beta_analytics.py
+++ b/src/openrouter/beta_analytics.py
@@ -273,6 +273,15 @@ def query_analytics(
http_referer: Optional[str] = None,
x_open_router_title: Optional[str] = None,
x_open_router_categories: Optional[str] = None,
+ classifier_dimensions: Optional[
+ Union[
+ operations.ClassifierDimensions,
+ operations.ClassifierDimensionsTypedDict,
+ ]
+ ] = None,
+ classifier_filters: Optional[
+ Union[operations.ClassifierFilters, operations.ClassifierFiltersTypedDict]
+ ] = None,
dimensions: Optional[Iterable[str]] = None,
filters: Optional[
Union[Iterable[operations.Filter], Iterable[operations.FilterTypedDict]]
@@ -303,6 +312,8 @@ def query_analytics(
:param x_open_router_categories: Comma-separated list of app categories (e.g. \"cli-agent,cloud-agent\"). Used for marketplace rankings.
+ :param classifier_dimensions: Group results by custom classifier tags, breaking down metrics by the specified dimension values. Requires an active classifier on the workspace.
+ :param classifier_filters: Filter results to generations with specific classifier tag values. Can be combined with classifier_dimensions (must use the same classifier_id) or used independently with standard dimensions.
:param dimensions:
:param filters:
:param granularity: Time granularity
@@ -330,6 +341,12 @@ def query_analytics(
x_open_router_title=x_open_router_title,
x_open_router_categories=x_open_router_categories,
request_body=operations.QueryAnalyticsRequestBody(
+ classifier_dimensions=utils.get_pydantic_model(
+ classifier_dimensions, Optional[operations.ClassifierDimensions]
+ ),
+ classifier_filters=utils.get_pydantic_model(
+ classifier_filters, Optional[operations.ClassifierFilters]
+ ),
dimensions=utils.unmarshal(dimensions, Optional[List[str]]),
filters=utils.get_pydantic_model(
filters, Optional[List[operations.Filter]]
@@ -453,6 +470,15 @@ async def query_analytics_async(
http_referer: Optional[str] = None,
x_open_router_title: Optional[str] = None,
x_open_router_categories: Optional[str] = None,
+ classifier_dimensions: Optional[
+ Union[
+ operations.ClassifierDimensions,
+ operations.ClassifierDimensionsTypedDict,
+ ]
+ ] = None,
+ classifier_filters: Optional[
+ Union[operations.ClassifierFilters, operations.ClassifierFiltersTypedDict]
+ ] = None,
dimensions: Optional[Iterable[str]] = None,
filters: Optional[
Union[Iterable[operations.Filter], Iterable[operations.FilterTypedDict]]
@@ -483,6 +509,8 @@ async def query_analytics_async(
:param x_open_router_categories: Comma-separated list of app categories (e.g. \"cli-agent,cloud-agent\"). Used for marketplace rankings.
+ :param classifier_dimensions: Group results by custom classifier tags, breaking down metrics by the specified dimension values. Requires an active classifier on the workspace.
+ :param classifier_filters: Filter results to generations with specific classifier tag values. Can be combined with classifier_dimensions (must use the same classifier_id) or used independently with standard dimensions.
:param dimensions:
:param filters:
:param granularity: Time granularity
@@ -510,6 +538,12 @@ async def query_analytics_async(
x_open_router_title=x_open_router_title,
x_open_router_categories=x_open_router_categories,
request_body=operations.QueryAnalyticsRequestBody(
+ classifier_dimensions=utils.get_pydantic_model(
+ classifier_dimensions, Optional[operations.ClassifierDimensions]
+ ),
+ classifier_filters=utils.get_pydantic_model(
+ classifier_filters, Optional[operations.ClassifierFilters]
+ ),
dimensions=utils.unmarshal(dimensions, Optional[List[str]]),
filters=utils.get_pydantic_model(
filters, Optional[List[operations.Filter]]
diff --git a/src/openrouter/operations/__init__.py b/src/openrouter/operations/__init__.py
index 3ee6fd4d..134f9b32 100644
--- a/src/openrouter/operations/__init__.py
+++ b/src/openrouter/operations/__init__.py
@@ -652,6 +652,14 @@
ListWorkspacesResponseTypedDict,
)
from .queryanalytics import (
+ ClassifierDimensions,
+ ClassifierDimensionsTypedDict,
+ ClassifierFilters,
+ ClassifierFiltersFilter,
+ ClassifierFiltersFilterTypedDict,
+ ClassifierFiltersTypedDict,
+ ClassifierFiltersValue,
+ ClassifierFiltersValueTypedDict,
Direction,
Filter,
FilterTypedDict,
@@ -677,6 +685,8 @@
Value1TypedDict,
Value2,
Value2TypedDict,
+ ValueClassifierFilters,
+ ValueClassifierFiltersTypedDict,
)
from .sendchatcompletionrequest import (
SendChatCompletionRequestGlobals,
@@ -772,6 +782,14 @@
"BulkUnassignMembersFromGuardrailGlobalsTypedDict",
"BulkUnassignMembersFromGuardrailRequest",
"BulkUnassignMembersFromGuardrailRequestTypedDict",
+ "ClassifierDimensions",
+ "ClassifierDimensionsTypedDict",
+ "ClassifierFilters",
+ "ClassifierFiltersFilter",
+ "ClassifierFiltersFilterTypedDict",
+ "ClassifierFiltersTypedDict",
+ "ClassifierFiltersValue",
+ "ClassifierFiltersValueTypedDict",
"Content",
"ContentImageURL",
"ContentImageURLTypedDict",
@@ -1308,6 +1326,8 @@
"Value1TypedDict",
"Value2",
"Value2TypedDict",
+ "ValueClassifierFilters",
+ "ValueClassifierFiltersTypedDict",
"ValueType",
"Window",
"Zdr",
@@ -1804,6 +1824,14 @@
"ListWorkspacesRequestTypedDict": ".listworkspaces",
"ListWorkspacesResponse": ".listworkspaces",
"ListWorkspacesResponseTypedDict": ".listworkspaces",
+ "ClassifierDimensions": ".queryanalytics",
+ "ClassifierDimensionsTypedDict": ".queryanalytics",
+ "ClassifierFilters": ".queryanalytics",
+ "ClassifierFiltersFilter": ".queryanalytics",
+ "ClassifierFiltersFilterTypedDict": ".queryanalytics",
+ "ClassifierFiltersTypedDict": ".queryanalytics",
+ "ClassifierFiltersValue": ".queryanalytics",
+ "ClassifierFiltersValueTypedDict": ".queryanalytics",
"Direction": ".queryanalytics",
"Filter": ".queryanalytics",
"FilterTypedDict": ".queryanalytics",
@@ -1829,6 +1857,8 @@
"Value1TypedDict": ".queryanalytics",
"Value2": ".queryanalytics",
"Value2TypedDict": ".queryanalytics",
+ "ValueClassifierFilters": ".queryanalytics",
+ "ValueClassifierFiltersTypedDict": ".queryanalytics",
"SendChatCompletionRequestGlobals": ".sendchatcompletionrequest",
"SendChatCompletionRequestGlobalsTypedDict": ".sendchatcompletionrequest",
"SendChatCompletionRequestRequest": ".sendchatcompletionrequest",
diff --git a/src/openrouter/operations/queryanalytics.py b/src/openrouter/operations/queryanalytics.py
index 705a3eaf..23f2f939 100644
--- a/src/openrouter/operations/queryanalytics.py
+++ b/src/openrouter/operations/queryanalytics.py
@@ -74,6 +74,102 @@ def serialize_model(self, handler):
return m
+class ClassifierDimensionsTypedDict(TypedDict):
+ r"""Group results by custom classifier tags, breaking down metrics by the specified dimension values. Requires an active classifier on the workspace."""
+
+ classifier_id: str
+ r"""UUID of the classifier whose tags to group by."""
+ dimension_names: NotRequired[List[str]]
+ include_nulls: NotRequired[bool]
+ r"""When true, also include generations that have no tag from this classifier. Defaults to false, which returns only classified generations."""
+
+
+class ClassifierDimensions(BaseModel):
+ r"""Group results by custom classifier tags, breaking down metrics by the specified dimension values. Requires an active classifier on the workspace."""
+
+ classifier_id: str
+ r"""UUID of the classifier whose tags to group by."""
+
+ dimension_names: Optional[List[str]] = None
+
+ include_nulls: Optional[bool] = None
+ r"""When true, also include generations that have no tag from this classifier. Defaults to false, which returns only classified generations."""
+
+ @model_serializer(mode="wrap")
+ def serialize_model(self, handler):
+ optional_fields = set(["dimension_names", "include_nulls"])
+ serialized = handler(self)
+ m = {}
+
+ for n, f in type(self).model_fields.items():
+ k = f.alias or n
+ val = serialized.get(k, serialized.get(n))
+
+ if val != UNSET_SENTINEL:
+ if val is not None or k not in optional_fields:
+ m[k] = val
+
+ return m
+
+
+ValueClassifierFiltersTypedDict = TypeAliasType(
+ "ValueClassifierFiltersTypedDict", Union[str, float]
+)
+
+
+ValueClassifierFilters = TypeAliasType("ValueClassifierFilters", Union[str, float])
+
+
+ClassifierFiltersValueTypedDict = TypeAliasType(
+ "ClassifierFiltersValueTypedDict",
+ Union[str, float, List[ValueClassifierFiltersTypedDict]],
+)
+r"""Filter value. Use a scalar (string or number) for eq/neq, or an array for in/not_in."""
+
+
+ClassifierFiltersValue = TypeAliasType(
+ "ClassifierFiltersValue", Union[str, float, List[ValueClassifierFilters]]
+)
+r"""Filter value. Use a scalar (string or number) for eq/neq, or an array for in/not_in."""
+
+
+class ClassifierFiltersFilterTypedDict(TypedDict):
+ field: str
+ r"""Classifier dimension name to filter on (snake_case identifier, e.g. \"department\", \"work_type\")."""
+ operator: str
+ r"""Filter operator. Only equality/set operators are supported (eq, neq, in, not_in) — ordered comparisons are not available because classification values are strings."""
+ value: ClassifierFiltersValueTypedDict
+ r"""Filter value. Use a scalar (string or number) for eq/neq, or an array for in/not_in."""
+
+
+class ClassifierFiltersFilter(BaseModel):
+ field: str
+ r"""Classifier dimension name to filter on (snake_case identifier, e.g. \"department\", \"work_type\")."""
+
+ operator: str
+ r"""Filter operator. Only equality/set operators are supported (eq, neq, in, not_in) — ordered comparisons are not available because classification values are strings."""
+
+ value: ClassifierFiltersValue
+ r"""Filter value. Use a scalar (string or number) for eq/neq, or an array for in/not_in."""
+
+
+class ClassifierFiltersTypedDict(TypedDict):
+ r"""Filter results to generations with specific classifier tag values. Can be combined with classifier_dimensions (must use the same classifier_id) or used independently with standard dimensions."""
+
+ classifier_id: str
+ r"""UUID of the classifier whose tags to filter by. Must match classifier_dimensions.classifier_id when both are specified."""
+ filters: List[ClassifierFiltersFilterTypedDict]
+
+
+class ClassifierFilters(BaseModel):
+ r"""Filter results to generations with specific classifier tag values. Can be combined with classifier_dimensions (must use the same classifier_id) or used independently with standard dimensions."""
+
+ classifier_id: str
+ r"""UUID of the classifier whose tags to filter by. Must match classifier_dimensions.classifier_id when both are specified."""
+
+ filters: List[ClassifierFiltersFilter]
+
+
Value2TypedDict = TypeAliasType("Value2TypedDict", Union[str, float])
@@ -145,6 +241,10 @@ class TimeRange(BaseModel):
class QueryAnalyticsRequestBodyTypedDict(TypedDict):
metrics: List[str]
+ classifier_dimensions: NotRequired[ClassifierDimensionsTypedDict]
+ r"""Group results by custom classifier tags, breaking down metrics by the specified dimension values. Requires an active classifier on the workspace."""
+ classifier_filters: NotRequired[ClassifierFiltersTypedDict]
+ r"""Filter results to generations with specific classifier tag values. Can be combined with classifier_dimensions (must use the same classifier_id) or used independently with standard dimensions."""
dimensions: NotRequired[List[str]]
filters: NotRequired[List[FilterTypedDict]]
granularity: NotRequired[str]
@@ -160,6 +260,12 @@ class QueryAnalyticsRequestBodyTypedDict(TypedDict):
class QueryAnalyticsRequestBody(BaseModel):
metrics: List[str]
+ classifier_dimensions: Optional[ClassifierDimensions] = None
+ r"""Group results by custom classifier tags, breaking down metrics by the specified dimension values. Requires an active classifier on the workspace."""
+
+ classifier_filters: Optional[ClassifierFilters] = None
+ r"""Filter results to generations with specific classifier tag values. Can be combined with classifier_dimensions (must use the same classifier_id) or used independently with standard dimensions."""
+
dimensions: Optional[List[str]] = None
filters: Optional[List[Filter]] = None
@@ -181,6 +287,8 @@ class QueryAnalyticsRequestBody(BaseModel):
def serialize_model(self, handler):
optional_fields = set(
[
+ "classifier_dimensions",
+ "classifier_filters",
"dimensions",
"filters",
"granularity",
diff --git a/uv.lock b/uv.lock
index 405c5a67..783d413e 100644
--- a/uv.lock
+++ b/uv.lock
@@ -213,7 +213,7 @@ wheels = [
[[package]]
name = "openrouter"
-version = "0.11.19"
+version = "0.11.20"
source = { editable = "." }
dependencies = [
{ name = "httpcore" },