Skip to main content

hanzo_client/apis/
team_api.rs

1/*
2 * Hanzo Cloud API
3 *
4 * The Hanzo Cloud API as a customer calls it: every operation under /v1/ except the operator's admin product, relay routes, legacy spellings and capabilities still reached by flag. Tagged by product: the first path segment after /v1/.
5 *
6 * The version of the OpenAPI document: v1
7 * 
8 * Generated by: https://openapi-generator.tech
9 */
10
11
12use reqwest;
13use serde::{Deserialize, Serialize, de::Error as _};
14use crate::{apis::ResponseContent, models};
15use super::{Error, configuration, ContentType};
16
17
18/// struct for typed errors of method [`delete_team_account_cookie`]
19#[derive(Debug, Clone, Serialize, Deserialize)]
20#[serde(untagged)]
21pub enum DeleteTeamAccountCookieError {
22    UnknownValue(serde_json::Value),
23}
24
25/// struct for typed errors of method [`delete_team_files_by_workspace_by_filename`]
26#[derive(Debug, Clone, Serialize, Deserialize)]
27#[serde(untagged)]
28pub enum DeleteTeamFilesByWorkspaceByFilenameError {
29    UnknownValue(serde_json::Value),
30}
31
32/// struct for typed errors of method [`get_team_account_auth_by_provider`]
33#[derive(Debug, Clone, Serialize, Deserialize)]
34#[serde(untagged)]
35pub enum GetTeamAccountAuthByProviderError {
36    UnknownValue(serde_json::Value),
37}
38
39/// struct for typed errors of method [`get_team_account_auth_by_provider_callback`]
40#[derive(Debug, Clone, Serialize, Deserialize)]
41#[serde(untagged)]
42pub enum GetTeamAccountAuthByProviderCallbackError {
43    UnknownValue(serde_json::Value),
44}
45
46/// struct for typed errors of method [`get_team_account_providers`]
47#[derive(Debug, Clone, Serialize, Deserialize)]
48#[serde(untagged)]
49pub enum GetTeamAccountProvidersError {
50    UnknownValue(serde_json::Value),
51}
52
53/// struct for typed errors of method [`get_team_billing_plan`]
54#[derive(Debug, Clone, Serialize, Deserialize)]
55#[serde(untagged)]
56pub enum GetTeamBillingPlanError {
57    UnknownValue(serde_json::Value),
58}
59
60/// struct for typed errors of method [`get_team_billing_ui`]
61#[derive(Debug, Clone, Serialize, Deserialize)]
62#[serde(untagged)]
63pub enum GetTeamBillingUiError {
64    UnknownValue(serde_json::Value),
65}
66
67/// struct for typed errors of method [`get_team_bots`]
68#[derive(Debug, Clone, Serialize, Deserialize)]
69#[serde(untagged)]
70pub enum GetTeamBotsError {
71    UnknownValue(serde_json::Value),
72}
73
74/// struct for typed errors of method [`get_team_collaborator`]
75#[derive(Debug, Clone, Serialize, Deserialize)]
76#[serde(untagged)]
77pub enum GetTeamCollaboratorError {
78    UnknownValue(serde_json::Value),
79}
80
81/// struct for typed errors of method [`get_team_files_by_workspace_by_filename`]
82#[derive(Debug, Clone, Serialize, Deserialize)]
83#[serde(untagged)]
84pub enum GetTeamFilesByWorkspaceByFilenameError {
85    UnknownValue(serde_json::Value),
86}
87
88/// struct for typed errors of method [`get_team_rooms`]
89#[derive(Debug, Clone, Serialize, Deserialize)]
90#[serde(untagged)]
91pub enum GetTeamRoomsError {
92    UnknownValue(serde_json::Value),
93}
94
95/// struct for typed errors of method [`get_team_transactor_api_v1_statistics`]
96#[derive(Debug, Clone, Serialize, Deserialize)]
97#[serde(untagged)]
98pub enum GetTeamTransactorApiV1StatisticsError {
99    UnknownValue(serde_json::Value),
100}
101
102/// struct for typed errors of method [`get_team_transactor_by_token`]
103#[derive(Debug, Clone, Serialize, Deserialize)]
104#[serde(untagged)]
105pub enum GetTeamTransactorByTokenError {
106    UnknownValue(serde_json::Value),
107}
108
109/// struct for typed errors of method [`get_team_transactor_statistics`]
110#[derive(Debug, Clone, Serialize, Deserialize)]
111#[serde(untagged)]
112pub enum GetTeamTransactorStatisticsError {
113    UnknownValue(serde_json::Value),
114}
115
116/// struct for typed errors of method [`post_team_account`]
117#[derive(Debug, Clone, Serialize, Deserialize)]
118#[serde(untagged)]
119pub enum PostTeamAccountError {
120    UnknownValue(serde_json::Value),
121}
122
123/// struct for typed errors of method [`post_team_bots_sync`]
124#[derive(Debug, Clone, Serialize, Deserialize)]
125#[serde(untagged)]
126pub enum PostTeamBotsSyncError {
127    UnknownValue(serde_json::Value),
128}
129
130/// struct for typed errors of method [`post_team_collaborator_rpc_by_documentid`]
131#[derive(Debug, Clone, Serialize, Deserialize)]
132#[serde(untagged)]
133pub enum PostTeamCollaboratorRpcByDocumentidError {
134    UnknownValue(serde_json::Value),
135}
136
137/// struct for typed errors of method [`post_team_files_by_workspace`]
138#[derive(Debug, Clone, Serialize, Deserialize)]
139#[serde(untagged)]
140pub enum PostTeamFilesByWorkspaceError {
141    UnknownValue(serde_json::Value),
142}
143
144/// struct for typed errors of method [`put_team_account_cookie`]
145#[derive(Debug, Clone, Serialize, Deserialize)]
146#[serde(untagged)]
147pub enum PutTeamAccountCookieError {
148    UnknownValue(serde_json::Value),
149}
150
151/// struct for typed errors of method [`put_team_rooms_by_id`]
152#[derive(Debug, Clone, Serialize, Deserialize)]
153#[serde(untagged)]
154pub enum PutTeamRoomsByIdError {
155    UnknownValue(serde_json::Value),
156}
157
158
159/// Signs this browser out of team by expiring the HttpOnly account-token cookie the OAuth callback set. It is the counterpart of the cookie PUT, it takes nothing — the cookie it clears is named by this service, never by the caller — and it is unconditional: a caller with no cookie, an expired one or a forged one all get the same acknowledgement, because clearing something that is not there is the same outcome as clearing something that is.  It clears ONLY the team session cookie. The IAM access-token cookie the same callback set is a different credential with a different lifetime and is left alone, so this is a team sign-out, not a platform one.
160pub async fn delete_team_account_cookie(configuration: &configuration::Configuration, ) -> Result<models::CookieAck, Error<DeleteTeamAccountCookieError>> {
161
162    let uri_str = format!("{}/v1/team/account/cookie", configuration.base_path);
163    let mut req_builder = configuration.client.request(reqwest::Method::DELETE, &uri_str);
164
165    if let Some(ref user_agent) = configuration.user_agent {
166        req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
167    }
168    if let Some(ref token) = configuration.bearer_access_token {
169        req_builder = req_builder.bearer_auth(token.to_owned());
170    };
171
172    let req = req_builder.build()?;
173    let resp = configuration.client.execute(req).await?;
174
175    let status = resp.status();
176    let content_type = resp
177        .headers()
178        .get("content-type")
179        .and_then(|v| v.to_str().ok())
180        .unwrap_or("application/octet-stream");
181    let content_type = super::ContentType::from(content_type);
182
183    if !status.is_client_error() && !status.is_server_error() {
184        let content = resp.text().await?;
185        match content_type {
186            ContentType::Json => serde_json::from_str(&content).map_err(Error::from),
187            ContentType::Text => return Err(Error::from(serde_json::Error::custom("Received `text/plain` content type response that cannot be converted to `models::CookieAck`"))),
188            ContentType::Unsupported(unknown_type) => return Err(Error::from(serde_json::Error::custom(format!("Received `{unknown_type}` content type response that cannot be converted to `models::CookieAck`")))),
189        }
190    } else {
191        let content = resp.text().await?;
192        let entity: Option<DeleteTeamAccountCookieError> = serde_json::from_str(&content).ok();
193        Err(Error::ResponseError(ResponseContent { status, content, entity }))
194    }
195}
196
197/// Removes one blob from a workspace's file store. The caller must hold a verified session AND be a member of the workspace; anything else — an unknown workspace, another tenant's workspace, a workspace the caller is not in — answers the same 404, so a probe learns nothing about what exists.  It is IDEMPOTENT: deleting a present or an absent blob both answer 204, so a delete never confirms a blob's existence and a foreign blob id (a physical key the caller can never name into another tenant's box) is a harmless no-op. A storage backend that is unavailable fails closed with 502 rather than lying about success.
198pub async fn delete_team_files_by_workspace_by_filename(configuration: &configuration::Configuration, workspace: &str, filename: &str, file: Option<&str>) -> Result<(), Error<DeleteTeamFilesByWorkspaceByFilenameError>> {
199    // add a prefix to parameters to efficiently prevent name collisions
200    let p_workspace = workspace;
201    let p_filename = filename;
202    let p_file = file;
203
204    let uri_str = format!("{}/v1/team/files/{workspace}/{filename}", configuration.base_path, workspace=crate::apis::urlencode(p_workspace), filename=crate::apis::urlencode(p_filename));
205    let mut req_builder = configuration.client.request(reqwest::Method::DELETE, &uri_str);
206
207    if let Some(ref param_value) = p_file {
208        req_builder = req_builder.query(&[("file", &param_value.to_string())]);
209    }
210    if let Some(ref user_agent) = configuration.user_agent {
211        req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
212    }
213    if let Some(ref token) = configuration.bearer_access_token {
214        req_builder = req_builder.bearer_auth(token.to_owned());
215    };
216
217    let req = req_builder.build()?;
218    let resp = configuration.client.execute(req).await?;
219
220    let status = resp.status();
221
222    if !status.is_client_error() && !status.is_server_error() {
223        Ok(())
224    } else {
225        let content = resp.text().await?;
226        let entity: Option<DeleteTeamFilesByWorkspaceByFilenameError> = serde_json::from_str(&content).ok();
227        Err(Error::ResponseError(ResponseContent { status, content, entity }))
228    }
229}
230
231/// STARTS the OAuth hop: answers 302 to hanzo.id's authorize endpoint and sets the short-lived HttpOnly state cookie that binds the flow to this browser. NO TOKEN COMES BACK FROM THIS CALL — the session is minted by the callback below, and a client that expects JSON here gets a redirect with no body.  A browser is the intended caller. Anything else must follow the Location AND keep the Set-Cookie, because the callback refuses a flow whose state it cannot match. That cookie carries the random nonce plus the client's navigateUrl, so the round trip needs no second channel, and it lives ten minutes — the whole budget for the hop.  The provider segment only picks a hint: the redirect_uri is ALWAYS the canonical openid callback, the one IAM has registered. Measured end to end, hanzo.id strips that hint today, so /auth/google and /auth/openid land on the same Hanzo sign-in page — the federation shortcut is an upstream fix, not a second endpoint here.
232pub async fn get_team_account_auth_by_provider(configuration: &configuration::Configuration, provider: &str) -> Result<(), Error<GetTeamAccountAuthByProviderError>> {
233    // add a prefix to parameters to efficiently prevent name collisions
234    let p_provider = provider;
235
236    let uri_str = format!("{}/v1/team/account/auth/{provider}", configuration.base_path, provider=crate::apis::urlencode(p_provider));
237    let mut req_builder = configuration.client.request(reqwest::Method::GET, &uri_str);
238
239    if let Some(ref user_agent) = configuration.user_agent {
240        req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
241    }
242    if let Some(ref token) = configuration.bearer_access_token {
243        req_builder = req_builder.bearer_auth(token.to_owned());
244    };
245
246    let req = req_builder.build()?;
247    let resp = configuration.client.execute(req).await?;
248
249    let status = resp.status();
250
251    if !status.is_client_error() && !status.is_server_error() {
252        Ok(())
253    } else {
254        let content = resp.text().await?;
255        let entity: Option<GetTeamAccountAuthByProviderError> = serde_json::from_str(&content).ok();
256        Err(Error::ResponseError(ResponseContent { status, content, entity }))
257    }
258}
259
260/// COMPLETES the OAuth hop: hanzo.id redirects the browser here with ?code and ?state, and the answer is another 302 — back to the client's login route carrying the freshly minted team session token in the query. Never JSON, and never a token in this response's own body.  THE STATE IS CHECKED FIRST, before the code is even looked at: the flow cookie is read and cleared one-shot, and a callback whose ?state does not equal the nonce it held is bounced with error=state_mismatch and NEVER exchanged. That is what makes a forged or replayed callback inert. Only then is the code exchanged server-side — team is a confidential client with a client_secret, so there is no PKCE and the code never passes through the browser's JS.  The tenant is derived from the IAM access token VERIFIED RS256 against the JWKS, the same trust anchor the identity boundary uses; a token whose owner claim is empty fails closed with no login at all. Every org that token proves gets a workspace ensured, so a member of two orgs is a counted seat in both. The IAM access token is also parked in an HttpOnly cookie for the same-origin agents proxy — page JS never reads it.  EVERY failure is a redirect, not a status: a denied consent, a missing code, a failed exchange, an unreadable userinfo, an unverifiable org and a token-mint failure each bounce to the login page with an ?error code naming the step.
261pub async fn get_team_account_auth_by_provider_callback(configuration: &configuration::Configuration, provider: &str) -> Result<(), Error<GetTeamAccountAuthByProviderCallbackError>> {
262    // add a prefix to parameters to efficiently prevent name collisions
263    let p_provider = provider;
264
265    let uri_str = format!("{}/v1/team/account/auth/{provider}/callback", configuration.base_path, provider=crate::apis::urlencode(p_provider));
266    let mut req_builder = configuration.client.request(reqwest::Method::GET, &uri_str);
267
268    if let Some(ref user_agent) = configuration.user_agent {
269        req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
270    }
271    if let Some(ref token) = configuration.bearer_access_token {
272        req_builder = req_builder.bearer_auth(token.to_owned());
273    };
274
275    let req = req_builder.build()?;
276    let resp = configuration.client.execute(req).await?;
277
278    let status = resp.status();
279
280    if !status.is_client_error() && !status.is_server_error() {
281        Ok(())
282    } else {
283        let content = resp.text().await?;
284        let entity: Option<GetTeamAccountAuthByProviderCallbackError> = serde_json::from_str(&content).ok();
285        Err(Error::ResponseError(ResponseContent { status, content, entity }))
286    }
287}
288
289/// Returns the identity providers this deployment starts a login with. It is always exactly one — hanzo.id. Which identities that provider accepts (Google, GitHub, passkey, password) is IAM's question, answered on IAM's own page next to the identity check and the training-data consent that must precede a first session; listing them here would be a second place holding that answer, and the two drift the moment IAM gains or drops one.
290pub async fn get_team_account_providers(configuration: &configuration::Configuration, ) -> Result<Vec<models::ProviderInfo>, Error<GetTeamAccountProvidersError>> {
291
292    let uri_str = format!("{}/v1/team/account/providers", configuration.base_path);
293    let mut req_builder = configuration.client.request(reqwest::Method::GET, &uri_str);
294
295    if let Some(ref user_agent) = configuration.user_agent {
296        req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
297    }
298    if let Some(ref token) = configuration.bearer_access_token {
299        req_builder = req_builder.bearer_auth(token.to_owned());
300    };
301
302    let req = req_builder.build()?;
303    let resp = configuration.client.execute(req).await?;
304
305    let status = resp.status();
306    let content_type = resp
307        .headers()
308        .get("content-type")
309        .and_then(|v| v.to_str().ok())
310        .unwrap_or("application/octet-stream");
311    let content_type = super::ContentType::from(content_type);
312
313    if !status.is_client_error() && !status.is_server_error() {
314        let content = resp.text().await?;
315        match content_type {
316            ContentType::Json => serde_json::from_str(&content).map_err(Error::from),
317            ContentType::Text => return Err(Error::from(serde_json::Error::custom("Received `text/plain` content type response that cannot be converted to `Vec&lt;models::ProviderInfo&gt;`"))),
318            ContentType::Unsupported(unknown_type) => return Err(Error::from(serde_json::Error::custom(format!("Received `{unknown_type}` content type response that cannot be converted to `Vec&lt;models::ProviderInfo&gt;`")))),
319        }
320    } else {
321        let content = resp.text().await?;
322        let entity: Option<GetTeamAccountProvidersError> = serde_json::from_str(&content).ok();
323        Err(Error::ResponseError(ResponseContent { status, content, entity }))
324    }
325}
326
327/// Returns the plan and seat counts for the caller's OWN org, resolved from the VERIFIED team session token — never a client header. Seats and guests are the org's distinct active human members (a bot member is not a seat); the plan comes from the licensing entitlement and is empty when that read is unavailable, so the page shows an honest dash rather than a fabricated tier. A caller with no verified session gets 401, and a real seat-read failure is a 502 rather than a false \"0 members\".
328pub async fn get_team_billing_plan(configuration: &configuration::Configuration, ) -> Result<models::PlanInfo, Error<GetTeamBillingPlanError>> {
329
330    let uri_str = format!("{}/v1/team/billing/plan", configuration.base_path);
331    let mut req_builder = configuration.client.request(reqwest::Method::GET, &uri_str);
332
333    if let Some(ref user_agent) = configuration.user_agent {
334        req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
335    }
336    if let Some(ref token) = configuration.bearer_access_token {
337        req_builder = req_builder.bearer_auth(token.to_owned());
338    };
339
340    let req = req_builder.build()?;
341    let resp = configuration.client.execute(req).await?;
342
343    let status = resp.status();
344    let content_type = resp
345        .headers()
346        .get("content-type")
347        .and_then(|v| v.to_str().ok())
348        .unwrap_or("application/octet-stream");
349    let content_type = super::ContentType::from(content_type);
350
351    if !status.is_client_error() && !status.is_server_error() {
352        let content = resp.text().await?;
353        match content_type {
354            ContentType::Json => serde_json::from_str(&content).map_err(Error::from),
355            ContentType::Text => return Err(Error::from(serde_json::Error::custom("Received `text/plain` content type response that cannot be converted to `models::PlanInfo`"))),
356            ContentType::Unsupported(unknown_type) => return Err(Error::from(serde_json::Error::custom(format!("Received `{unknown_type}` content type response that cannot be converted to `models::PlanInfo`")))),
357        }
358    } else {
359        let content = resp.text().await?;
360        let entity: Option<GetTeamBillingPlanError> = serde_json::from_str(&content).ok();
361        Err(Error::ResponseError(ResponseContent { status, content, entity }))
362    }
363}
364
365/// Serves the usage-and-wallet page the Team front links to — HTML, not JSON. It is a static React build compiled into this binary, so there is no upstream to be down and no build step at request time.  SESSION-GATED: without a verified team session token — bearer, else the HttpOnly account cookie — the caller gets 401 and not one byte of the page, so an anonymous browser meets a refusal rather than a shell that then fails to load anything.  The page is markup only. It reads money SAME-ORIGIN from cloud's own balance and usage endpoints, which pin the org from the IAM cookie the team OAuth callback set — nothing under this path proxies a money read, so there is no second auth mechanism here to get wrong. A deployment whose page was never built answers 503 naming the missing bundle, never a blank 200.
366pub async fn get_team_billing_ui(configuration: &configuration::Configuration, ) -> Result<reqwest::Response, Error<GetTeamBillingUiError>> {
367
368    let uri_str = format!("{}/v1/team/billing/ui", configuration.base_path);
369    let mut req_builder = configuration.client.request(reqwest::Method::GET, &uri_str);
370
371    if let Some(ref user_agent) = configuration.user_agent {
372        req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
373    }
374    if let Some(ref token) = configuration.bearer_access_token {
375        req_builder = req_builder.bearer_auth(token.to_owned());
376    };
377
378    let req = req_builder.build()?;
379    let resp = configuration.client.execute(req).await?;
380
381    let status = resp.status();
382
383    if !status.is_client_error() && !status.is_server_error() {
384        Ok(resp)
385    } else {
386        let content = resp.text().await?;
387        let entity: Option<GetTeamBillingUiError> = serde_json::from_str(&content).ok();
388        Err(Error::ResponseError(ResponseContent { status, content, entity }))
389    }
390}
391
392/// Returns the caller org's bot members — the org's agents projected as the workspace Employees they become, each with the member account uuid and Person reference the roster addresses it by. An agents subsystem that is not mounted answers an empty list, never an error.
393pub async fn get_team_bots(configuration: &configuration::Configuration, ) -> Result<models::BotRoster, Error<GetTeamBotsError>> {
394
395    let uri_str = format!("{}/v1/team/bots", configuration.base_path);
396    let mut req_builder = configuration.client.request(reqwest::Method::GET, &uri_str);
397
398    if let Some(ref user_agent) = configuration.user_agent {
399        req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
400    }
401    if let Some(ref token) = configuration.bearer_access_token {
402        req_builder = req_builder.bearer_auth(token.to_owned());
403    };
404
405    let req = req_builder.build()?;
406    let resp = configuration.client.execute(req).await?;
407
408    let status = resp.status();
409    let content_type = resp
410        .headers()
411        .get("content-type")
412        .and_then(|v| v.to_str().ok())
413        .unwrap_or("application/octet-stream");
414    let content_type = super::ContentType::from(content_type);
415
416    if !status.is_client_error() && !status.is_server_error() {
417        let content = resp.text().await?;
418        match content_type {
419            ContentType::Json => serde_json::from_str(&content).map_err(Error::from),
420            ContentType::Text => return Err(Error::from(serde_json::Error::custom("Received `text/plain` content type response that cannot be converted to `models::BotRoster`"))),
421            ContentType::Unsupported(unknown_type) => return Err(Error::from(serde_json::Error::custom(format!("Received `{unknown_type}` content type response that cannot be converted to `models::BotRoster`")))),
422        }
423    } else {
424        let content = resp.text().await?;
425        let entity: Option<GetTeamBotsError> = serde_json::from_str(&content).ok();
426        Err(Error::ResponseError(ResponseContent { status, content, entity }))
427    }
428}
429
430/// Upgrades to the hocuspocus WebSocket the Team editor syncs its Y.js documents over: binary frames of document name, message type and payload, with ONE socket multiplexing every document a tab has open. The server is a relay and an ordered update log, not a CRDT engine — it replays the log to each joining peer and broadcasts every update to the rest, which converges because Y.js updates are commutative and idempotent. There is no body; the response is a protocol upgrade.  BOTH LANES SHARE ONE ROOT. The client derives them from one configured URL — this socket at its root, the markup-snapshot RPC one segment in — so pointing the editor at this service is one value, and the two lanes cannot drift apart.  AUTH IS IN-BAND, PER DOCUMENT, NOT ON THE UPGRADE. The handshake gates only on browser Origin (403 outside the team surfaces; no Origin at all is admitted, which is what a non-browser sends), and then the first frame for a document must be an Auth message carrying the same session or workspace token every other team route verifies — a browser WebSocket cannot set an Authorization header, which is why the token rides inside the protocol. Anything else on an unauthenticated document is answered with one permission denial and nothing further.  Every document is authorized on its own: the document's workspace must be the token's workspace when the token pins one, and the caller must be a member of it. A mismatch, an unknown workspace and a non-member deny alike with \"document not found\". Rooms are keyed by org and workspace and the persisted log's key embeds both, so a foreign document id can neither join a room nor read a blob.  The server pings every twenty seconds and drops a socket silent for sixty, so a backgrounded tab — whose JS timers are throttled but whose network stack still auto-pongs — stays connected instead of dying into a reconnect loop.
431pub async fn get_team_collaborator(configuration: &configuration::Configuration, ) -> Result<(), Error<GetTeamCollaboratorError>> {
432
433    let uri_str = format!("{}/v1/team/collaborator", configuration.base_path);
434    let mut req_builder = configuration.client.request(reqwest::Method::GET, &uri_str);
435
436    if let Some(ref user_agent) = configuration.user_agent {
437        req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
438    }
439    if let Some(ref token) = configuration.bearer_access_token {
440        req_builder = req_builder.bearer_auth(token.to_owned());
441    };
442
443    let req = req_builder.build()?;
444    let resp = configuration.client.execute(req).await?;
445
446    let status = resp.status();
447
448    if !status.is_client_error() && !status.is_server_error() {
449        Ok(())
450    } else {
451        let content = resp.text().await?;
452        let entity: Option<GetTeamCollaboratorError> = serde_json::from_str(&content).ok();
453        Err(Error::ResponseError(ResponseContent { status, content, entity }))
454    }
455}
456
457/// Streams one blob's raw BYTES back — this is the read side of the workspace file store, not a JSON envelope around it.  THE BLOB IS NAMED BY THE `file` QUERY PARAMETER, NOT BY :filename. The path segment is only the name a browser saves the download under; a request without ?file= is a 400 no matter what the path says.  The Content-Type is derived from the STORED BYTES, never from the name: only png, jpeg, gif and webp, recognized by their magic bytes, are served inline under their true type, and everything else is served inert as application/octet-stream with an attachment disposition. Every response carries nosniff, so a file uploaded under an .svg or .html name cannot be talked into executing in a viewer's origin. Blobs are immutable, so a hit caches privately for a year.  Same gate as the upload: verified token, membership of the workspace. A genuine miss, another tenant's workspace, a workspace the caller is not in, and a blob id belonging to a different workspace are ONE answer — 404 — because the physical key is org- and workspace-scoped and a foreign id is simply a key that does not exist. An unavailable backend is a 502, never an empty 200.
458pub async fn get_team_files_by_workspace_by_filename(configuration: &configuration::Configuration, workspace: &str, filename: &str) -> Result<reqwest::Response, Error<GetTeamFilesByWorkspaceByFilenameError>> {
459    // add a prefix to parameters to efficiently prevent name collisions
460    let p_workspace = workspace;
461    let p_filename = filename;
462
463    let uri_str = format!("{}/v1/team/files/{workspace}/{filename}", configuration.base_path, workspace=crate::apis::urlencode(p_workspace), filename=crate::apis::urlencode(p_filename));
464    let mut req_builder = configuration.client.request(reqwest::Method::GET, &uri_str);
465
466    if let Some(ref user_agent) = configuration.user_agent {
467        req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
468    }
469    if let Some(ref token) = configuration.bearer_access_token {
470        req_builder = req_builder.bearer_auth(token.to_owned());
471    };
472
473    let req = req_builder.build()?;
474    let resp = configuration.client.execute(req).await?;
475
476    let status = resp.status();
477
478    if !status.is_client_error() && !status.is_server_error() {
479        Ok(resp)
480    } else {
481        let content = resp.text().await?;
482        let entity: Option<GetTeamFilesByWorkspaceByFilenameError> = serde_json::from_str(&content).ok();
483        Err(Error::ResponseError(ResponseContent { status, content, entity }))
484    }
485}
486
487/// Returns every room of the caller's org, across the workspaces it owns, with the work facet each carries.  It reads the SAME Chunter documents the transactor serves, so a room opened in the Team client appears here with no sync, and a facet written here is read by anything holding the document. Direct messages are included: a room between two people is a room with no name, not a different kind of thing.
488pub async fn get_team_rooms(configuration: &configuration::Configuration, ) -> Result<models::TeamRooms, Error<GetTeamRoomsError>> {
489
490    let uri_str = format!("{}/v1/team/rooms", configuration.base_path);
491    let mut req_builder = configuration.client.request(reqwest::Method::GET, &uri_str);
492
493    if let Some(ref user_agent) = configuration.user_agent {
494        req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
495    }
496    if let Some(ref token) = configuration.bearer_access_token {
497        req_builder = req_builder.bearer_auth(token.to_owned());
498    };
499
500    let req = req_builder.build()?;
501    let resp = configuration.client.execute(req).await?;
502
503    let status = resp.status();
504    let content_type = resp
505        .headers()
506        .get("content-type")
507        .and_then(|v| v.to_str().ok())
508        .unwrap_or("application/octet-stream");
509    let content_type = super::ContentType::from(content_type);
510
511    if !status.is_client_error() && !status.is_server_error() {
512        let content = resp.text().await?;
513        match content_type {
514            ContentType::Json => serde_json::from_str(&content).map_err(Error::from),
515            ContentType::Text => return Err(Error::from(serde_json::Error::custom("Received `text/plain` content type response that cannot be converted to `models::TeamRooms`"))),
516            ContentType::Unsupported(unknown_type) => return Err(Error::from(serde_json::Error::custom(format!("Received `{unknown_type}` content type response that cannot be converted to `models::TeamRooms`")))),
517        }
518    } else {
519        let content = resp.text().await?;
520        let entity: Option<GetTeamRoomsError> = serde_json::from_str(&content).ok();
521        Err(Error::ResponseError(ResponseContent { status, content, entity }))
522    }
523}
524
525/// Statistics returns the transactor's live sessions for the workspace the caller's credential names — the endpoint the front's workspace switcher and server panel poll on the transactor base. `token` carries the same two lanes the socket's path segment does: a workspace UUID names the workspace and is authorized against the membership rows, an HS256 workspace token names it in its signed claims. activeSessions carries ONLY that one workspace, never another tenant's sessions. An unverifiable credential, or one the caller is no member under, is 401.
526pub async fn get_team_transactor_api_v1_statistics(configuration: &configuration::Configuration, token: Option<&str>) -> Result<models::StatsOut, Error<GetTeamTransactorApiV1StatisticsError>> {
527    // add a prefix to parameters to efficiently prevent name collisions
528    let p_token = token;
529
530    let uri_str = format!("{}/v1/team/transactor/api/v1/statistics", configuration.base_path);
531    let mut req_builder = configuration.client.request(reqwest::Method::GET, &uri_str);
532
533    if let Some(ref param_value) = p_token {
534        req_builder = req_builder.query(&[("token", &param_value.to_string())]);
535    }
536    if let Some(ref user_agent) = configuration.user_agent {
537        req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
538    }
539    if let Some(ref token) = configuration.bearer_access_token {
540        req_builder = req_builder.bearer_auth(token.to_owned());
541    };
542
543    let req = req_builder.build()?;
544    let resp = configuration.client.execute(req).await?;
545
546    let status = resp.status();
547    let content_type = resp
548        .headers()
549        .get("content-type")
550        .and_then(|v| v.to_str().ok())
551        .unwrap_or("application/octet-stream");
552    let content_type = super::ContentType::from(content_type);
553
554    if !status.is_client_error() && !status.is_server_error() {
555        let content = resp.text().await?;
556        match content_type {
557            ContentType::Json => serde_json::from_str(&content).map_err(Error::from),
558            ContentType::Text => return Err(Error::from(serde_json::Error::custom("Received `text/plain` content type response that cannot be converted to `models::StatsOut`"))),
559            ContentType::Unsupported(unknown_type) => return Err(Error::from(serde_json::Error::custom(format!("Received `{unknown_type}` content type response that cannot be converted to `models::StatsOut`")))),
560        }
561    } else {
562        let content = resp.text().await?;
563        let entity: Option<GetTeamTransactorApiV1StatisticsError> = serde_json::from_str(&content).ok();
564        Err(Error::ResponseError(ResponseContent { status, content, entity }))
565    }
566}
567
568/// Upgrades to the WebSocket the Team client runs an entire workspace over: every frame is a ZAP envelope wrapping one JSON-RPC message — findAll/findOne reads against the workspace's documents, tx writes that broadcast to the other live sessions, hello negotiating JSON rather than msgpack. The response is a protocol upgrade, so there is no body to read.  THE PATH SEGMENT IS THE CREDENTIAL. It is the workspace token selectWorkspace minted — bearer-equivalent, and sitting in a URL that proxies and access logs record, which is exactly why it expires in twelve hours and is re-minted on demand rather than being long-lived like the session token. It is decoded and verified (signature and expiry) BEFORE the upgrade, so a bad one is a 401 and never a socket that is accepted and then dropped, and it must carry both an account and a workspace claim. Nothing ambient authorizes this socket: a WebSocket is exempt from CORS, so a cookie-borne credential would make the Origin check the only access control on the whole data plane.  The tenant is the token's SIGNED org claim and it keys every store path, so no header can name another workspace's data. The upgrade ALSO refuses a browser Origin outside the team surfaces with 403 — otherwise any page could open an authenticated socket with a token it lured out of a logged-in browser — while a request with no Origin at all is admitted, because that is what a non-browser client sends.  On connect the workspace's system spaces are seeded once and the roster is reconciled every time, so the org's human members and its bots are present as workspace people without a separate sync call.
569pub async fn get_team_transactor_by_token(configuration: &configuration::Configuration, token: &str) -> Result<(), Error<GetTeamTransactorByTokenError>> {
570    // add a prefix to parameters to efficiently prevent name collisions
571    let p_token = token;
572
573    let uri_str = format!("{}/v1/team/transactor/{token}", configuration.base_path, token=crate::apis::urlencode(p_token));
574    let mut req_builder = configuration.client.request(reqwest::Method::GET, &uri_str);
575
576    if let Some(ref user_agent) = configuration.user_agent {
577        req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
578    }
579    if let Some(ref token) = configuration.bearer_access_token {
580        req_builder = req_builder.bearer_auth(token.to_owned());
581    };
582
583    let req = req_builder.build()?;
584    let resp = configuration.client.execute(req).await?;
585
586    let status = resp.status();
587
588    if !status.is_client_error() && !status.is_server_error() {
589        Ok(())
590    } else {
591        let content = resp.text().await?;
592        let entity: Option<GetTeamTransactorByTokenError> = serde_json::from_str(&content).ok();
593        Err(Error::ResponseError(ResponseContent { status, content, entity }))
594    }
595}
596
597/// Statistics returns the transactor's live sessions for the workspace the caller's credential names — the endpoint the front's workspace switcher and server panel poll on the transactor base. `token` carries the same two lanes the socket's path segment does: a workspace UUID names the workspace and is authorized against the membership rows, an HS256 workspace token names it in its signed claims. activeSessions carries ONLY that one workspace, never another tenant's sessions. An unverifiable credential, or one the caller is no member under, is 401.
598pub async fn get_team_transactor_statistics(configuration: &configuration::Configuration, token: Option<&str>) -> Result<models::StatsOut, Error<GetTeamTransactorStatisticsError>> {
599    // add a prefix to parameters to efficiently prevent name collisions
600    let p_token = token;
601
602    let uri_str = format!("{}/v1/team/transactor/statistics", configuration.base_path);
603    let mut req_builder = configuration.client.request(reqwest::Method::GET, &uri_str);
604
605    if let Some(ref param_value) = p_token {
606        req_builder = req_builder.query(&[("token", &param_value.to_string())]);
607    }
608    if let Some(ref user_agent) = configuration.user_agent {
609        req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
610    }
611    if let Some(ref token) = configuration.bearer_access_token {
612        req_builder = req_builder.bearer_auth(token.to_owned());
613    };
614
615    let req = req_builder.build()?;
616    let resp = configuration.client.execute(req).await?;
617
618    let status = resp.status();
619    let content_type = resp
620        .headers()
621        .get("content-type")
622        .and_then(|v| v.to_str().ok())
623        .unwrap_or("application/octet-stream");
624    let content_type = super::ContentType::from(content_type);
625
626    if !status.is_client_error() && !status.is_server_error() {
627        let content = resp.text().await?;
628        match content_type {
629            ContentType::Json => serde_json::from_str(&content).map_err(Error::from),
630            ContentType::Text => return Err(Error::from(serde_json::Error::custom("Received `text/plain` content type response that cannot be converted to `models::StatsOut`"))),
631            ContentType::Unsupported(unknown_type) => return Err(Error::from(serde_json::Error::custom(format!("Received `{unknown_type}` content type response that cannot be converted to `models::StatsOut`")))),
632        }
633    } else {
634        let content = resp.text().await?;
635        let entity: Option<GetTeamTransactorStatisticsError> = serde_json::from_str(&content).ok();
636        Err(Error::ResponseError(ResponseContent { status, content, entity }))
637    }
638}
639
640/// The account control plane the Team client speaks: one POST carries a `method` verb and its `params`, and answers {\"result\": …}. The verbs are the session's own reads and the workspace switch — getLoginInfoByToken, getUserWorkspaces, selectWorkspace, getWorkspaceInfo, getMemberships, getPerson, getSocialIds, getRegionInfo, isReadOnlyGuest — plus sendInvite, which adds a member to a workspace and is refused for a caller who is not its owner or admin.  A REFUSAL IS HTTP 200 carrying {\"error\": {severity, code, params}} — the platform Status the client translates — not a 4xx. An unreadable body, an unauthorized session and an unknown verb all arrive that way, so a caller that reads only the status code reads every failure here as a success.  NO CREDENTIAL IS EVER HANDLED HERE. login, signUp, the OTP verbs, password change and reset, join and the guest-token exchange each answer Unauthorized with \"sign in at hanzo.id\" — a stated policy, not an unknown method, so the refusal is a fact a test can pin. Sessions come from the OAuth pair under /account/auth.  Auth is the team session token: Authorization: Bearer, else the HttpOnly account-token cookie. The tenant is that token's SIGNED org claim, never a header, and selectWorkspace resolves only among the orgs the token proves membership of. It also demands an explicit workspaceUrl — it never falls back to a first workspace, and a slug that resolves in two of the caller's orgs answers Ambiguous rather than picking one.
641pub async fn post_team_account(configuration: &configuration::Configuration, ) -> Result<(), Error<PostTeamAccountError>> {
642
643    let uri_str = format!("{}/v1/team/account", configuration.base_path);
644    let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
645
646    if let Some(ref user_agent) = configuration.user_agent {
647        req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
648    }
649    if let Some(ref token) = configuration.bearer_access_token {
650        req_builder = req_builder.bearer_auth(token.to_owned());
651    };
652
653    let req = req_builder.build()?;
654    let resp = configuration.client.execute(req).await?;
655
656    let status = resp.status();
657
658    if !status.is_client_error() && !status.is_server_error() {
659        Ok(())
660    } else {
661        let content = resp.text().await?;
662        let entity: Option<PostTeamAccountError> = serde_json::from_str(&content).ok();
663        Err(Error::ResponseError(ResponseContent { status, content, entity }))
664    }
665}
666
667/// SyncBots re-projects the caller org's agents as workspace members into EVERY workspace of the org, and removes the ones whose agent is gone. It is idempotent, and admin only: mutating a workspace's roster requires the gateway-minted admin flag, which a client can never forge. It answers how many roster entries the reconcile touched.
668pub async fn post_team_bots_sync(configuration: &configuration::Configuration, ) -> Result<models::BotSync, Error<PostTeamBotsSyncError>> {
669
670    let uri_str = format!("{}/v1/team/bots/sync", configuration.base_path);
671    let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
672
673    if let Some(ref user_agent) = configuration.user_agent {
674        req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
675    }
676    if let Some(ref token) = configuration.bearer_access_token {
677        req_builder = req_builder.bearer_auth(token.to_owned());
678    };
679
680    let req = req_builder.build()?;
681    let resp = configuration.client.execute(req).await?;
682
683    let status = resp.status();
684    let content_type = resp
685        .headers()
686        .get("content-type")
687        .and_then(|v| v.to_str().ok())
688        .unwrap_or("application/octet-stream");
689    let content_type = super::ContentType::from(content_type);
690
691    if !status.is_client_error() && !status.is_server_error() {
692        let content = resp.text().await?;
693        match content_type {
694            ContentType::Json => serde_json::from_str(&content).map_err(Error::from),
695            ContentType::Text => return Err(Error::from(serde_json::Error::custom("Received `text/plain` content type response that cannot be converted to `models::BotSync`"))),
696            ContentType::Unsupported(unknown_type) => return Err(Error::from(serde_json::Error::custom(format!("Received `{unknown_type}` content type response that cannot be converted to `models::BotSync`")))),
697        }
698    } else {
699        let content = resp.text().await?;
700        let entity: Option<PostTeamBotsSyncError> = serde_json::from_str(&content).ok();
701        Err(Error::ResponseError(ResponseContent { status, content, entity }))
702    }
703}
704
705/// CollabRPC is the collaborative-markup snapshot plane the Team front's editor speaks: createContent stores a document field's markup at a fresh, immutable blob ref and returns it, updateContent stores a new snapshot and answers nothing, and getContent reads back the exact snapshot a ref names.  createContent ALSO seeds the live-editing update log from the front-supplied Y.js update, so a dialog-authored description is visible in the collaborative editor — which replays that log — and not only in snapshot reads. updateContent never touches that log: peers may be live-editing the document, and their edits are not this call's to overwrite.  Every call is scoped to the caller's VERIFIED session or workspace token: the documentId's workspace must be the token's workspace when the token names one, and the caller must be a member of it. An unknown workspace, another tenant's workspace and a workspace the caller is not in all answer the same 404, so a probe learns nothing about what exists.
706pub async fn post_team_collaborator_rpc_by_documentid(configuration: &configuration::Configuration, document_id: &str, collab_request: models::CollabRequest) -> Result<models::CollabResult, Error<PostTeamCollaboratorRpcByDocumentidError>> {
707    // add a prefix to parameters to efficiently prevent name collisions
708    let p_document_id = document_id;
709    let p_collab_request = collab_request;
710
711    let uri_str = format!("{}/v1/team/collaborator/rpc/{documentId}", configuration.base_path, documentId=crate::apis::urlencode(p_document_id));
712    let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
713
714    if let Some(ref user_agent) = configuration.user_agent {
715        req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
716    }
717    if let Some(ref token) = configuration.bearer_access_token {
718        req_builder = req_builder.bearer_auth(token.to_owned());
719    };
720    req_builder = req_builder.json(&p_collab_request);
721
722    let req = req_builder.build()?;
723    let resp = configuration.client.execute(req).await?;
724
725    let status = resp.status();
726    let content_type = resp
727        .headers()
728        .get("content-type")
729        .and_then(|v| v.to_str().ok())
730        .unwrap_or("application/octet-stream");
731    let content_type = super::ContentType::from(content_type);
732
733    if !status.is_client_error() && !status.is_server_error() {
734        let content = resp.text().await?;
735        match content_type {
736            ContentType::Json => serde_json::from_str(&content).map_err(Error::from),
737            ContentType::Text => return Err(Error::from(serde_json::Error::custom("Received `text/plain` content type response that cannot be converted to `models::CollabResult`"))),
738            ContentType::Unsupported(unknown_type) => return Err(Error::from(serde_json::Error::custom(format!("Received `{unknown_type}` content type response that cannot be converted to `models::CollabResult`")))),
739        }
740    } else {
741        let content = resp.text().await?;
742        let entity: Option<PostTeamCollaboratorRpcByDocumentidError> = serde_json::from_str(&content).ok();
743        Err(Error::ResponseError(ResponseContent { status, content, entity }))
744    }
745}
746
747/// Stores one file in a workspace's blob store and answers the blob id it is addressable by, as plain text — the front discards that body, it is there for a caller driving this by hand.  The body is a multipart form with a `file` part, and THAT PART'S FILENAME IS THE BLOB ID: the client mints it (a uuid v4) and the server stores under it, so a part whose filename is not a uuid is refused rather than assigned one. A file over 100 MiB is 413 and an empty one is 400.  The caller must hold a verified session or workspace token AND be a member of the workspace; an unknown workspace, another tenant's workspace and a workspace the caller is not in all answer the same 404, so a probe learns nothing about what exists. The stored key embeds the verified org and the workspace, so an upload cannot land in another tenant's box whatever id it names. A storage backend that is unavailable fails closed with 502 rather than reporting a write it never made.
748pub async fn post_team_files_by_workspace(configuration: &configuration::Configuration, workspace: &str, body: Option<Vec<u8>>) -> Result<reqwest::Response, Error<PostTeamFilesByWorkspaceError>> {
749    // add a prefix to parameters to efficiently prevent name collisions
750    let p_workspace = workspace;
751    let p_body = body;
752
753    let uri_str = format!("{}/v1/team/files/{workspace}", configuration.base_path, workspace=crate::apis::urlencode(p_workspace));
754    let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
755
756    if let Some(ref user_agent) = configuration.user_agent {
757        req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
758    }
759    if let Some(ref token) = configuration.bearer_access_token {
760        req_builder = req_builder.bearer_auth(token.to_owned());
761    };
762    if let Some(body) = p_body {
763        req_builder = req_builder.body(body);
764    }
765
766    let req = req_builder.build()?;
767    let resp = configuration.client.execute(req).await?;
768
769    let status = resp.status();
770
771    if !status.is_client_error() && !status.is_server_error() {
772        Ok(resp)
773    } else {
774        let content = resp.text().await?;
775        let entity: Option<PostTeamFilesByWorkspaceError> = serde_json::from_str(&content).ok();
776        Err(Error::ResponseError(ResponseContent { status, content, entity }))
777    }
778}
779
780/// Writes the team session token into the HttpOnly `account-token` cookie — Secure, SameSite=Lax, whole-origin scope, thirty days — and answers {\"result\": true}. This is how the client turns the token it caught off the OAuth bounce into a credential page JS can no longer read, which IS the security property: script that cannot see the cookie cannot exfiltrate it, and every later call on the files, billing and collaborator planes authenticates from it when no bearer is sent.  The token is VERIFIED — signature and expiry, against this service's own signing secret — BEFORE it is stored. Anything this service did not sign is 401 and nothing is written; persisting a caller-supplied value unchecked would be a session-fixation hole, where an attacker pins a cookie the victim's browser then presents as its own.  The token may arrive as `token` in the JSON body or, when the body is absent or unparseable, from the Authorization bearer — an unreadable body is NOT an error here. The sibling DELETE clears this same cookie and signs the browser out of team only: the IAM cookie set alongside it is a different credential with its own lifetime and is left alone.
781pub async fn put_team_account_cookie(configuration: &configuration::Configuration, ) -> Result<models::CookieAck, Error<PutTeamAccountCookieError>> {
782
783    let uri_str = format!("{}/v1/team/account/cookie", configuration.base_path);
784    let mut req_builder = configuration.client.request(reqwest::Method::PUT, &uri_str);
785
786    if let Some(ref user_agent) = configuration.user_agent {
787        req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
788    }
789    if let Some(ref token) = configuration.bearer_access_token {
790        req_builder = req_builder.bearer_auth(token.to_owned());
791    };
792
793    let req = req_builder.build()?;
794    let resp = configuration.client.execute(req).await?;
795
796    let status = resp.status();
797    let content_type = resp
798        .headers()
799        .get("content-type")
800        .and_then(|v| v.to_str().ok())
801        .unwrap_or("application/octet-stream");
802    let content_type = super::ContentType::from(content_type);
803
804    if !status.is_client_error() && !status.is_server_error() {
805        let content = resp.text().await?;
806        match content_type {
807            ContentType::Json => serde_json::from_str(&content).map_err(Error::from),
808            ContentType::Text => return Err(Error::from(serde_json::Error::custom("Received `text/plain` content type response that cannot be converted to `models::CookieAck`"))),
809            ContentType::Unsupported(unknown_type) => return Err(Error::from(serde_json::Error::custom(format!("Received `{unknown_type}` content type response that cannot be converted to `models::CookieAck`")))),
810        }
811    } else {
812        let content = resp.text().await?;
813        let entity: Option<PutTeamAccountCookieError> = serde_json::from_str(&content).ok();
814        Err(Error::ResponseError(ResponseContent { status, content, entity }))
815    }
816}
817
818/// States what a room is for: its lifecycle intent, and what it is about. It answers the room as it now stands.  The write is a platform MIXIN on the room document, applied through the SAME applyTx path the Team client's own writes take and broadcast to every connected client — so a room bound here updates live in an open workspace rather than on the next reload.
819pub async fn put_team_rooms_by_id(configuration: &configuration::Configuration, id: &str, team_room_bind: models::TeamRoomBind) -> Result<models::TeamRoom, Error<PutTeamRoomsByIdError>> {
820    // add a prefix to parameters to efficiently prevent name collisions
821    let p_id = id;
822    let p_team_room_bind = team_room_bind;
823
824    let uri_str = format!("{}/v1/team/rooms/{id}", configuration.base_path, id=crate::apis::urlencode(p_id));
825    let mut req_builder = configuration.client.request(reqwest::Method::PUT, &uri_str);
826
827    if let Some(ref user_agent) = configuration.user_agent {
828        req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
829    }
830    if let Some(ref token) = configuration.bearer_access_token {
831        req_builder = req_builder.bearer_auth(token.to_owned());
832    };
833    req_builder = req_builder.json(&p_team_room_bind);
834
835    let req = req_builder.build()?;
836    let resp = configuration.client.execute(req).await?;
837
838    let status = resp.status();
839    let content_type = resp
840        .headers()
841        .get("content-type")
842        .and_then(|v| v.to_str().ok())
843        .unwrap_or("application/octet-stream");
844    let content_type = super::ContentType::from(content_type);
845
846    if !status.is_client_error() && !status.is_server_error() {
847        let content = resp.text().await?;
848        match content_type {
849            ContentType::Json => serde_json::from_str(&content).map_err(Error::from),
850            ContentType::Text => return Err(Error::from(serde_json::Error::custom("Received `text/plain` content type response that cannot be converted to `models::TeamRoom`"))),
851            ContentType::Unsupported(unknown_type) => return Err(Error::from(serde_json::Error::custom(format!("Received `{unknown_type}` content type response that cannot be converted to `models::TeamRoom`")))),
852        }
853    } else {
854        let content = resp.text().await?;
855        let entity: Option<PutTeamRoomsByIdError> = serde_json::from_str(&content).ok();
856        Err(Error::ResponseError(ResponseContent { status, content, entity }))
857    }
858}
859