Skip to main content

openrouter/types/
workspace.rs

1//! Types for the workspace management endpoints
2//! (`/workspaces` CRUD + bulk-member add/remove).
3//!
4//! Shapes mirror the Go SDK (`workspaces_models.go`) one-for-one. All these
5//! endpoints require a **provisioning (management) API key** — a regular
6//! inference key returns 401.
7
8use serde::{Deserialize, Serialize};
9
10/// A workspace as returned by the workspaces endpoints.
11#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
12pub struct Workspace {
13    /// Stable workspace identifier.
14    #[serde(default)]
15    pub id: String,
16    /// Display name.
17    #[serde(default)]
18    pub name: String,
19    /// URL-safe slug.
20    #[serde(default)]
21    pub slug: String,
22    /// Free-form description.
23    #[serde(default)]
24    pub description: Option<String>,
25    /// User id of the workspace creator, when known.
26    #[serde(default)]
27    pub created_by: Option<String>,
28    /// Creation timestamp.
29    #[serde(default)]
30    pub created_at: String,
31    /// Last-update timestamp.
32    #[serde(default)]
33    pub updated_at: Option<String>,
34    /// Default text-model id.
35    #[serde(default)]
36    pub default_text_model: Option<String>,
37    /// Default image-model id.
38    #[serde(default)]
39    pub default_image_model: Option<String>,
40    /// Default provider sort (`throughput`, `price`, `latency`).
41    #[serde(default)]
42    pub default_provider_sort: Option<String>,
43    /// API key ids whose IO is logged for this workspace.
44    #[serde(default)]
45    pub io_logging_api_key_ids: Option<Vec<i64>>,
46    /// IO-logging sampling rate (0.0–1.0).
47    #[serde(default)]
48    pub io_logging_sampling_rate: f64,
49    /// Enable data-discount logging.
50    #[serde(default)]
51    pub is_data_discount_logging_enabled: bool,
52    /// Broadcast observability events.
53    #[serde(default)]
54    pub is_observability_broadcast_enabled: bool,
55    /// Enable IO logging for observability.
56    #[serde(default)]
57    pub is_observability_io_logging_enabled: bool,
58}
59
60/// Optional query parameters for [`crate::Client::list_workspaces`].
61#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
62pub struct ListWorkspacesOptions {
63    /// Skip this many rows before returning results.
64    pub offset: Option<u32>,
65    /// Cap on the number of rows returned.
66    pub limit: Option<u32>,
67}
68
69impl ListWorkspacesOptions {
70    /// Construct an empty options struct.
71    pub fn new() -> Self {
72        Self::default()
73    }
74
75    /// Builder: set [`Self::offset`].
76    pub fn offset(mut self, offset: u32) -> Self {
77        self.offset = Some(offset);
78        self
79    }
80
81    /// Builder: set [`Self::limit`].
82    pub fn limit(mut self, limit: u32) -> Self {
83        self.limit = Some(limit);
84        self
85    }
86
87    pub(crate) fn to_query(self) -> Vec<(&'static str, String)> {
88        let mut q = Vec::new();
89        if let Some(o) = self.offset {
90            q.push(("offset", o.to_string()));
91        }
92        if let Some(l) = self.limit {
93            q.push(("limit", l.to_string()));
94        }
95        q
96    }
97}
98
99/// Response from `GET /workspaces`.
100#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
101pub struct ListWorkspacesResponse {
102    /// Workspace rows.
103    #[serde(default)]
104    pub data: Vec<Workspace>,
105    /// Total row count, ignoring pagination.
106    #[serde(default)]
107    pub total_count: u64,
108}
109
110/// Request body for [`crate::Client::create_workspace`].
111///
112/// `name` and `slug` are required; all other fields are optional.
113#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
114pub struct CreateWorkspaceRequest {
115    /// Display name.
116    pub name: String,
117    /// URL-safe slug.
118    pub slug: String,
119    /// Free-form description.
120    #[serde(skip_serializing_if = "Option::is_none", default)]
121    pub description: Option<String>,
122    /// Default text-model id.
123    #[serde(skip_serializing_if = "Option::is_none", default)]
124    pub default_text_model: Option<String>,
125    /// Default image-model id.
126    #[serde(skip_serializing_if = "Option::is_none", default)]
127    pub default_image_model: Option<String>,
128    /// Default provider sort.
129    #[serde(skip_serializing_if = "Option::is_none", default)]
130    pub default_provider_sort: Option<String>,
131    /// API key ids whose IO is logged.
132    #[serde(skip_serializing_if = "Option::is_none", default)]
133    pub io_logging_api_key_ids: Option<Vec<i64>>,
134    /// IO-logging sampling rate.
135    #[serde(skip_serializing_if = "Option::is_none", default)]
136    pub io_logging_sampling_rate: Option<f64>,
137    /// Enable data-discount logging.
138    #[serde(skip_serializing_if = "Option::is_none", default)]
139    pub is_data_discount_logging_enabled: Option<bool>,
140    /// Broadcast observability events.
141    #[serde(skip_serializing_if = "Option::is_none", default)]
142    pub is_observability_broadcast_enabled: Option<bool>,
143    /// Enable IO logging for observability.
144    #[serde(skip_serializing_if = "Option::is_none", default)]
145    pub is_observability_io_logging_enabled: Option<bool>,
146}
147
148/// Partial-update body for [`crate::Client::update_workspace`]. Only the
149/// fields you set are sent.
150#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
151pub struct UpdateWorkspaceRequest {
152    /// New display name.
153    #[serde(skip_serializing_if = "Option::is_none", default)]
154    pub name: Option<String>,
155    /// New URL-safe slug.
156    #[serde(skip_serializing_if = "Option::is_none", default)]
157    pub slug: Option<String>,
158    /// New description.
159    #[serde(skip_serializing_if = "Option::is_none", default)]
160    pub description: Option<String>,
161    /// New default text-model id.
162    #[serde(skip_serializing_if = "Option::is_none", default)]
163    pub default_text_model: Option<String>,
164    /// New default image-model id.
165    #[serde(skip_serializing_if = "Option::is_none", default)]
166    pub default_image_model: Option<String>,
167    /// New default provider sort.
168    #[serde(skip_serializing_if = "Option::is_none", default)]
169    pub default_provider_sort: Option<String>,
170    /// New IO-logging API key ids.
171    #[serde(skip_serializing_if = "Option::is_none", default)]
172    pub io_logging_api_key_ids: Option<Vec<i64>>,
173    /// New IO-logging sampling rate.
174    #[serde(skip_serializing_if = "Option::is_none", default)]
175    pub io_logging_sampling_rate: Option<f64>,
176    /// New data-discount logging flag.
177    #[serde(skip_serializing_if = "Option::is_none", default)]
178    pub is_data_discount_logging_enabled: Option<bool>,
179    /// New observability broadcast flag.
180    #[serde(skip_serializing_if = "Option::is_none", default)]
181    pub is_observability_broadcast_enabled: Option<bool>,
182    /// New observability IO-logging flag.
183    #[serde(skip_serializing_if = "Option::is_none", default)]
184    pub is_observability_io_logging_enabled: Option<bool>,
185}
186
187/// Response from `GET /workspaces/{id_or_slug}`.
188#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
189pub struct GetWorkspaceResponse {
190    /// Workspace payload.
191    #[serde(default)]
192    pub data: Workspace,
193}
194
195/// Response from `POST /workspaces`.
196#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
197pub struct CreateWorkspaceResponse {
198    /// Newly-created workspace.
199    #[serde(default)]
200    pub data: Workspace,
201}
202
203/// Response from `PATCH /workspaces/{id_or_slug}`.
204#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
205pub struct UpdateWorkspaceResponse {
206    /// Updated workspace.
207    #[serde(default)]
208    pub data: Workspace,
209}
210
211/// Response from `DELETE /workspaces/{id_or_slug}`.
212#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
213pub struct DeleteWorkspaceResponse {
214    /// True when the workspace existed and was deleted.
215    #[serde(default)]
216    pub deleted: bool,
217}
218
219/// Role of a member within a workspace.
220#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
221#[serde(rename_all = "lowercase")]
222pub enum WorkspaceMemberRole {
223    /// Workspace administrator.
224    Admin,
225    /// Regular workspace member.
226    Member,
227}
228
229/// A single workspace membership.
230#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
231pub struct WorkspaceMember {
232    /// Membership identifier.
233    #[serde(default)]
234    pub id: String,
235    /// Workspace this membership belongs to.
236    #[serde(default)]
237    pub workspace_id: String,
238    /// User id of the member.
239    #[serde(default)]
240    pub user_id: String,
241    /// Member role.
242    pub role: WorkspaceMemberRole,
243    /// Membership creation timestamp.
244    #[serde(default)]
245    pub created_at: String,
246}
247
248/// Response from `POST /workspaces/{id_or_slug}/members/add`.
249#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
250pub struct BulkAddWorkspaceMembersResponse {
251    /// Number of members added.
252    #[serde(default)]
253    pub added_count: u64,
254    /// Membership rows for the newly-added members.
255    #[serde(default)]
256    pub data: Vec<WorkspaceMember>,
257}
258
259/// Response from `POST /workspaces/{id_or_slug}/members/remove`.
260#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
261pub struct BulkRemoveWorkspaceMembersResponse {
262    /// Number of members removed.
263    #[serde(default)]
264    pub removed_count: u64,
265}
266
267/// Internal body shape for bulk add/remove requests.
268#[derive(Debug, Serialize)]
269pub(crate) struct BulkWorkspaceMembersRequest<'a> {
270    pub user_ids: &'a [String],
271}