diff --git a/.speakeasy/gen.lock b/.speakeasy/gen.lock
index d1c9c66c..acb7a47d 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: 31a453ec8245c65098405a9010d2ff54
+ docChecksum: 22dd2a8c52c82b2e6d45813b3a136d8e
docVersion: 1.0.0
speakeasyVersion: 1.787.0
generationVersion: 2.914.0
- releaseVersion: 0.11.1
- configChecksum: 85e803126e799123b660fa86fbd0594f
+ releaseVersion: 0.11.2
+ configChecksum: d99c6e3ad8d65139a1705b2482f5b0f6
repoURL: https://github.com/OpenRouterTeam/python-sdk.git
installationURL: https://github.com/OpenRouterTeam/python-sdk.git
published: true
persistentEdits:
- generation_id: 2fd172e4-2ed7-47d2-959b-76faccc0db40
- pristine_commit_hash: 770c36dfd9d9611977f1d4f1b874b911010e7f2b
- pristine_tree_hash: 752195cbe1fa7f997c727815c9f9ea4da62ac759
+ generation_id: 17428005-f3ed-41ee-832f-a08e2ee4b2c9
+ pristine_commit_hash: c52584d3b29fe1ab0cd11c36fc0519e7988910d6
+ pristine_tree_hash: 35802e82c88cd41747250883f8acad806745fe0e
features:
python:
acceptHeaders: 3.0.0
@@ -2508,6 +2508,10 @@ trackedFiles:
id: be60b3aa222d
last_write_checksum: sha1:5e5e015f7957686bce403d8f176e4f7f9eba9b47
pristine_git_object: 27bb746a556432a1d423634c0d2f55e384de7859
+ docs/components/listworkspacemembersresponse.mdx:
+ id: 1b8dff85b565
+ last_write_checksum: sha1:3577f9efc0094f785f0413e6eacc729267e204fc
+ pristine_git_object: 90edcaf6b5451904212adc4202422f5808d2194f
docs/components/listworkspacesresponse.mdx:
id: cddf2b6dd8bf
last_write_checksum: sha1:e5f4cc01853d9fa8feb77140d976d64ebe5b1d45
@@ -6016,6 +6020,18 @@ trackedFiles:
id: fbaf80b58271
last_write_checksum: sha1:b9166455ca5f9dfbb1d692547ef54158685ece80
pristine_git_object: f6101881f6a54e2b999a60c6c607b2e7bcf103dc
+ docs/operations/listworkspacemembersglobals.mdx:
+ id: 0b0ec6b14941
+ last_write_checksum: sha1:ed137f5daaa24ffda73b29d91830b62782c75f46
+ pristine_git_object: c8f845c5520b7d515548724e90034eec4e2989f5
+ docs/operations/listworkspacemembersrequest.mdx:
+ id: 094a5435a3a6
+ last_write_checksum: sha1:655363c94d19fee214f5ca0283f5f8e4c2c10ddd
+ pristine_git_object: fe553b32e8a2e665d7f60820017710b9d1d1e759
+ docs/operations/listworkspacemembersresponse.mdx:
+ id: 1ea6e450f1db
+ last_write_checksum: sha1:69a0763e6d3816274d51b825514ec38b637a0312
+ pristine_git_object: 94558019b67d816d9deb6acc7508d3f9ab4419aa
docs/operations/listworkspacesglobals.mdx:
id: 796f26dced99
last_write_checksum: sha1:900a20b914fa6bf043585f1e0de3692510bab04e
@@ -6346,16 +6362,16 @@ trackedFiles:
pristine_git_object: 429ca7dad6a66516aec6bb1e674af1e09dc42dd5
docs/sdks/workspaces/README.mdx:
id: 0c75d023ef6b
- last_write_checksum: sha1:b3552fadeab957d102333c3ba7d69f7c6bae267e
- pristine_git_object: cf4cc041104ab0bffd6a0c8276068616e104819c
+ last_write_checksum: sha1:29a4f4699004ed16b9c980463a649576b30fe035
+ pristine_git_object: 37f2346cb81f6c7712df90b676b5084808b609b5
py.typed:
id: 258c3ed47ae4
last_write_checksum: sha1:8efc425ffe830805ffcc0f3055871bdcdc542c60
pristine_git_object: 3e38f1a929f7d6b1d6de74604aa87e3d8f010544
pyproject.toml:
id: 5d07e7d72637
- last_write_checksum: sha1:315748f12aad769a99d497d7f7b72b1bfd6d79ab
- pristine_git_object: 60601548fd081896f4b477f701e887facde0de63
+ last_write_checksum: sha1:e2bc1b3fccb2ccdf85aa79e5886a52f91340150a
+ pristine_git_object: e0deb3eae39559a8ab667ff46b01c4a505abd7db
scripts/prepare_readme.py:
id: e0c5957a6035
last_write_checksum: sha1:77f44b60b98bc126557ec27391f91dfba764bb54
@@ -6382,8 +6398,8 @@ trackedFiles:
pristine_git_object: 86713cfea633e09d33b3d4e65281071fe20e6137
src/openrouter/_version.py:
id: d8d15ad6c586
- last_write_checksum: sha1:c775f28ffba30ec6110b067674d42628dfe28b1e
- pristine_git_object: 30f0645017b376be4851dddedda35fdbcd70fb48
+ last_write_checksum: sha1:0d2f123171a2b90c45806c351b029f722c836270
+ pristine_git_object: 065e7c6105281025b6c465f401c6bf6c03966342
src/openrouter/analytics.py:
id: cb406b5aaabb
last_write_checksum: sha1:9e709b71dd0611056dc0cec6150b578defe32841
@@ -6422,8 +6438,8 @@ trackedFiles:
pristine_git_object: ad3d247954547814054c01989a2dff3d12b3e4e1
src/openrouter/components/__init__.py:
id: 81754e97b3f4
- last_write_checksum: sha1:f1a79345c2156a1e659b55a506babccbdd392463
- pristine_git_object: c0bbbca94f36baba1ca34b27a0827a97cf47ed00
+ last_write_checksum: sha1:3d56cadcea54efec319a1d282eeae4c5b387d1e5
+ pristine_git_object: 19c69fe69c979eccea5ec82ed501dda6fc391d3a
src/openrouter/components/aabenchmarkentry.py:
id: e2e0f0b48c82
last_write_checksum: sha1:fab4d9a24d2cea937bb749d46c5f83941e99d65c
@@ -7524,6 +7540,10 @@ trackedFiles:
id: 64fa8723acb0
last_write_checksum: sha1:2546a0136f06ab451e7df5d1af7d32029e5f4719
pristine_git_object: df7bc125a2e1135e8e83f6032810d879d06934f7
+ src/openrouter/components/listworkspacemembersresponse.py:
+ id: cfe46d91c277
+ last_write_checksum: sha1:f5d86b2ad810be375324b6cd281c4f41f6864419
+ pristine_git_object: 911823770e39cfeb2d632eaa0796a4de58c26147
src/openrouter/components/listworkspacesresponse.py:
id: 0c5f98eddbf5
last_write_checksum: sha1:53b10630a44ccc43fa86a34e9a3f5a64f08488c4
@@ -8694,8 +8714,8 @@ trackedFiles:
pristine_git_object: a1dea9b45650cc42a6f60447c032fa46b102839a
src/openrouter/operations/__init__.py:
id: 9afcea1e7161
- last_write_checksum: sha1:a652e6a05b4685dff3a016965467f2b90b862c05
- pristine_git_object: a79839770301dc301204149ff14f7f8945122b0c
+ last_write_checksum: sha1:58c06e81675a137ec84b13517f78cf1020874f2d
+ pristine_git_object: fc51690a99a6041a78762af05e43da30f15875da
src/openrouter/operations/bulkaddworkspacemembers.py:
id: e0ed56117619
last_write_checksum: sha1:5c44eb0d40fdece3ac084615f6c6082be4cf1d5a
@@ -8996,6 +9016,10 @@ trackedFiles:
id: 1310fb7e01a9
last_write_checksum: sha1:83b3e498943e3c5a239e2c50e9d417b1f5d227fb
pristine_git_object: a65454da5ec6727d99312d56c64324edd8615685
+ src/openrouter/operations/listworkspacemembers.py:
+ id: 9886d508d283
+ last_write_checksum: sha1:c83463410e0899b9f5b686e2155f69340c7acff7
+ pristine_git_object: 9a8706fcb1a1761c4e636dba74866e239e8d51a3
src/openrouter/operations/listworkspaces.py:
id: fe94c6f61835
last_write_checksum: sha1:2458a0c8d4834fa046496a68620b66c5ba55d927
@@ -9170,8 +9194,8 @@ trackedFiles:
pristine_git_object: 4a82cde858211c0f5a01b08980cee0e9e3d0f52c
src/openrouter/workspaces.py:
id: cd6c533b1802
- last_write_checksum: sha1:545a54d7d445ecb42e24c9b137362747e9d90651
- pristine_git_object: d22a8e667cb3f29570234bc057261a9082d69ee5
+ last_write_checksum: sha1:cde38a8140d790751ffd6bb013a4c702c112aa6f
+ pristine_git_object: f3cf390c8f027710aaf32e794fa5229f0447b991
examples:
createResponses:
speakeasy-default-create-responses:
@@ -10599,5 +10623,23 @@ examples:
application/json: {"error": {"code": 404, "message": "Resource not found"}}
"500":
application/json: {"error": {"code": 500, "message": "Internal Server Error"}}
+ listWorkspaceMembers:
+ speakeasy-default-list-workspace-members:
+ parameters:
+ path:
+ id: "production"
+ responses:
+ "200":
+ application/json: {"data": [{"created_at": "2025-08-24T10:30:00Z", "id": "660e8400-e29b-41d4-a716-446655440000", "role": "member", "user_id": "user_abc123", "workspace_id": "550e8400-e29b-41d4-a716-446655440000"}], "total_count": 1}
+ "401":
+ application/json: {"error": {"code": 401, "message": "Missing Authentication header"}}
+ "403":
+ application/json: {"error": {"code": 403, "message": "Only management keys can perform this operation"}}
+ "404":
+ application/json: {"error": {"code": 404, "message": "Resource not found"}}
+ "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.tools[].union(openrouter:files)` **Added**\n* `open_router.chat.send()`: \n * `request.tools[].union(FilesServerTool)` **Added**\n* `open_router.presets.create_presets_chat_completions()`: \n * `request.tools[].union(FilesServerTool)` **Added**\n* `open_router.presets.create_presets_responses()`: \n * `request.tools[].union(openrouter:files)` **Added**\n"
+releaseNotes: |
+ ## Python SDK Changes:
+ * `open_router.workspaces.list_members()`: **Added**
diff --git a/.speakeasy/gen.yaml b/.speakeasy/gen.yaml
index c14d6f5e..fcd35491 100644
--- a/.speakeasy/gen.yaml
+++ b/.speakeasy/gen.yaml
@@ -36,7 +36,7 @@ generation:
documentation: mintlify
preApplyUnionDiscriminators: true
python:
- version: 0.11.1
+ version: 0.11.2
additionalDependencies:
dev: {}
main: {}
diff --git a/.speakeasy/out.openapi.yaml b/.speakeasy/out.openapi.yaml
index 3ff05edf..39c2451f 100644
--- a/.speakeasy/out.openapi.yaml
+++ b/.speakeasy/out.openapi.yaml
@@ -10872,6 +10872,29 @@ components:
required:
- data
type: object
+ ListWorkspaceMembersResponse:
+ example:
+ data:
+ - created_at: '2025-08-24T10:30:00Z'
+ id: 660e8400-e29b-41d4-a716-446655440000
+ role: member
+ user_id: user_abc123
+ workspace_id: 550e8400-e29b-41d4-a716-446655440000
+ total_count: 1
+ properties:
+ data:
+ description: List of workspace members
+ items:
+ $ref: '#/components/schemas/WorkspaceMember'
+ type: array
+ total_count:
+ description: Total number of members in the workspace
+ example: 5
+ type: integer
+ required:
+ - data
+ - total_count
+ type: object
ListWorkspacesResponse:
example:
data:
@@ -33907,6 +33930,115 @@ paths:
- $ref: "#/components/parameters/AppIdentifier"
- $ref: "#/components/parameters/AppDisplayName"
- $ref: "#/components/parameters/AppCategories"
+ /workspaces/{id}/members:
+ get:
+ description: >-
+ List all members of a workspace. Returns paginated results. For the default workspace, returns all organization members (implicit membership). [Management key](/docs/guides/overview/auth/management-api-keys) required.
+ operationId: listWorkspaceMembers
+ parameters:
+ - description: The workspace ID (UUID) or slug
+ in: path
+ name: id
+ required: true
+ schema:
+ description: The workspace ID (UUID) or slug
+ example: production
+ minLength: 1
+ type: string
+ - description: Number of records to skip for pagination
+ in: query
+ name: offset
+ required: false
+ schema:
+ description: Number of records to skip for pagination
+ example: 0
+ minimum: 0
+ nullable: false
+ type: integer
+ - description: Maximum number of records to return (max 100)
+ in: query
+ name: limit
+ required: false
+ schema:
+ description: Maximum number of records to return (max 100)
+ example: 50
+ maximum: 100
+ minimum: 1
+ type: integer
+ responses:
+ '200':
+ content:
+ application/json:
+ example:
+ data:
+ - created_at: '2025-08-24T10:30:00Z'
+ id: 660e8400-e29b-41d4-a716-446655440000
+ role: member
+ user_id: user_abc123
+ workspace_id: 550e8400-e29b-41d4-a716-446655440000
+ total_count: 1
+ schema:
+ $ref: '#/components/schemas/ListWorkspaceMembersResponse'
+ description: List of workspace members
+ '401':
+ content:
+ application/json:
+ example:
+ error:
+ code: 401
+ message: Missing Authentication header
+ schema:
+ $ref: '#/components/schemas/UnauthorizedResponse'
+ description: Unauthorized - Authentication required or invalid credentials
+ '403':
+ content:
+ application/json:
+ example:
+ error:
+ code: 403
+ message: Only management keys can perform this operation
+ schema:
+ $ref: '#/components/schemas/ForbiddenResponse'
+ description: Forbidden - Authentication successful but insufficient permissions
+ '404':
+ content:
+ application/json:
+ example:
+ error:
+ code: 404
+ message: Resource not found
+ schema:
+ $ref: '#/components/schemas/NotFoundResponse'
+ description: Not Found - Resource does not exist
+ '500':
+ content:
+ application/json:
+ example:
+ error:
+ code: 500
+ message: Internal Server Error
+ schema:
+ $ref: '#/components/schemas/InternalServerResponse'
+ description: Internal Server Error - Unexpected server error
+ summary: List workspace members
+ tags:
+ - Workspaces
+ x-speakeasy-name-override: listMembers
+ x-speakeasy-pagination:
+ inputs:
+ - in: parameters
+ name: offset
+ type: offset
+ - in: parameters
+ name: limit
+ type: limit
+ outputs:
+ results: $.data
+ type: offsetLimit
+ parameters:
+ - $ref: "#/components/parameters/AppIdentifier"
+ - $ref: "#/components/parameters/AppDisplayName"
+ - $ref: "#/components/parameters/AppCategories"
/workspaces/{id}/members/add:
post:
description: >-
diff --git a/.speakeasy/workflow.lock b/.speakeasy/workflow.lock
index d7018bfe..9e6f0884 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:f55ad0f499156d20c6b57efb38c3ae9ed94c860e434405e7d52338e61eb6f79c
- sourceBlobDigest: sha256:90e75fce2c45d81d02e9eaeb0a1be6e2d4a214ac796334b5680996b911d4e9c5
+ sourceRevisionDigest: sha256:5f1370b2087005edf5335d559553a8e78a7f68548feeb5007ffd159eb331d4b8
+ sourceBlobDigest: sha256:ccab13156b379a7393d475a3dffeede1ab1e849f77860609a73af1ce7a3839e4
tags:
- latest
- 1.0.0
@@ -11,10 +11,10 @@ targets:
open-router:
source: OpenRouter API
sourceNamespace: open-router-chat-completions-api
- sourceRevisionDigest: sha256:f55ad0f499156d20c6b57efb38c3ae9ed94c860e434405e7d52338e61eb6f79c
- sourceBlobDigest: sha256:90e75fce2c45d81d02e9eaeb0a1be6e2d4a214ac796334b5680996b911d4e9c5
+ sourceRevisionDigest: sha256:5f1370b2087005edf5335d559553a8e78a7f68548feeb5007ffd159eb331d4b8
+ sourceBlobDigest: sha256:ccab13156b379a7393d475a3dffeede1ab1e849f77860609a73af1ce7a3839e4
codeSamplesNamespace: open-router-python-code-samples
- codeSamplesRevisionDigest: sha256:32b3050b10d3e0f8cbe39300fb98b5c0e1ee9b07ff7c1c4bcef85045d844b33c
+ codeSamplesRevisionDigest: sha256:68f0535d2a29eafd4da54cc0f2ebb260b678afae6f4a752f76cad957fb319df2
workflow:
workflowVersion: 1.0.0
speakeasyVersion: 1.787.0
diff --git a/RELEASES.md b/RELEASES.md
index 06b3d82b..251818a2 100644
--- a/RELEASES.md
+++ b/RELEASES.md
@@ -118,4 +118,14 @@ Based on:
### Generated
- [python v0.11.1] .
### Releases
-- [PyPI v0.11.1] https://pypi.org/project/openrouter/0.11.1 - .
\ No newline at end of file
+- [PyPI v0.11.1] https://pypi.org/project/openrouter/0.11.1 - .
+
+## 2026-07-03 15:05:16
+### Changes
+Based on:
+- OpenAPI Doc
+- Speakeasy CLI 1.787.0 (2.914.0) https://github.com/speakeasy-api/speakeasy
+### Generated
+- [python v0.11.2] .
+### Releases
+- [PyPI v0.11.2] https://pypi.org/project/openrouter/0.11.2 - .
\ No newline at end of file
diff --git a/docs/components/listworkspacemembersresponse.mdx b/docs/components/listworkspacemembersresponse.mdx
new file mode 100644
index 00000000..90edcaf6
--- /dev/null
+++ b/docs/components/listworkspacemembersresponse.mdx
@@ -0,0 +1,10 @@
+---
+title: "ListWorkspaceMembersResponse"
+---
+
+## Fields
+
+| Field | Type | Required | Description | Example |
+| -------------------------------------------------------------------- | -------------------------------------------------------------------- | -------------------------------------------------------------------- | -------------------------------------------------------------------- | -------------------------------------------------------------------- |
+| `data` | List[[components.WorkspaceMember](../components/workspacemember.mdx)] | :heavy_check_mark: | List of workspace members | |
+| `total_count` | *int* | :heavy_check_mark: | Total number of members in the workspace | 5 |
\ No newline at end of file
diff --git a/docs/operations/listworkspacemembersglobals.mdx b/docs/operations/listworkspacemembersglobals.mdx
new file mode 100644
index 00000000..c8f845c5
--- /dev/null
+++ b/docs/operations/listworkspacemembersglobals.mdx
@@ -0,0 +1,11 @@
+---
+title: "ListWorkspaceMembersGlobals"
+---
+
+## Fields
+
+| Field | Type | Required | Description |
+| ------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
+| `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.
|
\ No newline at end of file
diff --git a/docs/operations/listworkspacemembersrequest.mdx b/docs/operations/listworkspacemembersrequest.mdx
new file mode 100644
index 00000000..fe553b32
--- /dev/null
+++ b/docs/operations/listworkspacemembersrequest.mdx
@@ -0,0 +1,14 @@
+---
+title: "ListWorkspaceMembersRequest"
+---
+
+## Fields
+
+| Field | Type | Required | Description | Example |
+| ------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
+| `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.
| |
+| `id` | *str* | :heavy_check_mark: | The workspace ID (UUID) or slug | production |
+| `offset` | *Optional[int]* | :heavy_minus_sign: | Number of records to skip for pagination | 0 |
+| `limit` | *Optional[int]* | :heavy_minus_sign: | Maximum number of records to return (max 100) | 50 |
\ No newline at end of file
diff --git a/docs/operations/listworkspacemembersresponse.mdx b/docs/operations/listworkspacemembersresponse.mdx
new file mode 100644
index 00000000..94558019
--- /dev/null
+++ b/docs/operations/listworkspacemembersresponse.mdx
@@ -0,0 +1,9 @@
+---
+title: "ListWorkspaceMembersResponse"
+---
+
+## Fields
+
+| Field | Type | Required | Description | Example |
+| ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| `result` | [components.ListWorkspaceMembersResponse](../components/listworkspacemembersresponse.mdx) | :heavy_check_mark: | N/A | \{
"data": [
\{
"created_at": "2025-08-24T10:30:00Z",
"id": "660e8400-e29b-41d4-a716-446655440000",
"role": "member",
"user_id": "user_abc123",
"workspace_id": "550e8400-e29b-41d4-a716-446655440000"
}
],
"total_count": 1
} |
\ No newline at end of file
diff --git a/docs/sdks/workspaces/README.mdx b/docs/sdks/workspaces/README.mdx
index cf4cc041..37f2346c 100644
--- a/docs/sdks/workspaces/README.mdx
+++ b/docs/sdks/workspaces/README.mdx
@@ -17,6 +17,7 @@ Workspaces endpoints
* [list_budgets](#list_budgets) - List workspace budgets
* [delete_budget](#delete_budget) - Delete a workspace budget
* [set_budget](#set_budget) - Create or update a workspace budget
+* [list_members](#list_members) - List workspace members
* [bulk_add_members](#bulk_add_members) - Bulk add members to a workspace
* [bulk_remove_members](#bulk_remove_members) - Bulk remove members from a workspace
@@ -436,6 +437,59 @@ with OpenRouter(
| errors.InternalServerResponseError | 500 | application/json |
| errors.OpenRouterDefaultError | 4XX, 5XX | \*/\* |
+## list_members
+
+List all members of a workspace. Returns paginated results. For the default workspace, returns all organization members (implicit membership). [Management key](/docs/guides/overview/auth/management-api-keys) required.
+
+### Example Usage
+
+```python
+from openrouter import OpenRouter
+import os
+
+
+with OpenRouter(
+ http_referer="",
+ x_open_router_title="",
+ x_open_router_categories="",
+ api_key=os.getenv("OPENROUTER_API_KEY", ""),
+) as open_router:
+
+ res = open_router.workspaces.list_members(id="production")
+
+ while res is not None:
+ # Handle items
+
+ res = res.next()
+
+```
+
+### Parameters
+
+| Parameter | Type | Required | Description | Example |
+| ------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
+| `id` | *str* | :heavy_check_mark: | The workspace ID (UUID) or slug | production |
+| `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.
| |
+| `offset` | *Optional[int]* | :heavy_minus_sign: | Number of records to skip for pagination | 0 |
+| `limit` | *Optional[int]* | :heavy_minus_sign: | Maximum number of records to return (max 100) | 50 |
+| `retries` | [Optional[utils.RetryConfig]](../../models/utils/retryconfig.mdx) | :heavy_minus_sign: | Configuration to override the default retry behavior of the client. | |
+
+### Response
+
+**[operations.ListWorkspaceMembersResponse](../../operations/listworkspacemembersresponse.mdx)**
+
+### Errors
+
+| Error Type | Status Code | Content Type |
+| ---------------------------------- | ---------------------------------- | ---------------------------------- |
+| errors.UnauthorizedResponseError | 401 | application/json |
+| errors.ForbiddenResponseError | 403 | application/json |
+| errors.NotFoundResponseError | 404 | application/json |
+| errors.InternalServerResponseError | 500 | application/json |
+| errors.OpenRouterDefaultError | 4XX, 5XX | \*/\* |
+
## bulk_add_members
Add multiple organization members to a workspace. Members are assigned the same role they hold in the organization. [Management key](/docs/guides/overview/auth/management-api-keys) required.
diff --git a/pyproject.toml b/pyproject.toml
index 60601548..e0deb3ea 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,6 +1,6 @@
[project]
name = "openrouter"
-version = "0.11.1"
+version = "0.11.2"
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 30f06450..065e7c61 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.1"
+__version__: str = "0.11.2"
__openapi_doc_version__: str = "1.0.0"
__gen_version__: str = "2.914.0"
-__user_agent__: str = "speakeasy-sdk/python 0.11.1 2.914.0 1.0.0 openrouter"
+__user_agent__: str = "speakeasy-sdk/python 0.11.2 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 c0bbbca9..19c69fe6 100644
--- a/src/openrouter/components/__init__.py
+++ b/src/openrouter/components/__init__.py
@@ -1330,6 +1330,10 @@
ListWorkspaceBudgetsResponse,
ListWorkspaceBudgetsResponseTypedDict,
)
+ from .listworkspacemembersresponse import (
+ ListWorkspaceMembersResponse,
+ ListWorkspaceMembersResponseTypedDict,
+ )
from .listworkspacesresponse import (
ListWorkspacesResponse,
ListWorkspacesResponseTypedDict,
@@ -3686,6 +3690,8 @@
"ListPresetsResponseTypedDict",
"ListWorkspaceBudgetsResponse",
"ListWorkspaceBudgetsResponseTypedDict",
+ "ListWorkspaceMembersResponse",
+ "ListWorkspaceMembersResponseTypedDict",
"ListWorkspacesResponse",
"ListWorkspacesResponseTypedDict",
"LocalShellCallItem",
@@ -5651,6 +5657,8 @@
"ListPresetVersionsResponseTypedDict": ".listpresetversionsresponse",
"ListWorkspaceBudgetsResponse": ".listworkspacebudgetsresponse",
"ListWorkspaceBudgetsResponseTypedDict": ".listworkspacebudgetsresponse",
+ "ListWorkspaceMembersResponse": ".listworkspacemembersresponse",
+ "ListWorkspaceMembersResponseTypedDict": ".listworkspacemembersresponse",
"ListWorkspacesResponse": ".listworkspacesresponse",
"ListWorkspacesResponseTypedDict": ".listworkspacesresponse",
"LocalShellCallItem": ".localshellcallitem",
diff --git a/src/openrouter/components/listworkspacemembersresponse.py b/src/openrouter/components/listworkspacemembersresponse.py
new file mode 100644
index 00000000..91182377
--- /dev/null
+++ b/src/openrouter/components/listworkspacemembersresponse.py
@@ -0,0 +1,22 @@
+"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT."""
+
+from __future__ import annotations
+from .workspacemember import WorkspaceMember, WorkspaceMemberTypedDict
+from openrouter.types import BaseModel
+from typing import List
+from typing_extensions import TypedDict
+
+
+class ListWorkspaceMembersResponseTypedDict(TypedDict):
+ data: List[WorkspaceMemberTypedDict]
+ r"""List of workspace members"""
+ total_count: int
+ r"""Total number of members in the workspace"""
+
+
+class ListWorkspaceMembersResponse(BaseModel):
+ data: List[WorkspaceMember]
+ r"""List of workspace members"""
+
+ total_count: int
+ r"""Total number of members in the workspace"""
diff --git a/src/openrouter/operations/__init__.py b/src/openrouter/operations/__init__.py
index a7983977..fc51690a 100644
--- a/src/openrouter/operations/__init__.py
+++ b/src/openrouter/operations/__init__.py
@@ -618,6 +618,14 @@
ListWorkspaceBudgetsRequest,
ListWorkspaceBudgetsRequestTypedDict,
)
+ from .listworkspacemembers import (
+ ListWorkspaceMembersGlobals,
+ ListWorkspaceMembersGlobalsTypedDict,
+ ListWorkspaceMembersRequest,
+ ListWorkspaceMembersRequestTypedDict,
+ ListWorkspaceMembersResponse,
+ ListWorkspaceMembersResponseTypedDict,
+ )
from .listworkspaces import (
ListWorkspacesGlobals,
ListWorkspacesGlobalsTypedDict,
@@ -1159,6 +1167,12 @@
"ListWorkspaceBudgetsGlobalsTypedDict",
"ListWorkspaceBudgetsRequest",
"ListWorkspaceBudgetsRequestTypedDict",
+ "ListWorkspaceMembersGlobals",
+ "ListWorkspaceMembersGlobalsTypedDict",
+ "ListWorkspaceMembersRequest",
+ "ListWorkspaceMembersRequestTypedDict",
+ "ListWorkspaceMembersResponse",
+ "ListWorkspaceMembersResponseTypedDict",
"ListWorkspacesGlobals",
"ListWorkspacesGlobalsTypedDict",
"ListWorkspacesRequest",
@@ -1721,6 +1735,12 @@
"ListWorkspaceBudgetsGlobalsTypedDict": ".listworkspacebudgets",
"ListWorkspaceBudgetsRequest": ".listworkspacebudgets",
"ListWorkspaceBudgetsRequestTypedDict": ".listworkspacebudgets",
+ "ListWorkspaceMembersGlobals": ".listworkspacemembers",
+ "ListWorkspaceMembersGlobalsTypedDict": ".listworkspacemembers",
+ "ListWorkspaceMembersRequest": ".listworkspacemembers",
+ "ListWorkspaceMembersRequestTypedDict": ".listworkspacemembers",
+ "ListWorkspaceMembersResponse": ".listworkspacemembers",
+ "ListWorkspaceMembersResponseTypedDict": ".listworkspacemembers",
"ListWorkspacesGlobals": ".listworkspaces",
"ListWorkspacesGlobalsTypedDict": ".listworkspaces",
"ListWorkspacesRequest": ".listworkspaces",
diff --git a/src/openrouter/operations/listworkspacemembers.py b/src/openrouter/operations/listworkspacemembers.py
new file mode 100644
index 00000000..9a8706fc
--- /dev/null
+++ b/src/openrouter/operations/listworkspacemembers.py
@@ -0,0 +1,189 @@
+"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT."""
+
+from __future__ import annotations
+from openrouter.components import (
+ listworkspacemembersresponse as components_listworkspacemembersresponse,
+)
+from openrouter.types import BaseModel, UNSET_SENTINEL
+from openrouter.utils import (
+ FieldMetadata,
+ HeaderMetadata,
+ PathParamMetadata,
+ QueryParamMetadata,
+)
+import pydantic
+from pydantic import model_serializer
+from typing import Awaitable, Callable, Optional, Union
+from typing_extensions import Annotated, NotRequired, TypedDict
+
+
+class ListWorkspaceMembersGlobalsTypedDict(TypedDict):
+ http_referer: NotRequired[str]
+ r"""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: NotRequired[str]
+ r"""The app display name allows you to customize how your app appears in OpenRouter's dashboard.
+
+ """
+ x_open_router_categories: NotRequired[str]
+ r"""Comma-separated list of app categories (e.g. \"cli-agent,cloud-agent\"). Used for marketplace rankings.
+
+ """
+
+
+class ListWorkspaceMembersGlobals(BaseModel):
+ http_referer: Annotated[
+ Optional[str],
+ pydantic.Field(alias="HTTP-Referer"),
+ FieldMetadata(header=HeaderMetadata(style="simple", explode=False)),
+ ] = None
+ r"""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: Annotated[
+ Optional[str],
+ pydantic.Field(alias="X-OpenRouter-Title"),
+ FieldMetadata(header=HeaderMetadata(style="simple", explode=False)),
+ ] = None
+ r"""The app display name allows you to customize how your app appears in OpenRouter's dashboard.
+
+ """
+
+ x_open_router_categories: Annotated[
+ Optional[str],
+ pydantic.Field(alias="X-OpenRouter-Categories"),
+ FieldMetadata(header=HeaderMetadata(style="simple", explode=False)),
+ ] = None
+ r"""Comma-separated list of app categories (e.g. \"cli-agent,cloud-agent\"). Used for marketplace rankings.
+
+ """
+
+ @model_serializer(mode="wrap")
+ def serialize_model(self, handler):
+ optional_fields = set(
+ ["HTTP-Referer", "X-OpenRouter-Title", "X-OpenRouter-Categories"]
+ )
+ serialized = handler(self)
+ m = {}
+
+ for n, f in type(self).model_fields.items():
+ k = f.alias or n
+ val = serialized.get(k, serialized.get(n))
+
+ if val != UNSET_SENTINEL:
+ if val is not None or k not in optional_fields:
+ m[k] = val
+
+ return m
+
+
+class ListWorkspaceMembersRequestTypedDict(TypedDict):
+ id: str
+ r"""The workspace ID (UUID) or slug"""
+ http_referer: NotRequired[str]
+ r"""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: NotRequired[str]
+ r"""The app display name allows you to customize how your app appears in OpenRouter's dashboard.
+
+ """
+ x_open_router_categories: NotRequired[str]
+ r"""Comma-separated list of app categories (e.g. \"cli-agent,cloud-agent\"). Used for marketplace rankings.
+
+ """
+ offset: NotRequired[int]
+ r"""Number of records to skip for pagination"""
+ limit: NotRequired[int]
+ r"""Maximum number of records to return (max 100)"""
+
+
+class ListWorkspaceMembersRequest(BaseModel):
+ id: Annotated[
+ str, FieldMetadata(path=PathParamMetadata(style="simple", explode=False))
+ ]
+ r"""The workspace ID (UUID) or slug"""
+
+ http_referer: Annotated[
+ Optional[str],
+ pydantic.Field(alias="HTTP-Referer"),
+ FieldMetadata(header=HeaderMetadata(style="simple", explode=False)),
+ ] = None
+ r"""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: Annotated[
+ Optional[str],
+ pydantic.Field(alias="X-OpenRouter-Title"),
+ FieldMetadata(header=HeaderMetadata(style="simple", explode=False)),
+ ] = None
+ r"""The app display name allows you to customize how your app appears in OpenRouter's dashboard.
+
+ """
+
+ x_open_router_categories: Annotated[
+ Optional[str],
+ pydantic.Field(alias="X-OpenRouter-Categories"),
+ FieldMetadata(header=HeaderMetadata(style="simple", explode=False)),
+ ] = None
+ r"""Comma-separated list of app categories (e.g. \"cli-agent,cloud-agent\"). Used for marketplace rankings.
+
+ """
+
+ offset: Annotated[
+ Optional[int],
+ FieldMetadata(query=QueryParamMetadata(style="form", explode=True)),
+ ] = None
+ r"""Number of records to skip for pagination"""
+
+ limit: Annotated[
+ Optional[int],
+ FieldMetadata(query=QueryParamMetadata(style="form", explode=True)),
+ ] = None
+ r"""Maximum number of records to return (max 100)"""
+
+ @model_serializer(mode="wrap")
+ def serialize_model(self, handler):
+ optional_fields = set(
+ [
+ "HTTP-Referer",
+ "X-OpenRouter-Title",
+ "X-OpenRouter-Categories",
+ "offset",
+ "limit",
+ ]
+ )
+ serialized = handler(self)
+ m = {}
+
+ for n, f in type(self).model_fields.items():
+ k = f.alias or n
+ val = serialized.get(k, serialized.get(n))
+
+ if val != UNSET_SENTINEL:
+ if val is not None or k not in optional_fields:
+ m[k] = val
+
+ return m
+
+
+class ListWorkspaceMembersResponseTypedDict(TypedDict):
+ result: (
+ components_listworkspacemembersresponse.ListWorkspaceMembersResponseTypedDict
+ )
+
+
+class ListWorkspaceMembersResponse(BaseModel):
+ next: Union[
+ Callable[[], Optional[ListWorkspaceMembersResponse]],
+ Callable[[], Awaitable[Optional[ListWorkspaceMembersResponse]]],
+ ]
+
+ result: components_listworkspacemembersresponse.ListWorkspaceMembersResponse
diff --git a/src/openrouter/workspaces.py b/src/openrouter/workspaces.py
index d22a8e66..f3cf390c 100644
--- a/src/openrouter/workspaces.py
+++ b/src/openrouter/workspaces.py
@@ -2402,6 +2402,353 @@ async def set_budget_async(
raise errors.OpenRouterDefaultError("Unexpected response received", http_res)
+ def list_members(
+ self,
+ *,
+ id: str,
+ http_referer: Optional[str] = None,
+ x_open_router_title: Optional[str] = None,
+ x_open_router_categories: Optional[str] = None,
+ offset: Optional[int] = None,
+ limit: Optional[int] = None,
+ retries: OptionalNullable[utils.RetryConfig] = UNSET,
+ server_url: Optional[str] = None,
+ timeout_ms: Optional[int] = None,
+ http_headers: Optional[Mapping[str, str]] = None,
+ ) -> Optional[operations.ListWorkspaceMembersResponse]:
+ r"""List workspace members
+
+ List all members of a workspace. Returns paginated results. For the default workspace, returns all organization members (implicit membership). [Management key](/docs/guides/overview/auth/management-api-keys) required.
+
+ :param id: The workspace ID (UUID) or slug
+ :param http_referer: 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.
+
+ :param x_open_router_title: The app display name allows you to customize how your app appears in OpenRouter's dashboard.
+
+ :param x_open_router_categories: Comma-separated list of app categories (e.g. \"cli-agent,cloud-agent\"). Used for marketplace rankings.
+
+ :param offset: Number of records to skip for pagination
+ :param limit: Maximum number of records to return (max 100)
+ :param retries: Override the default retry configuration for this method
+ :param server_url: Override the default server URL for this method
+ :param timeout_ms: Override the default request timeout configuration for this method in milliseconds
+ :param http_headers: Additional headers to set or replace on requests.
+ """
+ base_url = None
+ url_variables = None
+ if timeout_ms is None:
+ timeout_ms = self.sdk_configuration.timeout_ms
+
+ if server_url is not None:
+ base_url = server_url
+ else:
+ base_url = self._get_url(base_url, url_variables)
+
+ request = operations.ListWorkspaceMembersRequest(
+ http_referer=http_referer,
+ x_open_router_title=x_open_router_title,
+ x_open_router_categories=x_open_router_categories,
+ id=id,
+ offset=offset,
+ limit=limit,
+ )
+
+ req = self._build_request(
+ method="GET",
+ path="/workspaces/{id}/members",
+ base_url=base_url,
+ url_variables=url_variables,
+ request=request,
+ request_body_required=False,
+ request_has_path_params=True,
+ request_has_query_params=True,
+ user_agent_header="user-agent",
+ accept_header_value="application/json",
+ http_headers=http_headers,
+ _globals=operations.ListWorkspaceMembersGlobals(
+ http_referer=self.sdk_configuration.globals.http_referer,
+ x_open_router_title=self.sdk_configuration.globals.x_open_router_title,
+ x_open_router_categories=self.sdk_configuration.globals.x_open_router_categories,
+ ),
+ security=self.sdk_configuration.security,
+ allow_empty_value=None,
+ timeout_ms=timeout_ms,
+ )
+
+ if retries == UNSET:
+ if self.sdk_configuration.retry_config is not UNSET:
+ retries = self.sdk_configuration.retry_config
+ else:
+ retries = utils.RetryConfig(
+ "backoff", utils.BackoffStrategy(500, 60000, 1.5, 3600000), True
+ )
+
+ retry_config = None
+ if isinstance(retries, utils.RetryConfig):
+ retry_config = (retries, ["5XX"])
+
+ http_res = self.do_request(
+ hook_ctx=HookContext(
+ config=self.sdk_configuration,
+ base_url=base_url or "",
+ operation_id="listWorkspaceMembers",
+ oauth2_scopes=None,
+ security_source=get_security_from_env(
+ self.sdk_configuration.security, components.Security
+ ),
+ tags=["Workspaces"],
+ extensions=None,
+ ),
+ request=req,
+ is_error_status_code=lambda c: utils.match_status_codes(["4XX", "5XX"], c),
+ retry_config=retry_config,
+ )
+
+ def next_func() -> Optional[operations.ListWorkspaceMembersResponse]:
+ body = utils.unmarshal_json(http_res.text, Union[Dict[Any, Any], List[Any]])
+
+ offset = request.offset if isinstance(request.offset, int) else 0
+
+ if not http_res.text:
+ return None
+ results = JSONPath("$.data").parse(body)
+ if len(results) == 0 or len(results[0]) == 0:
+ return None
+ limit_ = request.limit if isinstance(request.limit, int) else 0
+ if len(results[0]) < limit_:
+ return None
+ next_offset = offset + len(results[0])
+
+ return self.list_members(
+ id=id,
+ http_referer=http_referer,
+ x_open_router_title=x_open_router_title,
+ x_open_router_categories=x_open_router_categories,
+ offset=next_offset,
+ limit=limit,
+ retries=retries,
+ server_url=server_url,
+ timeout_ms=timeout_ms,
+ http_headers=http_headers,
+ )
+
+ response_data: Any = None
+ if utils.match_response(http_res, "200", "application/json"):
+ return operations.ListWorkspaceMembersResponse(
+ result=unmarshal_json_response(
+ components.ListWorkspaceMembersResponse, http_res
+ ),
+ next=next_func,
+ )
+ if utils.match_response(http_res, "401", "application/json"):
+ response_data = unmarshal_json_response(
+ errors.UnauthorizedResponseErrorData, http_res
+ )
+ raise errors.UnauthorizedResponseError(response_data, http_res)
+ if utils.match_response(http_res, "403", "application/json"):
+ response_data = unmarshal_json_response(
+ errors.ForbiddenResponseErrorData, http_res
+ )
+ raise errors.ForbiddenResponseError(response_data, http_res)
+ if utils.match_response(http_res, "404", "application/json"):
+ response_data = unmarshal_json_response(
+ errors.NotFoundResponseErrorData, http_res
+ )
+ raise errors.NotFoundResponseError(response_data, http_res)
+ if utils.match_response(http_res, "500", "application/json"):
+ response_data = unmarshal_json_response(
+ errors.InternalServerResponseErrorData, http_res
+ )
+ raise errors.InternalServerResponseError(response_data, http_res)
+ if utils.match_response(http_res, "4XX", "*"):
+ http_res_text = utils.stream_to_text(http_res)
+ raise errors.OpenRouterDefaultError(
+ "API error occurred", http_res, http_res_text
+ )
+ if utils.match_response(http_res, "5XX", "*"):
+ http_res_text = utils.stream_to_text(http_res)
+ raise errors.OpenRouterDefaultError(
+ "API error occurred", http_res, http_res_text
+ )
+
+ raise errors.OpenRouterDefaultError("Unexpected response received", http_res)
+
+ async def list_members_async(
+ self,
+ *,
+ id: str,
+ http_referer: Optional[str] = None,
+ x_open_router_title: Optional[str] = None,
+ x_open_router_categories: Optional[str] = None,
+ offset: Optional[int] = None,
+ limit: Optional[int] = None,
+ retries: OptionalNullable[utils.RetryConfig] = UNSET,
+ server_url: Optional[str] = None,
+ timeout_ms: Optional[int] = None,
+ http_headers: Optional[Mapping[str, str]] = None,
+ ) -> Optional[operations.ListWorkspaceMembersResponse]:
+ r"""List workspace members
+
+ List all members of a workspace. Returns paginated results. For the default workspace, returns all organization members (implicit membership). [Management key](/docs/guides/overview/auth/management-api-keys) required.
+
+ :param id: The workspace ID (UUID) or slug
+ :param http_referer: 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.
+
+ :param x_open_router_title: The app display name allows you to customize how your app appears in OpenRouter's dashboard.
+
+ :param x_open_router_categories: Comma-separated list of app categories (e.g. \"cli-agent,cloud-agent\"). Used for marketplace rankings.
+
+ :param offset: Number of records to skip for pagination
+ :param limit: Maximum number of records to return (max 100)
+ :param retries: Override the default retry configuration for this method
+ :param server_url: Override the default server URL for this method
+ :param timeout_ms: Override the default request timeout configuration for this method in milliseconds
+ :param http_headers: Additional headers to set or replace on requests.
+ """
+ base_url = None
+ url_variables = None
+ if timeout_ms is None:
+ timeout_ms = self.sdk_configuration.timeout_ms
+
+ if server_url is not None:
+ base_url = server_url
+ else:
+ base_url = self._get_url(base_url, url_variables)
+
+ request = operations.ListWorkspaceMembersRequest(
+ http_referer=http_referer,
+ x_open_router_title=x_open_router_title,
+ x_open_router_categories=x_open_router_categories,
+ id=id,
+ offset=offset,
+ limit=limit,
+ )
+
+ req = self._build_request_async(
+ method="GET",
+ path="/workspaces/{id}/members",
+ base_url=base_url,
+ url_variables=url_variables,
+ request=request,
+ request_body_required=False,
+ request_has_path_params=True,
+ request_has_query_params=True,
+ user_agent_header="user-agent",
+ accept_header_value="application/json",
+ http_headers=http_headers,
+ _globals=operations.ListWorkspaceMembersGlobals(
+ http_referer=self.sdk_configuration.globals.http_referer,
+ x_open_router_title=self.sdk_configuration.globals.x_open_router_title,
+ x_open_router_categories=self.sdk_configuration.globals.x_open_router_categories,
+ ),
+ security=self.sdk_configuration.security,
+ allow_empty_value=None,
+ timeout_ms=timeout_ms,
+ )
+
+ if retries == UNSET:
+ if self.sdk_configuration.retry_config is not UNSET:
+ retries = self.sdk_configuration.retry_config
+ else:
+ retries = utils.RetryConfig(
+ "backoff", utils.BackoffStrategy(500, 60000, 1.5, 3600000), True
+ )
+
+ retry_config = None
+ if isinstance(retries, utils.RetryConfig):
+ retry_config = (retries, ["5XX"])
+
+ http_res = await self.do_request_async(
+ hook_ctx=HookContext(
+ config=self.sdk_configuration,
+ base_url=base_url or "",
+ operation_id="listWorkspaceMembers",
+ oauth2_scopes=None,
+ security_source=get_security_from_env(
+ self.sdk_configuration.security, components.Security
+ ),
+ tags=["Workspaces"],
+ extensions=None,
+ ),
+ request=req,
+ is_error_status_code=lambda c: utils.match_status_codes(["4XX", "5XX"], c),
+ retry_config=retry_config,
+ )
+
+ def next_func() -> Awaitable[Optional[operations.ListWorkspaceMembersResponse]]:
+ body = utils.unmarshal_json(http_res.text, Union[Dict[Any, Any], List[Any]])
+
+ async def empty_result():
+ return None
+
+ offset = request.offset if isinstance(request.offset, int) else 0
+
+ if not http_res.text:
+ return empty_result()
+ results = JSONPath("$.data").parse(body)
+ if len(results) == 0 or len(results[0]) == 0:
+ return empty_result()
+ limit_ = request.limit if isinstance(request.limit, int) else 0
+ if len(results[0]) < limit_:
+ return empty_result()
+ next_offset = offset + len(results[0])
+
+ return self.list_members_async(
+ id=id,
+ http_referer=http_referer,
+ x_open_router_title=x_open_router_title,
+ x_open_router_categories=x_open_router_categories,
+ offset=next_offset,
+ limit=limit,
+ retries=retries,
+ server_url=server_url,
+ timeout_ms=timeout_ms,
+ http_headers=http_headers,
+ )
+
+ response_data: Any = None
+ if utils.match_response(http_res, "200", "application/json"):
+ return operations.ListWorkspaceMembersResponse(
+ result=unmarshal_json_response(
+ components.ListWorkspaceMembersResponse, http_res
+ ),
+ next=next_func,
+ )
+ if utils.match_response(http_res, "401", "application/json"):
+ response_data = unmarshal_json_response(
+ errors.UnauthorizedResponseErrorData, http_res
+ )
+ raise errors.UnauthorizedResponseError(response_data, http_res)
+ if utils.match_response(http_res, "403", "application/json"):
+ response_data = unmarshal_json_response(
+ errors.ForbiddenResponseErrorData, http_res
+ )
+ raise errors.ForbiddenResponseError(response_data, http_res)
+ if utils.match_response(http_res, "404", "application/json"):
+ response_data = unmarshal_json_response(
+ errors.NotFoundResponseErrorData, http_res
+ )
+ raise errors.NotFoundResponseError(response_data, http_res)
+ if utils.match_response(http_res, "500", "application/json"):
+ response_data = unmarshal_json_response(
+ errors.InternalServerResponseErrorData, http_res
+ )
+ raise errors.InternalServerResponseError(response_data, http_res)
+ if utils.match_response(http_res, "4XX", "*"):
+ http_res_text = await utils.stream_to_text_async(http_res)
+ raise errors.OpenRouterDefaultError(
+ "API error occurred", http_res, http_res_text
+ )
+ if utils.match_response(http_res, "5XX", "*"):
+ http_res_text = await utils.stream_to_text_async(http_res)
+ raise errors.OpenRouterDefaultError(
+ "API error occurred", http_res, http_res_text
+ )
+
+ raise errors.OpenRouterDefaultError("Unexpected response received", http_res)
+
def bulk_add_members(
self,
*,
diff --git a/uv.lock b/uv.lock
index 68cc8206..b1a15246 100644
--- a/uv.lock
+++ b/uv.lock
@@ -213,7 +213,7 @@ wheels = [
[[package]]
name = "openrouter"
-version = "0.11.1"
+version = "0.11.2"
source = { editable = "." }
dependencies = [
{ name = "httpcore" },