Skip to main content

clickhouse_cloud_api/
client.rs

1//! HTTP client for the ClickHouse Cloud API.
2//!
3//! Auto-generated from the OpenAPI specification.
4
5use crate::error::Error;
6use crate::models::*;
7
8/// Authentication mode for the API client.
9#[derive(Debug, Clone)]
10enum Auth {
11    Basic { key_id: String, key_secret: String },
12    Bearer { token: String },
13}
14
15/// ClickHouse Cloud API client.
16///
17/// Supports both HTTP Basic Auth (API key/secret) and Bearer token (OAuth) authentication.
18#[derive(Debug, Clone)]
19pub struct Client {
20    http: reqwest::Client,
21    base_url: String,
22    auth: Auth,
23}
24
25impl Client {
26    /// Create a new client with the default base URL (`https://api.clickhouse.cloud`).
27    pub fn new(key_id: impl Into<String>, key_secret: impl Into<String>) -> Self {
28        Self::with_base_url("https://api.clickhouse.cloud", key_id, key_secret)
29    }
30
31    /// Create a new client with a custom base URL.
32    pub fn with_base_url(
33        base_url: impl Into<String>,
34        key_id: impl Into<String>,
35        key_secret: impl Into<String>,
36    ) -> Self {
37        Self {
38            http: reqwest::Client::new(),
39            base_url: base_url.into().trim_end_matches('/').to_string(),
40            auth: Auth::Basic {
41                key_id: key_id.into(),
42                key_secret: key_secret.into(),
43            },
44        }
45    }
46
47    /// Create a new client with Bearer token authentication and a custom base URL.
48    pub fn with_bearer_token(
49        base_url: impl Into<String>,
50        token: impl Into<String>,
51    ) -> Self {
52        Self {
53            http: reqwest::Client::new(),
54            base_url: base_url.into().trim_end_matches('/').to_string(),
55            auth: Auth::Bearer {
56                token: token.into(),
57            },
58        }
59    }
60
61    /// Create a new client with a pre-built HTTP client and Basic auth.
62    ///
63    /// Use this when you need to customize the underlying `reqwest::Client`
64    /// (e.g. to set a custom user-agent or timeout).
65    pub fn with_http_client(
66        http: reqwest::Client,
67        base_url: impl Into<String>,
68        key_id: impl Into<String>,
69        key_secret: impl Into<String>,
70    ) -> Self {
71        Self {
72            http,
73            base_url: base_url.into().trim_end_matches('/').to_string(),
74            auth: Auth::Basic {
75                key_id: key_id.into(),
76                key_secret: key_secret.into(),
77            },
78        }
79    }
80
81    /// Create a new client with a pre-built HTTP client and Bearer auth.
82    ///
83    /// Use this when you need to customize the underlying `reqwest::Client`
84    /// (e.g. to set a custom user-agent or timeout).
85    pub fn with_http_client_bearer(
86        http: reqwest::Client,
87        base_url: impl Into<String>,
88        token: impl Into<String>,
89    ) -> Self {
90        Self {
91            http,
92            base_url: base_url.into().trim_end_matches('/').to_string(),
93            auth: Auth::Bearer {
94                token: token.into(),
95            },
96        }
97    }
98
99    /// Replace the Bearer token without rebuilding the client.
100    ///
101    /// Useful for refreshing an expired OAuth token.
102    /// Returns an error if the client is using Basic auth.
103    pub fn set_bearer_token(&mut self, token: impl Into<String>) -> Result<(), Error> {
104        match &mut self.auth {
105            Auth::Bearer { token: t } => {
106                *t = token.into();
107                Ok(())
108            }
109            Auth::Basic { .. } => Err(Error::AuthMismatch(
110                "set_bearer_token called on a Basic-auth client".into(),
111            )),
112        }
113    }
114
115    fn request(&self, method: reqwest::Method, path: &str) -> reqwest::RequestBuilder {
116        let builder = self
117            .http
118            .request(method, format!("{}{}", self.base_url, path));
119        match &self.auth {
120            Auth::Basic { key_id, key_secret } => builder.basic_auth(key_id, Some(key_secret)),
121            Auth::Bearer { token } => builder.bearer_auth(token),
122        }
123    }
124
125    /// Run a SQL statement against a service's Query API endpoint.
126    ///
127    /// Hits `queries.clickhouse.cloud` (override via the
128    /// `CLICKHOUSE_CLOUD_QUERY_HOST` env var) using Basic auth with the
129    /// provided `key_id`/`key_secret` — a per-service key bound to a
130    /// query endpoint with role `sql_console_read_only` (or
131    /// `sql_console_admin`). This bypasses the client's primary auth
132    /// because Query API keys are scoped to a single service.
133    ///
134    /// Returns the streaming response so the caller can forward it to
135    /// stdout or buffer it into memory.
136    pub async fn run_query(
137        &self,
138        service_id: &str,
139        key_id: &str,
140        key_secret: &str,
141        sql: &str,
142        database: Option<&str>,
143        format: &str,
144    ) -> Result<reqwest::Response, Error> {
145        #[derive(serde::Serialize)]
146        #[serde(rename_all = "camelCase")]
147        struct RunQueryBody<'a> {
148            run_id: String,
149            sql: &'a str,
150            #[serde(skip_serializing_if = "Option::is_none")]
151            database: Option<&'a str>,
152        }
153
154        let host = std::env::var("CLICKHOUSE_CLOUD_QUERY_HOST")
155            .unwrap_or_else(|_| "https://queries.clickhouse.cloud".to_string());
156        let url = format!(
157            "{}/service/{}/run",
158            host.trim_end_matches('/'),
159            service_id,
160        );
161
162        let body = RunQueryBody {
163            run_id: uuid::Uuid::new_v4().to_string(),
164            sql,
165            database,
166        };
167
168        let response = self
169            .http
170            .post(url)
171            .query(&[("format", format)])
172            .basic_auth(key_id, Some(key_secret))
173            .header("content-type", "text/plain;charset=UTF-8")
174            .header("x-service-type", "clickhouse")
175            .header("auth-provider", "custom")
176            .json(&body)
177            .send()
178            .await?;
179
180        let status = response.status();
181        if !status.is_success() {
182            let body_text = response.text().await.unwrap_or_default();
183            return Err(Error::Api {
184                status: status.as_u16(),
185                message: if body_text.is_empty() {
186                    format!("Query API returned {status}")
187                } else {
188                    body_text
189                },
190            });
191        }
192
193        Ok(response)
194    }
195
196    /// Get list of available organizations
197    pub async fn organization_get_list(
198        &self,
199    ) -> Result<ApiResponse<Vec<Organization>>, Error> {
200        let path = "/v1/organizations".to_string();
201        let req = self.request(reqwest::Method::GET, &path);
202        let resp = req.send().await?;
203        let status = resp.status();
204        let body_text = resp.text().await?;
205        if !status.is_success() {
206            return Err(Error::Api {
207                status: status.as_u16(),
208                message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
209                    .ok()
210                    .and_then(|r| r.error)
211                    .unwrap_or(body_text.clone()),
212            });
213        }
214        Ok(serde_json::from_str(&body_text)?)
215    }
216
217    /// Get organization details
218    pub async fn organization_get(
219        &self,
220        organization_id: &str,
221    ) -> Result<ApiResponse<Organization>, Error> {
222        let path = format!("/v1/organizations/{organization_id}");
223        let req = self.request(reqwest::Method::GET, &path);
224        let resp = req.send().await?;
225        let status = resp.status();
226        let body_text = resp.text().await?;
227        if !status.is_success() {
228            return Err(Error::Api {
229                status: status.as_u16(),
230                message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
231                    .ok()
232                    .and_then(|r| r.error)
233                    .unwrap_or(body_text.clone()),
234            });
235        }
236        Ok(serde_json::from_str(&body_text)?)
237    }
238
239    /// Update organization details
240    pub async fn organization_update(
241        &self,
242        organization_id: &str,
243        body: &OrganizationPatchRequest,
244    ) -> Result<ApiResponse<Organization>, Error> {
245        let path = format!("/v1/organizations/{organization_id}");
246        let mut req = self.request(reqwest::Method::PATCH, &path);
247        req = req.json(body);
248        let resp = req.send().await?;
249        let status = resp.status();
250        let body_text = resp.text().await?;
251        if !status.is_success() {
252            return Err(Error::Api {
253                status: status.as_u16(),
254                message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
255                    .ok()
256                    .and_then(|r| r.error)
257                    .unwrap_or(body_text.clone()),
258            });
259        }
260        Ok(serde_json::from_str(&body_text)?)
261    }
262
263    /// List of organization activities
264    pub async fn activity_get_list(
265        &self,
266        organization_id: &str,
267        from_date: Option<&str>,
268        to_date: Option<&str>,
269    ) -> Result<ApiResponse<Vec<Activity>>, Error> {
270        let path = format!("/v1/organizations/{organization_id}/activities");
271        let mut req = self.request(reqwest::Method::GET, &path);
272        if let Some(v) = from_date {
273            req = req.query(&[("from_date", v)]);
274        }
275        if let Some(v) = to_date {
276            req = req.query(&[("to_date", v)]);
277        }
278        let resp = req.send().await?;
279        let status = resp.status();
280        let body_text = resp.text().await?;
281        if !status.is_success() {
282            return Err(Error::Api {
283                status: status.as_u16(),
284                message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
285                    .ok()
286                    .and_then(|r| r.error)
287                    .unwrap_or(body_text.clone()),
288            });
289        }
290        Ok(serde_json::from_str(&body_text)?)
291    }
292
293    /// Organization activity
294    pub async fn activity_get(
295        &self,
296        organization_id: &str,
297        activity_id: &str,
298    ) -> Result<ApiResponse<Activity>, Error> {
299        let path = format!("/v1/organizations/{organization_id}/activities/{activity_id}");
300        let req = self.request(reqwest::Method::GET, &path);
301        let resp = req.send().await?;
302        let status = resp.status();
303        let body_text = resp.text().await?;
304        if !status.is_success() {
305            return Err(Error::Api {
306                status: status.as_u16(),
307                message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
308                    .ok()
309                    .and_then(|r| r.error)
310                    .unwrap_or(body_text.clone()),
311            });
312        }
313        Ok(serde_json::from_str(&body_text)?)
314    }
315
316    /// Create BYOC Infrastructure
317    pub async fn organization_byoc_infrastructure_create(
318        &self,
319        organization_id: &str,
320        body: &ByocInfrastructurePostRequest,
321    ) -> Result<ApiResponse<ByocConfig>, Error> {
322        let path = format!("/v1/organizations/{organization_id}/byocInfrastructure");
323        let mut req = self.request(reqwest::Method::POST, &path);
324        req = req.json(body);
325        let resp = req.send().await?;
326        let status = resp.status();
327        let body_text = resp.text().await?;
328        if !status.is_success() {
329            return Err(Error::Api {
330                status: status.as_u16(),
331                message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
332                    .ok()
333                    .and_then(|r| r.error)
334                    .unwrap_or(body_text.clone()),
335            });
336        }
337        Ok(serde_json::from_str(&body_text)?)
338    }
339
340    /// Remove a BYOC infrastructure
341    pub async fn organization_byoc_infrastructure_delete(
342        &self,
343        organization_id: &str,
344        byoc_infrastructure_id: &str,
345    ) -> Result<ApiResponse<serde_json::Value>, Error> {
346        let path = format!("/v1/organizations/{organization_id}/byocInfrastructure/{byoc_infrastructure_id}");
347        let req = self.request(reqwest::Method::DELETE, &path);
348        let resp = req.send().await?;
349        let status = resp.status();
350        let body_text = resp.text().await?;
351        if !status.is_success() {
352            return Err(Error::Api {
353                status: status.as_u16(),
354                message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
355                    .ok()
356                    .and_then(|r| r.error)
357                    .unwrap_or(body_text.clone()),
358            });
359        }
360        Ok(serde_json::from_str(&body_text)?)
361    }
362
363    /// Update BYOC Infrastructure
364    pub async fn organization_byoc_infrastructure_update(
365        &self,
366        organization_id: &str,
367        byoc_infrastructure_id: &str,
368        body: &ByocInfrastructurePatchRequest,
369    ) -> Result<ApiResponse<ByocConfig>, Error> {
370        let path = format!("/v1/organizations/{organization_id}/byocInfrastructure/{byoc_infrastructure_id}");
371        let mut req = self.request(reqwest::Method::PATCH, &path);
372        req = req.json(body);
373        let resp = req.send().await?;
374        let status = resp.status();
375        let body_text = resp.text().await?;
376        if !status.is_success() {
377            return Err(Error::Api {
378                status: status.as_u16(),
379                message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
380                    .ok()
381                    .and_then(|r| r.error)
382                    .unwrap_or(body_text.clone()),
383            });
384        }
385        Ok(serde_json::from_str(&body_text)?)
386    }
387
388    /// List all invitations
389    pub async fn invitation_get_list(
390        &self,
391        organization_id: &str,
392    ) -> Result<ApiResponse<Vec<Invitation>>, Error> {
393        let path = format!("/v1/organizations/{organization_id}/invitations");
394        let req = self.request(reqwest::Method::GET, &path);
395        let resp = req.send().await?;
396        let status = resp.status();
397        let body_text = resp.text().await?;
398        if !status.is_success() {
399            return Err(Error::Api {
400                status: status.as_u16(),
401                message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
402                    .ok()
403                    .and_then(|r| r.error)
404                    .unwrap_or(body_text.clone()),
405            });
406        }
407        Ok(serde_json::from_str(&body_text)?)
408    }
409
410    /// Create an invitation
411    pub async fn invitation_create(
412        &self,
413        organization_id: &str,
414        body: &InvitationPostRequest,
415    ) -> Result<ApiResponse<Invitation>, Error> {
416        let path = format!("/v1/organizations/{organization_id}/invitations");
417        let mut req = self.request(reqwest::Method::POST, &path);
418        req = req.json(body);
419        let resp = req.send().await?;
420        let status = resp.status();
421        let body_text = resp.text().await?;
422        if !status.is_success() {
423            return Err(Error::Api {
424                status: status.as_u16(),
425                message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
426                    .ok()
427                    .and_then(|r| r.error)
428                    .unwrap_or(body_text.clone()),
429            });
430        }
431        Ok(serde_json::from_str(&body_text)?)
432    }
433
434    /// Get invitation details
435    pub async fn invitation_get(
436        &self,
437        organization_id: &str,
438        invitation_id: &str,
439    ) -> Result<ApiResponse<Invitation>, Error> {
440        let path = format!("/v1/organizations/{organization_id}/invitations/{invitation_id}");
441        let req = self.request(reqwest::Method::GET, &path);
442        let resp = req.send().await?;
443        let status = resp.status();
444        let body_text = resp.text().await?;
445        if !status.is_success() {
446            return Err(Error::Api {
447                status: status.as_u16(),
448                message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
449                    .ok()
450                    .and_then(|r| r.error)
451                    .unwrap_or(body_text.clone()),
452            });
453        }
454        Ok(serde_json::from_str(&body_text)?)
455    }
456
457    /// Delete organization invitation
458    pub async fn invitation_delete(
459        &self,
460        organization_id: &str,
461        invitation_id: &str,
462    ) -> Result<ApiResponse<serde_json::Value>, Error> {
463        let path = format!("/v1/organizations/{organization_id}/invitations/{invitation_id}");
464        let req = self.request(reqwest::Method::DELETE, &path);
465        let resp = req.send().await?;
466        let status = resp.status();
467        let body_text = resp.text().await?;
468        if !status.is_success() {
469            return Err(Error::Api {
470                status: status.as_u16(),
471                message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
472                    .ok()
473                    .and_then(|r| r.error)
474                    .unwrap_or(body_text.clone()),
475            });
476        }
477        Ok(serde_json::from_str(&body_text)?)
478    }
479
480    /// Get list of all keys
481    pub async fn openapi_key_get_list(
482        &self,
483        organization_id: &str,
484    ) -> Result<ApiResponse<Vec<ApiKey>>, Error> {
485        let path = format!("/v1/organizations/{organization_id}/keys");
486        let req = self.request(reqwest::Method::GET, &path);
487        let resp = req.send().await?;
488        let status = resp.status();
489        let body_text = resp.text().await?;
490        if !status.is_success() {
491            return Err(Error::Api {
492                status: status.as_u16(),
493                message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
494                    .ok()
495                    .and_then(|r| r.error)
496                    .unwrap_or(body_text.clone()),
497            });
498        }
499        Ok(serde_json::from_str(&body_text)?)
500    }
501
502    /// Create key
503    pub async fn openapi_key_create(
504        &self,
505        organization_id: &str,
506        body: &ApiKeyPostRequest,
507    ) -> Result<ApiResponse<ApiKeyPostResponse>, Error> {
508        let path = format!("/v1/organizations/{organization_id}/keys");
509        let mut req = self.request(reqwest::Method::POST, &path);
510        req = req.json(body);
511        let resp = req.send().await?;
512        let status = resp.status();
513        let body_text = resp.text().await?;
514        if !status.is_success() {
515            return Err(Error::Api {
516                status: status.as_u16(),
517                message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
518                    .ok()
519                    .and_then(|r| r.error)
520                    .unwrap_or(body_text.clone()),
521            });
522        }
523        Ok(serde_json::from_str(&body_text)?)
524    }
525
526    /// Get key details
527    pub async fn openapi_key_get(
528        &self,
529        organization_id: &str,
530        key_id: &str,
531    ) -> Result<ApiResponse<ApiKey>, Error> {
532        let path = format!("/v1/organizations/{organization_id}/keys/{key_id}");
533        let req = self.request(reqwest::Method::GET, &path);
534        let resp = req.send().await?;
535        let status = resp.status();
536        let body_text = resp.text().await?;
537        if !status.is_success() {
538            return Err(Error::Api {
539                status: status.as_u16(),
540                message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
541                    .ok()
542                    .and_then(|r| r.error)
543                    .unwrap_or(body_text.clone()),
544            });
545        }
546        Ok(serde_json::from_str(&body_text)?)
547    }
548
549    /// Update key
550    pub async fn openapi_key_update(
551        &self,
552        organization_id: &str,
553        key_id: &str,
554        body: &ApiKeyPatchRequest,
555    ) -> Result<ApiResponse<ApiKey>, Error> {
556        let path = format!("/v1/organizations/{organization_id}/keys/{key_id}");
557        let mut req = self.request(reqwest::Method::PATCH, &path);
558        req = req.json(body);
559        let resp = req.send().await?;
560        let status = resp.status();
561        let body_text = resp.text().await?;
562        if !status.is_success() {
563            return Err(Error::Api {
564                status: status.as_u16(),
565                message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
566                    .ok()
567                    .and_then(|r| r.error)
568                    .unwrap_or(body_text.clone()),
569            });
570        }
571        Ok(serde_json::from_str(&body_text)?)
572    }
573
574    /// Delete key
575    pub async fn openapi_key_delete(
576        &self,
577        organization_id: &str,
578        key_id: &str,
579    ) -> Result<ApiResponse<serde_json::Value>, Error> {
580        let path = format!("/v1/organizations/{organization_id}/keys/{key_id}");
581        let req = self.request(reqwest::Method::DELETE, &path);
582        let resp = req.send().await?;
583        let status = resp.status();
584        let body_text = resp.text().await?;
585        if !status.is_success() {
586            return Err(Error::Api {
587                status: status.as_u16(),
588                message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
589                    .ok()
590                    .and_then(|r| r.error)
591                    .unwrap_or(body_text.clone()),
592            });
593        }
594        Ok(serde_json::from_str(&body_text)?)
595    }
596
597    /// List organization members
598    pub async fn member_get_list(
599        &self,
600        organization_id: &str,
601    ) -> Result<ApiResponse<Vec<Member>>, Error> {
602        let path = format!("/v1/organizations/{organization_id}/members");
603        let req = self.request(reqwest::Method::GET, &path);
604        let resp = req.send().await?;
605        let status = resp.status();
606        let body_text = resp.text().await?;
607        if !status.is_success() {
608            return Err(Error::Api {
609                status: status.as_u16(),
610                message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
611                    .ok()
612                    .and_then(|r| r.error)
613                    .unwrap_or(body_text.clone()),
614            });
615        }
616        Ok(serde_json::from_str(&body_text)?)
617    }
618
619    /// Get member details
620    pub async fn member_get(
621        &self,
622        organization_id: &str,
623        user_id: &str,
624    ) -> Result<ApiResponse<Member>, Error> {
625        let path = format!("/v1/organizations/{organization_id}/members/{user_id}");
626        let req = self.request(reqwest::Method::GET, &path);
627        let resp = req.send().await?;
628        let status = resp.status();
629        let body_text = resp.text().await?;
630        if !status.is_success() {
631            return Err(Error::Api {
632                status: status.as_u16(),
633                message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
634                    .ok()
635                    .and_then(|r| r.error)
636                    .unwrap_or(body_text.clone()),
637            });
638        }
639        Ok(serde_json::from_str(&body_text)?)
640    }
641
642    /// Update organization member
643    pub async fn member_update(
644        &self,
645        organization_id: &str,
646        user_id: &str,
647        body: &MemberPatchRequest,
648    ) -> Result<ApiResponse<Member>, Error> {
649        let path = format!("/v1/organizations/{organization_id}/members/{user_id}");
650        let mut req = self.request(reqwest::Method::PATCH, &path);
651        req = req.json(body);
652        let resp = req.send().await?;
653        let status = resp.status();
654        let body_text = resp.text().await?;
655        if !status.is_success() {
656            return Err(Error::Api {
657                status: status.as_u16(),
658                message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
659                    .ok()
660                    .and_then(|r| r.error)
661                    .unwrap_or(body_text.clone()),
662            });
663        }
664        Ok(serde_json::from_str(&body_text)?)
665    }
666
667    /// Remove an organization member
668    pub async fn member_delete(
669        &self,
670        organization_id: &str,
671        user_id: &str,
672    ) -> Result<ApiResponse<serde_json::Value>, Error> {
673        let path = format!("/v1/organizations/{organization_id}/members/{user_id}");
674        let req = self.request(reqwest::Method::DELETE, &path);
675        let resp = req.send().await?;
676        let status = resp.status();
677        let body_text = resp.text().await?;
678        if !status.is_success() {
679            return Err(Error::Api {
680                status: status.as_u16(),
681                message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
682                    .ok()
683                    .and_then(|r| r.error)
684                    .unwrap_or(body_text.clone()),
685            });
686        }
687        Ok(serde_json::from_str(&body_text)?)
688    }
689
690    /// List all available roles for an organization
691    pub async fn organization_roles_get_list(
692        &self,
693        organization_id: &str,
694    ) -> Result<ApiResponse<Vec<RBACRole>>, Error> {
695        let path = format!("/v1/organizations/{organization_id}/roles");
696        let req = self.request(reqwest::Method::GET, &path);
697        let resp = req.send().await?;
698        let status = resp.status();
699        let body_text = resp.text().await?;
700        if !status.is_success() {
701            return Err(Error::Api {
702                status: status.as_u16(),
703                message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
704                    .ok()
705                    .and_then(|r| r.error)
706                    .unwrap_or(body_text.clone()),
707            });
708        }
709        Ok(serde_json::from_str(&body_text)?)
710    }
711
712    /// Create a new role
713    pub async fn organization_role_post(
714        &self,
715        organization_id: &str,
716        body: &RoleCreateRequest,
717    ) -> Result<ApiResponse<RBACRole>, Error> {
718        let path = format!("/v1/organizations/{organization_id}/roles");
719        let mut req = self.request(reqwest::Method::POST, &path);
720        req = req.json(body);
721        let resp = req.send().await?;
722        let status = resp.status();
723        let body_text = resp.text().await?;
724        if !status.is_success() {
725            return Err(Error::Api {
726                status: status.as_u16(),
727                message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
728                    .ok()
729                    .and_then(|r| r.error)
730                    .unwrap_or(body_text.clone()),
731            });
732        }
733        Ok(serde_json::from_str(&body_text)?)
734    }
735
736    /// Get role details
737    pub async fn organization_role_get(
738        &self,
739        organization_id: &str,
740        role_id: &str,
741    ) -> Result<ApiResponse<RBACRole>, Error> {
742        let path = format!("/v1/organizations/{organization_id}/roles/{role_id}");
743        let req = self.request(reqwest::Method::GET, &path);
744        let resp = req.send().await?;
745        let status = resp.status();
746        let body_text = resp.text().await?;
747        if !status.is_success() {
748            return Err(Error::Api {
749                status: status.as_u16(),
750                message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
751                    .ok()
752                    .and_then(|r| r.error)
753                    .unwrap_or(body_text.clone()),
754            });
755        }
756        Ok(serde_json::from_str(&body_text)?)
757    }
758
759    /// Update a role
760    pub async fn organization_role_patch(
761        &self,
762        organization_id: &str,
763        role_id: &str,
764        body: &RoleUpdateRequest,
765    ) -> Result<ApiResponse<RBACRole>, Error> {
766        let path = format!("/v1/organizations/{organization_id}/roles/{role_id}");
767        let mut req = self.request(reqwest::Method::PATCH, &path);
768        req = req.json(body);
769        let resp = req.send().await?;
770        let status = resp.status();
771        let body_text = resp.text().await?;
772        if !status.is_success() {
773            return Err(Error::Api {
774                status: status.as_u16(),
775                message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
776                    .ok()
777                    .and_then(|r| r.error)
778                    .unwrap_or(body_text.clone()),
779            });
780        }
781        Ok(serde_json::from_str(&body_text)?)
782    }
783
784    /// Delete a role
785    pub async fn organization_role_delete(
786        &self,
787        organization_id: &str,
788        role_id: &str,
789    ) -> Result<ApiResponse<serde_json::Value>, Error> {
790        let path = format!("/v1/organizations/{organization_id}/roles/{role_id}");
791        let req = self.request(reqwest::Method::DELETE, &path);
792        let resp = req.send().await?;
793        let status = resp.status();
794        let body_text = resp.text().await?;
795        if !status.is_success() {
796            return Err(Error::Api {
797                status: status.as_u16(),
798                message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
799                    .ok()
800                    .and_then(|r| r.error)
801                    .unwrap_or(body_text.clone()),
802            });
803        }
804        Ok(serde_json::from_str(&body_text)?)
805    }
806
807    /// Create new Postgres service
808    pub async fn postgres_service_create(
809        &self,
810        organization_id: &str,
811        body: &PostgresServicePostRequest,
812    ) -> Result<ApiResponse<PostgresService>, Error> {
813        let path = format!("/v1/organizations/{organization_id}/postgres");
814        let mut req = self.request(reqwest::Method::POST, &path);
815        req = req.json(body);
816        let resp = req.send().await?;
817        let status = resp.status();
818        let body_text = resp.text().await?;
819        if !status.is_success() {
820            return Err(Error::Api {
821                status: status.as_u16(),
822                message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
823                    .ok()
824                    .and_then(|r| r.error)
825                    .unwrap_or(body_text.clone()),
826            });
827        }
828        Ok(serde_json::from_str(&body_text)?)
829    }
830
831    /// List of organization Postgres services
832    pub async fn postgres_service_get_list(
833        &self,
834        organization_id: &str,
835    ) -> Result<ApiResponse<Vec<PostgresServiceListItem>>, Error> {
836        let path = format!("/v1/organizations/{organization_id}/postgres");
837        let req = self.request(reqwest::Method::GET, &path);
838        let resp = req.send().await?;
839        let status = resp.status();
840        let body_text = resp.text().await?;
841        if !status.is_success() {
842            return Err(Error::Api {
843                status: status.as_u16(),
844                message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
845                    .ok()
846                    .and_then(|r| r.error)
847                    .unwrap_or(body_text.clone()),
848            });
849        }
850        Ok(serde_json::from_str(&body_text)?)
851    }
852
853    /// Get PostgreSQL service details
854    pub async fn postgres_service_get(
855        &self,
856        organization_id: &str,
857        postgres_id: &str,
858    ) -> Result<ApiResponse<PostgresService>, Error> {
859        let path = format!("/v1/organizations/{organization_id}/postgres/{postgres_id}");
860        let req = self.request(reqwest::Method::GET, &path);
861        let resp = req.send().await?;
862        let status = resp.status();
863        let body_text = resp.text().await?;
864        if !status.is_success() {
865            return Err(Error::Api {
866                status: status.as_u16(),
867                message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
868                    .ok()
869                    .and_then(|r| r.error)
870                    .unwrap_or(body_text.clone()),
871            });
872        }
873        Ok(serde_json::from_str(&body_text)?)
874    }
875
876    /// Delete a PostgreSQL service
877    pub async fn postgres_service_delete(
878        &self,
879        organization_id: &str,
880        postgres_id: &str,
881    ) -> Result<ApiResponse<serde_json::Value>, Error> {
882        let path = format!("/v1/organizations/{organization_id}/postgres/{postgres_id}");
883        let req = self.request(reqwest::Method::DELETE, &path);
884        let resp = req.send().await?;
885        let status = resp.status();
886        let body_text = resp.text().await?;
887        if !status.is_success() {
888            return Err(Error::Api {
889                status: status.as_u16(),
890                message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
891                    .ok()
892                    .and_then(|r| r.error)
893                    .unwrap_or(body_text.clone()),
894            });
895        }
896        Ok(serde_json::from_str(&body_text)?)
897    }
898
899    /// Update a PostgreSQL service
900    pub async fn postgres_service_patch(
901        &self,
902        organization_id: &str,
903        postgres_id: &str,
904        body: &PostgresServicePatchRequest,
905    ) -> Result<ApiResponse<PostgresService>, Error> {
906        let path = format!("/v1/organizations/{organization_id}/postgres/{postgres_id}");
907        let mut req = self.request(reqwest::Method::PATCH, &path);
908        req = req.json(body);
909        let resp = req.send().await?;
910        let status = resp.status();
911        let body_text = resp.text().await?;
912        if !status.is_success() {
913            return Err(Error::Api {
914                status: status.as_u16(),
915                message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
916                    .ok()
917                    .and_then(|r| r.error)
918                    .unwrap_or(body_text.clone()),
919            });
920        }
921        Ok(serde_json::from_str(&body_text)?)
922    }
923
924    /// Get Postgres CA certs
925    pub async fn postgres_service_certs_get(
926        &self,
927        organization_id: &str,
928        postgres_id: &str,
929    ) -> Result<String, Error> {
930        let path = format!("/v1/organizations/{organization_id}/postgres/{postgres_id}/caCertificates");
931        let req = self.request(reqwest::Method::GET, &path);
932        let resp = req.send().await?;
933        let status = resp.status();
934        let body_text = resp.text().await?;
935        if !status.is_success() {
936            return Err(Error::Api {
937                status: status.as_u16(),
938                message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
939                    .ok()
940                    .and_then(|r| r.error)
941                    .unwrap_or(body_text.clone()),
942            });
943        }
944        Ok(body_text)
945    }
946
947    /// Get PostgreSQL service configuration
948    pub async fn postgres_instance_config_get(
949        &self,
950        organization_id: &str,
951        postgres_id: &str,
952    ) -> Result<ApiResponse<PostgresInstanceConfig>, Error> {
953        let path = format!("/v1/organizations/{organization_id}/postgres/{postgres_id}/config");
954        let req = self.request(reqwest::Method::GET, &path);
955        let resp = req.send().await?;
956        let status = resp.status();
957        let body_text = resp.text().await?;
958        if !status.is_success() {
959            return Err(Error::Api {
960                status: status.as_u16(),
961                message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
962                    .ok()
963                    .and_then(|r| r.error)
964                    .unwrap_or(body_text.clone()),
965            });
966        }
967        Ok(serde_json::from_str(&body_text)?)
968    }
969
970    /// Replace Postgres service configuration
971    pub async fn postgres_instance_config_post(
972        &self,
973        organization_id: &str,
974        postgres_id: &str,
975        body: &PostgresInstanceConfig,
976    ) -> Result<ApiResponse<PostgresInstanceUpdateConfigResponse>, Error> {
977        let path = format!("/v1/organizations/{organization_id}/postgres/{postgres_id}/config");
978        let mut req = self.request(reqwest::Method::POST, &path);
979        req = req.json(body);
980        let resp = req.send().await?;
981        let status = resp.status();
982        let body_text = resp.text().await?;
983        if !status.is_success() {
984            return Err(Error::Api {
985                status: status.as_u16(),
986                message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
987                    .ok()
988                    .and_then(|r| r.error)
989                    .unwrap_or(body_text.clone()),
990            });
991        }
992        Ok(serde_json::from_str(&body_text)?)
993    }
994
995    /// Update Postgres service configuration
996    pub async fn postgres_instance_config_patch(
997        &self,
998        organization_id: &str,
999        postgres_id: &str,
1000        body: &PostgresInstanceConfig,
1001    ) -> Result<ApiResponse<PostgresInstanceUpdateConfigResponse>, Error> {
1002        let path = format!("/v1/organizations/{organization_id}/postgres/{postgres_id}/config");
1003        let mut req = self.request(reqwest::Method::PATCH, &path);
1004        req = req.json(body);
1005        let resp = req.send().await?;
1006        let status = resp.status();
1007        let body_text = resp.text().await?;
1008        if !status.is_success() {
1009            return Err(Error::Api {
1010                status: status.as_u16(),
1011                message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
1012                    .ok()
1013                    .and_then(|r| r.error)
1014                    .unwrap_or(body_text.clone()),
1015            });
1016        }
1017        Ok(serde_json::from_str(&body_text)?)
1018    }
1019
1020    /// Update Postgres superuser password
1021    pub async fn postgres_service_set_password(
1022        &self,
1023        organization_id: &str,
1024        postgres_id: &str,
1025        body: &PostgresServiceSetPassword,
1026    ) -> Result<ApiResponse<PostgresServicePasswordResource>, Error> {
1027        let path = format!("/v1/organizations/{organization_id}/postgres/{postgres_id}/password");
1028        let mut req = self.request(reqwest::Method::PATCH, &path);
1029        req = req.json(body);
1030        let resp = req.send().await?;
1031        let status = resp.status();
1032        let body_text = resp.text().await?;
1033        if !status.is_success() {
1034            return Err(Error::Api {
1035                status: status.as_u16(),
1036                message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
1037                    .ok()
1038                    .and_then(|r| r.error)
1039                    .unwrap_or(body_text.clone()),
1040            });
1041        }
1042        Ok(serde_json::from_str(&body_text)?)
1043    }
1044
1045    /// Create a read replica for a Postgres service
1046    pub async fn postgres_instance_create_read_replica(
1047        &self,
1048        organization_id: &str,
1049        postgres_id: &str,
1050        body: &PostgresServiceReadReplicaRequest,
1051    ) -> Result<ApiResponse<PostgresService>, Error> {
1052        let path = format!("/v1/organizations/{organization_id}/postgres/{postgres_id}/readReplica");
1053        let mut req = self.request(reqwest::Method::POST, &path);
1054        req = req.json(body);
1055        let resp = req.send().await?;
1056        let status = resp.status();
1057        let body_text = resp.text().await?;
1058        if !status.is_success() {
1059            return Err(Error::Api {
1060                status: status.as_u16(),
1061                message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
1062                    .ok()
1063                    .and_then(|r| r.error)
1064                    .unwrap_or(body_text.clone()),
1065            });
1066        }
1067        Ok(serde_json::from_str(&body_text)?)
1068    }
1069
1070    /// Get PostgreSQL service metrics
1071    pub async fn postgres_instance_prometheus_get(
1072        &self,
1073        organization_id: &str,
1074        postgres_id: &str,
1075    ) -> Result<String, Error> {
1076        let path =
1077            format!("/v1/organizations/{organization_id}/postgres/{postgres_id}/prometheus");
1078        let req = self.request(reqwest::Method::GET, &path);
1079        let resp = req.send().await?;
1080        let status = resp.status();
1081        if !status.is_success() {
1082            let body_text = resp.text().await?;
1083            return Err(Error::Api {
1084                status: status.as_u16(),
1085                message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
1086                    .ok()
1087                    .and_then(|r| r.error)
1088                    .unwrap_or(body_text),
1089            });
1090        }
1091        Ok(resp.text().await?)
1092    }
1093
1094    /// Get organization PostgreSQL metrics
1095    pub async fn postgres_org_prometheus_get(
1096        &self,
1097        organization_id: &str,
1098    ) -> Result<String, Error> {
1099        let path = format!("/v1/organizations/{organization_id}/postgres/prometheus");
1100        let req = self.request(reqwest::Method::GET, &path);
1101        let resp = req.send().await?;
1102        let status = resp.status();
1103        if !status.is_success() {
1104            let body_text = resp.text().await?;
1105            return Err(Error::Api {
1106                status: status.as_u16(),
1107                message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
1108                    .ok()
1109                    .and_then(|r| r.error)
1110                    .unwrap_or(body_text),
1111            });
1112        }
1113        Ok(resp.text().await?)
1114    }
1115
1116    /// Restore a Postgres service
1117    pub async fn postgres_instance_restore(
1118        &self,
1119        organization_id: &str,
1120        postgres_id: &str,
1121        body: &PostgresServiceRestoreRequest,
1122    ) -> Result<ApiResponse<PostgresService>, Error> {
1123        let path = format!("/v1/organizations/{organization_id}/postgres/{postgres_id}/restoredService");
1124        let mut req = self.request(reqwest::Method::POST, &path);
1125        req = req.json(body);
1126        let resp = req.send().await?;
1127        let status = resp.status();
1128        let body_text = resp.text().await?;
1129        if !status.is_success() {
1130            return Err(Error::Api {
1131                status: status.as_u16(),
1132                message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
1133                    .ok()
1134                    .and_then(|r| r.error)
1135                    .unwrap_or(body_text.clone()),
1136            });
1137        }
1138        Ok(serde_json::from_str(&body_text)?)
1139    }
1140
1141    /// Update Postgres service state
1142    pub async fn postgres_service_patch_state(
1143        &self,
1144        organization_id: &str,
1145        postgres_id: &str,
1146        body: &PostgresServiceSetState,
1147    ) -> Result<ApiResponse<PostgresService>, Error> {
1148        let path = format!("/v1/organizations/{organization_id}/postgres/{postgres_id}/state");
1149        let mut req = self.request(reqwest::Method::PATCH, &path);
1150        req = req.json(body);
1151        let resp = req.send().await?;
1152        let status = resp.status();
1153        let body_text = resp.text().await?;
1154        if !status.is_success() {
1155            return Err(Error::Api {
1156                status: status.as_u16(),
1157                message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
1158                    .ok()
1159                    .and_then(|r| r.error)
1160                    .unwrap_or(body_text.clone()),
1161            });
1162        }
1163        Ok(serde_json::from_str(&body_text)?)
1164    }
1165
1166    /// Get private endpoint configuration for region within cloud provider for an organization
1167    #[deprecated]
1168    #[allow(deprecated)]
1169    pub async fn organization_private_endpoint_config_get_list(
1170        &self,
1171        organization_id: &str,
1172        cloud_provider: &str,
1173        region_id: &str,
1174    ) -> Result<ApiResponse<OrganizationCloudRegionPrivateEndpointConfig>, Error> {
1175        let path = format!("/v1/organizations/{organization_id}/privateEndpointConfig");
1176        let mut req = self.request(reqwest::Method::GET, &path);
1177        req = req.query(&[("cloud_provider", cloud_provider)]);
1178        req = req.query(&[("region_id", region_id)]);
1179        let resp = req.send().await?;
1180        let status = resp.status();
1181        let body_text = resp.text().await?;
1182        if !status.is_success() {
1183            return Err(Error::Api {
1184                status: status.as_u16(),
1185                message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
1186                    .ok()
1187                    .and_then(|r| r.error)
1188                    .unwrap_or(body_text.clone()),
1189            });
1190        }
1191        Ok(serde_json::from_str(&body_text)?)
1192    }
1193
1194    /// Get organization metrics
1195    pub async fn organization_prometheus_get(
1196        &self,
1197        organization_id: &str,
1198        filtered_metrics: Option<&str>,
1199    ) -> Result<String, Error> {
1200        let path = format!("/v1/organizations/{organization_id}/prometheus");
1201        let mut req = self.request(reqwest::Method::GET, &path);
1202        if let Some(v) = filtered_metrics {
1203            req = req.query(&[("filtered_metrics", v)]);
1204        }
1205        let resp = req.send().await?;
1206        let status = resp.status();
1207        if !status.is_success() {
1208            let body_text = resp.text().await?;
1209            return Err(Error::Api {
1210                status: status.as_u16(),
1211                message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
1212                    .ok()
1213                    .and_then(|r| r.error)
1214                    .unwrap_or(body_text),
1215            });
1216        }
1217        Ok(resp.text().await?)
1218    }
1219
1220    /// List of organization services
1221    pub async fn instance_get_list(
1222        &self,
1223        organization_id: &str,
1224        filters: &[&str],
1225    ) -> Result<ApiResponse<Vec<Service>>, Error> {
1226        let path = format!("/v1/organizations/{organization_id}/services");
1227        let mut req = self.request(reqwest::Method::GET, &path);
1228        for f in filters {
1229            req = req.query(&[("filter", f)]);
1230        }
1231        let resp = req.send().await?;
1232        let status = resp.status();
1233        let body_text = resp.text().await?;
1234        if !status.is_success() {
1235            return Err(Error::Api {
1236                status: status.as_u16(),
1237                message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
1238                    .ok()
1239                    .and_then(|r| r.error)
1240                    .unwrap_or(body_text.clone()),
1241            });
1242        }
1243        Ok(serde_json::from_str(&body_text)?)
1244    }
1245
1246    /// Create new service
1247    pub async fn instance_create(
1248        &self,
1249        organization_id: &str,
1250        body: &ServicePostRequest,
1251    ) -> Result<ApiResponse<ServicePostResponse>, Error> {
1252        let path = format!("/v1/organizations/{organization_id}/services");
1253        let mut req = self.request(reqwest::Method::POST, &path);
1254        req = req.json(body);
1255        let resp = req.send().await?;
1256        let status = resp.status();
1257        let body_text = resp.text().await?;
1258        if !status.is_success() {
1259            return Err(Error::Api {
1260                status: status.as_u16(),
1261                message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
1262                    .ok()
1263                    .and_then(|r| r.error)
1264                    .unwrap_or(body_text.clone()),
1265            });
1266        }
1267        Ok(serde_json::from_str(&body_text)?)
1268    }
1269
1270    /// Get service details
1271    pub async fn instance_get(
1272        &self,
1273        organization_id: &str,
1274        service_id: &str,
1275    ) -> Result<ApiResponse<Service>, Error> {
1276        let path = format!("/v1/organizations/{organization_id}/services/{service_id}");
1277        let req = self.request(reqwest::Method::GET, &path);
1278        let resp = req.send().await?;
1279        let status = resp.status();
1280        let body_text = resp.text().await?;
1281        if !status.is_success() {
1282            return Err(Error::Api {
1283                status: status.as_u16(),
1284                message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
1285                    .ok()
1286                    .and_then(|r| r.error)
1287                    .unwrap_or(body_text.clone()),
1288            });
1289        }
1290        Ok(serde_json::from_str(&body_text)?)
1291    }
1292
1293    /// Update service basic details
1294    pub async fn instance_update(
1295        &self,
1296        organization_id: &str,
1297        service_id: &str,
1298        body: &ServicePatchRequest,
1299    ) -> Result<ApiResponse<Service>, Error> {
1300        let path = format!("/v1/organizations/{organization_id}/services/{service_id}");
1301        let mut req = self.request(reqwest::Method::PATCH, &path);
1302        req = req.json(body);
1303        let resp = req.send().await?;
1304        let status = resp.status();
1305        let body_text = resp.text().await?;
1306        if !status.is_success() {
1307            return Err(Error::Api {
1308                status: status.as_u16(),
1309                message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
1310                    .ok()
1311                    .and_then(|r| r.error)
1312                    .unwrap_or(body_text.clone()),
1313            });
1314        }
1315        Ok(serde_json::from_str(&body_text)?)
1316    }
1317
1318    /// Delete service
1319    pub async fn instance_delete(
1320        &self,
1321        organization_id: &str,
1322        service_id: &str,
1323    ) -> Result<ApiResponse<serde_json::Value>, Error> {
1324        let path = format!("/v1/organizations/{organization_id}/services/{service_id}");
1325        let req = self.request(reqwest::Method::DELETE, &path);
1326        let resp = req.send().await?;
1327        let status = resp.status();
1328        let body_text = resp.text().await?;
1329        if !status.is_success() {
1330            return Err(Error::Api {
1331                status: status.as_u16(),
1332                message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
1333                    .ok()
1334                    .and_then(|r| r.error)
1335                    .unwrap_or(body_text.clone()),
1336            });
1337        }
1338        Ok(serde_json::from_str(&body_text)?)
1339    }
1340
1341    /// Get service backup bucket
1342    pub async fn backup_bucket_get(
1343        &self,
1344        organization_id: &str,
1345        service_id: &str,
1346    ) -> Result<ApiResponse<BackupBucket>, Error> {
1347        let path = format!("/v1/organizations/{organization_id}/services/{service_id}/backupBucket");
1348        let req = self.request(reqwest::Method::GET, &path);
1349        let resp = req.send().await?;
1350        let status = resp.status();
1351        let body_text = resp.text().await?;
1352        if !status.is_success() {
1353            return Err(Error::Api {
1354                status: status.as_u16(),
1355                message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
1356                    .ok()
1357                    .and_then(|r| r.error)
1358                    .unwrap_or(body_text.clone()),
1359            });
1360        }
1361        Ok(serde_json::from_str(&body_text)?)
1362    }
1363
1364    /// Create service backup bucket
1365    pub async fn backup_bucket_create(
1366        &self,
1367        organization_id: &str,
1368        service_id: &str,
1369        body: &BackupBucketPostRequest,
1370    ) -> Result<ApiResponse<BackupBucket>, Error> {
1371        let path = format!("/v1/organizations/{organization_id}/services/{service_id}/backupBucket");
1372        let mut req = self.request(reqwest::Method::POST, &path);
1373        req = req.json(body);
1374        let resp = req.send().await?;
1375        let status = resp.status();
1376        let body_text = resp.text().await?;
1377        if !status.is_success() {
1378            return Err(Error::Api {
1379                status: status.as_u16(),
1380                message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
1381                    .ok()
1382                    .and_then(|r| r.error)
1383                    .unwrap_or(body_text.clone()),
1384            });
1385        }
1386        Ok(serde_json::from_str(&body_text)?)
1387    }
1388
1389    /// Update service backup bucket
1390    pub async fn backup_bucket_update(
1391        &self,
1392        organization_id: &str,
1393        service_id: &str,
1394        body: &BackupBucketPatchRequest,
1395    ) -> Result<ApiResponse<BackupBucket>, Error> {
1396        let path = format!("/v1/organizations/{organization_id}/services/{service_id}/backupBucket");
1397        let mut req = self.request(reqwest::Method::PATCH, &path);
1398        req = req.json(body);
1399        let resp = req.send().await?;
1400        let status = resp.status();
1401        let body_text = resp.text().await?;
1402        if !status.is_success() {
1403            return Err(Error::Api {
1404                status: status.as_u16(),
1405                message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
1406                    .ok()
1407                    .and_then(|r| r.error)
1408                    .unwrap_or(body_text.clone()),
1409            });
1410        }
1411        Ok(serde_json::from_str(&body_text)?)
1412    }
1413
1414    /// Delete service backup bucket
1415    pub async fn backup_bucket_delete(
1416        &self,
1417        organization_id: &str,
1418        service_id: &str,
1419    ) -> Result<ApiResponse<serde_json::Value>, Error> {
1420        let path = format!("/v1/organizations/{organization_id}/services/{service_id}/backupBucket");
1421        let req = self.request(reqwest::Method::DELETE, &path);
1422        let resp = req.send().await?;
1423        let status = resp.status();
1424        let body_text = resp.text().await?;
1425        if !status.is_success() {
1426            return Err(Error::Api {
1427                status: status.as_u16(),
1428                message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
1429                    .ok()
1430                    .and_then(|r| r.error)
1431                    .unwrap_or(body_text.clone()),
1432            });
1433        }
1434        Ok(serde_json::from_str(&body_text)?)
1435    }
1436
1437    /// Get service backup configuration
1438    pub async fn backup_configuration_get(
1439        &self,
1440        organization_id: &str,
1441        service_id: &str,
1442    ) -> Result<ApiResponse<BackupConfiguration>, Error> {
1443        let path = format!("/v1/organizations/{organization_id}/services/{service_id}/backupConfiguration");
1444        let req = self.request(reqwest::Method::GET, &path);
1445        let resp = req.send().await?;
1446        let status = resp.status();
1447        let body_text = resp.text().await?;
1448        if !status.is_success() {
1449            return Err(Error::Api {
1450                status: status.as_u16(),
1451                message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
1452                    .ok()
1453                    .and_then(|r| r.error)
1454                    .unwrap_or(body_text.clone()),
1455            });
1456        }
1457        Ok(serde_json::from_str(&body_text)?)
1458    }
1459
1460    /// Update service backup configuration
1461    pub async fn backup_configuration_update(
1462        &self,
1463        organization_id: &str,
1464        service_id: &str,
1465        body: &BackupConfigurationPatchRequest,
1466    ) -> Result<ApiResponse<BackupConfiguration>, Error> {
1467        let path = format!("/v1/organizations/{organization_id}/services/{service_id}/backupConfiguration");
1468        let mut req = self.request(reqwest::Method::PATCH, &path);
1469        req = req.json(body);
1470        let resp = req.send().await?;
1471        let status = resp.status();
1472        let body_text = resp.text().await?;
1473        if !status.is_success() {
1474            return Err(Error::Api {
1475                status: status.as_u16(),
1476                message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
1477                    .ok()
1478                    .and_then(|r| r.error)
1479                    .unwrap_or(body_text.clone()),
1480            });
1481        }
1482        Ok(serde_json::from_str(&body_text)?)
1483    }
1484
1485    /// List of service backups
1486    pub async fn backup_get_list(
1487        &self,
1488        organization_id: &str,
1489        service_id: &str,
1490    ) -> Result<ApiResponse<Vec<Backup>>, Error> {
1491        let path = format!("/v1/organizations/{organization_id}/services/{service_id}/backups");
1492        let req = self.request(reqwest::Method::GET, &path);
1493        let resp = req.send().await?;
1494        let status = resp.status();
1495        let body_text = resp.text().await?;
1496        if !status.is_success() {
1497            return Err(Error::Api {
1498                status: status.as_u16(),
1499                message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
1500                    .ok()
1501                    .and_then(|r| r.error)
1502                    .unwrap_or(body_text.clone()),
1503            });
1504        }
1505        Ok(serde_json::from_str(&body_text)?)
1506    }
1507
1508    /// Get backup details
1509    pub async fn backup_get(
1510        &self,
1511        organization_id: &str,
1512        service_id: &str,
1513        backup_id: &str,
1514    ) -> Result<ApiResponse<Backup>, Error> {
1515        let path = format!("/v1/organizations/{organization_id}/services/{service_id}/backups/{backup_id}");
1516        let req = self.request(reqwest::Method::GET, &path);
1517        let resp = req.send().await?;
1518        let status = resp.status();
1519        let body_text = resp.text().await?;
1520        if !status.is_success() {
1521            return Err(Error::Api {
1522                status: status.as_u16(),
1523                message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
1524                    .ok()
1525                    .and_then(|r| r.error)
1526                    .unwrap_or(body_text.clone()),
1527            });
1528        }
1529        Ok(serde_json::from_str(&body_text)?)
1530    }
1531
1532    /// List ClickPipes
1533    pub async fn click_pipe_get_list(
1534        &self,
1535        organization_id: &str,
1536        service_id: &str,
1537    ) -> Result<ApiResponse<Vec<ClickPipe>>, Error> {
1538        let path = format!("/v1/organizations/{organization_id}/services/{service_id}/clickpipes");
1539        let req = self.request(reqwest::Method::GET, &path);
1540        let resp = req.send().await?;
1541        let status = resp.status();
1542        let body_text = resp.text().await?;
1543        if !status.is_success() {
1544            return Err(Error::Api {
1545                status: status.as_u16(),
1546                message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
1547                    .ok()
1548                    .and_then(|r| r.error)
1549                    .unwrap_or(body_text.clone()),
1550            });
1551        }
1552        Ok(serde_json::from_str(&body_text)?)
1553    }
1554
1555    /// Create ClickPipe
1556    pub async fn click_pipe_create(
1557        &self,
1558        organization_id: &str,
1559        service_id: &str,
1560        body: &ClickPipePostRequest,
1561    ) -> Result<ApiResponse<ClickPipe>, Error> {
1562        let path = format!("/v1/organizations/{organization_id}/services/{service_id}/clickpipes");
1563        let mut req = self.request(reqwest::Method::POST, &path);
1564        req = req.json(body);
1565        let resp = req.send().await?;
1566        let status = resp.status();
1567        let body_text = resp.text().await?;
1568        if !status.is_success() {
1569            return Err(Error::Api {
1570                status: status.as_u16(),
1571                message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
1572                    .ok()
1573                    .and_then(|r| r.error)
1574                    .unwrap_or(body_text.clone()),
1575            });
1576        }
1577        Ok(serde_json::from_str(&body_text)?)
1578    }
1579
1580    /// Get ClickPipe
1581    pub async fn click_pipe_get(
1582        &self,
1583        organization_id: &str,
1584        service_id: &str,
1585        click_pipe_id: &str,
1586    ) -> Result<ApiResponse<ClickPipe>, Error> {
1587        let path = format!("/v1/organizations/{organization_id}/services/{service_id}/clickpipes/{click_pipe_id}");
1588        let req = self.request(reqwest::Method::GET, &path);
1589        let resp = req.send().await?;
1590        let status = resp.status();
1591        let body_text = resp.text().await?;
1592        if !status.is_success() {
1593            return Err(Error::Api {
1594                status: status.as_u16(),
1595                message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
1596                    .ok()
1597                    .and_then(|r| r.error)
1598                    .unwrap_or(body_text.clone()),
1599            });
1600        }
1601        Ok(serde_json::from_str(&body_text)?)
1602    }
1603
1604    /// Update ClickPipe
1605    pub async fn click_pipe_update(
1606        &self,
1607        organization_id: &str,
1608        service_id: &str,
1609        click_pipe_id: &str,
1610        body: &ClickPipePatchRequest,
1611    ) -> Result<ApiResponse<ClickPipe>, Error> {
1612        let path = format!("/v1/organizations/{organization_id}/services/{service_id}/clickpipes/{click_pipe_id}");
1613        let mut req = self.request(reqwest::Method::PATCH, &path);
1614        req = req.json(body);
1615        let resp = req.send().await?;
1616        let status = resp.status();
1617        let body_text = resp.text().await?;
1618        if !status.is_success() {
1619            return Err(Error::Api {
1620                status: status.as_u16(),
1621                message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
1622                    .ok()
1623                    .and_then(|r| r.error)
1624                    .unwrap_or(body_text.clone()),
1625            });
1626        }
1627        Ok(serde_json::from_str(&body_text)?)
1628    }
1629
1630    /// Delete ClickPipe
1631    pub async fn click_pipe_delete(
1632        &self,
1633        organization_id: &str,
1634        service_id: &str,
1635        click_pipe_id: &str,
1636    ) -> Result<ApiResponse<serde_json::Value>, Error> {
1637        let path = format!("/v1/organizations/{organization_id}/services/{service_id}/clickpipes/{click_pipe_id}");
1638        let req = self.request(reqwest::Method::DELETE, &path);
1639        let resp = req.send().await?;
1640        let status = resp.status();
1641        let body_text = resp.text().await?;
1642        if !status.is_success() {
1643            return Err(Error::Api {
1644                status: status.as_u16(),
1645                message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
1646                    .ok()
1647                    .and_then(|r| r.error)
1648                    .unwrap_or(body_text.clone()),
1649            });
1650        }
1651        Ok(serde_json::from_str(&body_text)?)
1652    }
1653
1654    /// Update ClickPipe scaling
1655    pub async fn click_pipe_scaling_update(
1656        &self,
1657        organization_id: &str,
1658        service_id: &str,
1659        click_pipe_id: &str,
1660        body: &ClickPipeScalingPatchRequest,
1661    ) -> Result<ApiResponse<ClickPipe>, Error> {
1662        let path = format!("/v1/organizations/{organization_id}/services/{service_id}/clickpipes/{click_pipe_id}/scaling");
1663        let mut req = self.request(reqwest::Method::PATCH, &path);
1664        req = req.json(body);
1665        let resp = req.send().await?;
1666        let status = resp.status();
1667        let body_text = resp.text().await?;
1668        if !status.is_success() {
1669            return Err(Error::Api {
1670                status: status.as_u16(),
1671                message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
1672                    .ok()
1673                    .and_then(|r| r.error)
1674                    .unwrap_or(body_text.clone()),
1675            });
1676        }
1677        Ok(serde_json::from_str(&body_text)?)
1678    }
1679
1680    /// Get ClickPipe settings
1681    pub async fn click_pipe_settings_get(
1682        &self,
1683        organization_id: &str,
1684        service_id: &str,
1685        click_pipe_id: &str,
1686    ) -> Result<ApiResponse<ClickPipeSettings>, Error> {
1687        let path = format!("/v1/organizations/{organization_id}/services/{service_id}/clickpipes/{click_pipe_id}/settings");
1688        let req = self.request(reqwest::Method::GET, &path);
1689        let resp = req.send().await?;
1690        let status = resp.status();
1691        let body_text = resp.text().await?;
1692        if !status.is_success() {
1693            return Err(Error::Api {
1694                status: status.as_u16(),
1695                message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
1696                    .ok()
1697                    .and_then(|r| r.error)
1698                    .unwrap_or(body_text.clone()),
1699            });
1700        }
1701        Ok(serde_json::from_str(&body_text)?)
1702    }
1703
1704    /// Update ClickPipe settings
1705    pub async fn click_pipe_settings_update(
1706        &self,
1707        organization_id: &str,
1708        service_id: &str,
1709        click_pipe_id: &str,
1710        body: &ClickPipeSettingsPutRequest,
1711    ) -> Result<ApiResponse<ClickPipeSettings>, Error> {
1712        let path = format!("/v1/organizations/{organization_id}/services/{service_id}/clickpipes/{click_pipe_id}/settings");
1713        let mut req = self.request(reqwest::Method::PUT, &path);
1714        req = req.json(body);
1715        let resp = req.send().await?;
1716        let status = resp.status();
1717        let body_text = resp.text().await?;
1718        if !status.is_success() {
1719            return Err(Error::Api {
1720                status: status.as_u16(),
1721                message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
1722                    .ok()
1723                    .and_then(|r| r.error)
1724                    .unwrap_or(body_text.clone()),
1725            });
1726        }
1727        Ok(serde_json::from_str(&body_text)?)
1728    }
1729
1730    /// Update ClickPipe state
1731    pub async fn click_pipe_state_update(
1732        &self,
1733        organization_id: &str,
1734        service_id: &str,
1735        click_pipe_id: &str,
1736        body: &ClickPipeStatePatchRequest,
1737    ) -> Result<ApiResponse<ClickPipe>, Error> {
1738        let path = format!("/v1/organizations/{organization_id}/services/{service_id}/clickpipes/{click_pipe_id}/state");
1739        let mut req = self.request(reqwest::Method::PATCH, &path);
1740        req = req.json(body);
1741        let resp = req.send().await?;
1742        let status = resp.status();
1743        let body_text = resp.text().await?;
1744        if !status.is_success() {
1745            return Err(Error::Api {
1746                status: status.as_u16(),
1747                message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
1748                    .ok()
1749                    .and_then(|r| r.error)
1750                    .unwrap_or(body_text.clone()),
1751            });
1752        }
1753        Ok(serde_json::from_str(&body_text)?)
1754    }
1755
1756    /// Get CDC ClickPipes scaling
1757    pub async fn click_pipe_cdc_scaling_get(
1758        &self,
1759        organization_id: &str,
1760        service_id: &str,
1761    ) -> Result<ApiResponse<ClickPipesCdcScaling>, Error> {
1762        let path = format!("/v1/organizations/{organization_id}/services/{service_id}/clickpipesCdcScaling");
1763        let req = self.request(reqwest::Method::GET, &path);
1764        let resp = req.send().await?;
1765        let status = resp.status();
1766        let body_text = resp.text().await?;
1767        if !status.is_success() {
1768            return Err(Error::Api {
1769                status: status.as_u16(),
1770                message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
1771                    .ok()
1772                    .and_then(|r| r.error)
1773                    .unwrap_or(body_text.clone()),
1774            });
1775        }
1776        Ok(serde_json::from_str(&body_text)?)
1777    }
1778
1779    /// Update CDC ClickPipes scaling
1780    pub async fn click_pipe_cdc_scaling_update(
1781        &self,
1782        organization_id: &str,
1783        service_id: &str,
1784        body: &ClickPipesCdcScalingPatchRequest,
1785    ) -> Result<ApiResponse<ClickPipesCdcScaling>, Error> {
1786        let path = format!("/v1/organizations/{organization_id}/services/{service_id}/clickpipesCdcScaling");
1787        let mut req = self.request(reqwest::Method::PATCH, &path);
1788        req = req.json(body);
1789        let resp = req.send().await?;
1790        let status = resp.status();
1791        let body_text = resp.text().await?;
1792        if !status.is_success() {
1793            return Err(Error::Api {
1794                status: status.as_u16(),
1795                message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
1796                    .ok()
1797                    .and_then(|r| r.error)
1798                    .unwrap_or(body_text.clone()),
1799            });
1800        }
1801        Ok(serde_json::from_str(&body_text)?)
1802    }
1803
1804    /// List reverse private endpoints
1805    pub async fn click_pipe_reverse_private_endpoint_get_list(
1806        &self,
1807        organization_id: &str,
1808        service_id: &str,
1809    ) -> Result<ApiResponse<Vec<ReversePrivateEndpoint>>, Error> {
1810        let path = format!("/v1/organizations/{organization_id}/services/{service_id}/clickpipesReversePrivateEndpoints");
1811        let req = self.request(reqwest::Method::GET, &path);
1812        let resp = req.send().await?;
1813        let status = resp.status();
1814        let body_text = resp.text().await?;
1815        if !status.is_success() {
1816            return Err(Error::Api {
1817                status: status.as_u16(),
1818                message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
1819                    .ok()
1820                    .and_then(|r| r.error)
1821                    .unwrap_or(body_text.clone()),
1822            });
1823        }
1824        Ok(serde_json::from_str(&body_text)?)
1825    }
1826
1827    /// Create reverse private endpoint
1828    pub async fn click_pipe_reverse_private_endpoint_create(
1829        &self,
1830        organization_id: &str,
1831        service_id: &str,
1832        body: &CreateReversePrivateEndpoint,
1833    ) -> Result<ApiResponse<ReversePrivateEndpoint>, Error> {
1834        let path = format!("/v1/organizations/{organization_id}/services/{service_id}/clickpipesReversePrivateEndpoints");
1835        let mut req = self.request(reqwest::Method::POST, &path);
1836        req = req.json(body);
1837        let resp = req.send().await?;
1838        let status = resp.status();
1839        let body_text = resp.text().await?;
1840        if !status.is_success() {
1841            return Err(Error::Api {
1842                status: status.as_u16(),
1843                message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
1844                    .ok()
1845                    .and_then(|r| r.error)
1846                    .unwrap_or(body_text.clone()),
1847            });
1848        }
1849        Ok(serde_json::from_str(&body_text)?)
1850    }
1851
1852    /// Get reverse private endpoint
1853    pub async fn click_pipe_reverse_private_endpoint_get(
1854        &self,
1855        organization_id: &str,
1856        service_id: &str,
1857        reverse_private_endpoint_id: &str,
1858    ) -> Result<ApiResponse<ReversePrivateEndpoint>, Error> {
1859        let path = format!("/v1/organizations/{organization_id}/services/{service_id}/clickpipesReversePrivateEndpoints/{reverse_private_endpoint_id}");
1860        let req = self.request(reqwest::Method::GET, &path);
1861        let resp = req.send().await?;
1862        let status = resp.status();
1863        let body_text = resp.text().await?;
1864        if !status.is_success() {
1865            return Err(Error::Api {
1866                status: status.as_u16(),
1867                message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
1868                    .ok()
1869                    .and_then(|r| r.error)
1870                    .unwrap_or(body_text.clone()),
1871            });
1872        }
1873        Ok(serde_json::from_str(&body_text)?)
1874    }
1875
1876    /// Delete reverse private endpoint
1877    pub async fn click_pipe_reverse_private_endpoint_delete(
1878        &self,
1879        organization_id: &str,
1880        service_id: &str,
1881        reverse_private_endpoint_id: &str,
1882    ) -> Result<ApiResponse<serde_json::Value>, Error> {
1883        let path = format!("/v1/organizations/{organization_id}/services/{service_id}/clickpipesReversePrivateEndpoints/{reverse_private_endpoint_id}");
1884        let req = self.request(reqwest::Method::DELETE, &path);
1885        let resp = req.send().await?;
1886        let status = resp.status();
1887        let body_text = resp.text().await?;
1888        if !status.is_success() {
1889            return Err(Error::Api {
1890                status: status.as_u16(),
1891                message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
1892                    .ok()
1893                    .and_then(|r| r.error)
1894                    .unwrap_or(body_text.clone()),
1895            });
1896        }
1897        Ok(serde_json::from_str(&body_text)?)
1898    }
1899
1900    /// ClickStack: List Alerts
1901    pub async fn click_stack_list_alerts(
1902        &self,
1903        organization_id: &str,
1904        service_id: &str,
1905    ) -> Result<ApiResponse<Vec<ClickStackAlertResponse>>, Error> {
1906        let path = format!("/v1/organizations/{organization_id}/services/{service_id}/clickstack/alerts");
1907        let req = self.request(reqwest::Method::GET, &path);
1908        let resp = req.send().await?;
1909        let status = resp.status();
1910        let body_text = resp.text().await?;
1911        if !status.is_success() {
1912            return Err(Error::Api {
1913                status: status.as_u16(),
1914                message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
1915                    .ok()
1916                    .and_then(|r| r.error)
1917                    .unwrap_or(body_text.clone()),
1918            });
1919        }
1920        Ok(serde_json::from_str(&body_text)?)
1921    }
1922
1923    /// ClickStack: Create Alert
1924    pub async fn click_stack_create_alert(
1925        &self,
1926        organization_id: &str,
1927        service_id: &str,
1928        body: &ClickStackCreateAlertRequest,
1929    ) -> Result<ApiResponse<ClickStackAlertResponse>, Error> {
1930        let path = format!("/v1/organizations/{organization_id}/services/{service_id}/clickstack/alerts");
1931        let mut req = self.request(reqwest::Method::POST, &path);
1932        req = req.json(body);
1933        let resp = req.send().await?;
1934        let status = resp.status();
1935        let body_text = resp.text().await?;
1936        if !status.is_success() {
1937            return Err(Error::Api {
1938                status: status.as_u16(),
1939                message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
1940                    .ok()
1941                    .and_then(|r| r.error)
1942                    .unwrap_or(body_text.clone()),
1943            });
1944        }
1945        Ok(serde_json::from_str(&body_text)?)
1946    }
1947
1948    /// ClickStack: Get Alert
1949    pub async fn click_stack_get_alert(
1950        &self,
1951        organization_id: &str,
1952        service_id: &str,
1953        click_stack_alert_id: &str,
1954    ) -> Result<ApiResponse<ClickStackAlertResponse>, Error> {
1955        let path = format!("/v1/organizations/{organization_id}/services/{service_id}/clickstack/alerts/{click_stack_alert_id}");
1956        let req = self.request(reqwest::Method::GET, &path);
1957        let resp = req.send().await?;
1958        let status = resp.status();
1959        let body_text = resp.text().await?;
1960        if !status.is_success() {
1961            return Err(Error::Api {
1962                status: status.as_u16(),
1963                message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
1964                    .ok()
1965                    .and_then(|r| r.error)
1966                    .unwrap_or(body_text.clone()),
1967            });
1968        }
1969        Ok(serde_json::from_str(&body_text)?)
1970    }
1971
1972    /// ClickStack: Update Alert
1973    pub async fn click_stack_update_alert(
1974        &self,
1975        organization_id: &str,
1976        service_id: &str,
1977        click_stack_alert_id: &str,
1978        body: &ClickStackUpdateAlertRequest,
1979    ) -> Result<ApiResponse<ClickStackAlertResponse>, Error> {
1980        let path = format!("/v1/organizations/{organization_id}/services/{service_id}/clickstack/alerts/{click_stack_alert_id}");
1981        let mut req = self.request(reqwest::Method::PUT, &path);
1982        req = req.json(body);
1983        let resp = req.send().await?;
1984        let status = resp.status();
1985        let body_text = resp.text().await?;
1986        if !status.is_success() {
1987            return Err(Error::Api {
1988                status: status.as_u16(),
1989                message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
1990                    .ok()
1991                    .and_then(|r| r.error)
1992                    .unwrap_or(body_text.clone()),
1993            });
1994        }
1995        Ok(serde_json::from_str(&body_text)?)
1996    }
1997
1998    /// ClickStack: Delete Alert
1999    pub async fn click_stack_delete_alert(
2000        &self,
2001        organization_id: &str,
2002        service_id: &str,
2003        click_stack_alert_id: &str,
2004    ) -> Result<ApiResponse<serde_json::Value>, Error> {
2005        let path = format!("/v1/organizations/{organization_id}/services/{service_id}/clickstack/alerts/{click_stack_alert_id}");
2006        let req = self.request(reqwest::Method::DELETE, &path);
2007        let resp = req.send().await?;
2008        let status = resp.status();
2009        let body_text = resp.text().await?;
2010        if !status.is_success() {
2011            return Err(Error::Api {
2012                status: status.as_u16(),
2013                message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
2014                    .ok()
2015                    .and_then(|r| r.error)
2016                    .unwrap_or(body_text.clone()),
2017            });
2018        }
2019        Ok(serde_json::from_str(&body_text)?)
2020    }
2021
2022    /// ClickStack: List Dashboards
2023    pub async fn click_stack_list_dashboards(
2024        &self,
2025        organization_id: &str,
2026        service_id: &str,
2027    ) -> Result<ApiResponse<Vec<ClickStackDashboardResponse>>, Error> {
2028        let path = format!("/v1/organizations/{organization_id}/services/{service_id}/clickstack/dashboards");
2029        let req = self.request(reqwest::Method::GET, &path);
2030        let resp = req.send().await?;
2031        let status = resp.status();
2032        let body_text = resp.text().await?;
2033        if !status.is_success() {
2034            return Err(Error::Api {
2035                status: status.as_u16(),
2036                message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
2037                    .ok()
2038                    .and_then(|r| r.error)
2039                    .unwrap_or(body_text.clone()),
2040            });
2041        }
2042        Ok(serde_json::from_str(&body_text)?)
2043    }
2044
2045    /// ClickStack: Create Dashboard
2046    pub async fn click_stack_create_dashboard(
2047        &self,
2048        organization_id: &str,
2049        service_id: &str,
2050        body: &ClickStackCreateDashboardRequest,
2051    ) -> Result<ApiResponse<ClickStackDashboardResponse>, Error> {
2052        let path = format!("/v1/organizations/{organization_id}/services/{service_id}/clickstack/dashboards");
2053        let mut req = self.request(reqwest::Method::POST, &path);
2054        req = req.json(body);
2055        let resp = req.send().await?;
2056        let status = resp.status();
2057        let body_text = resp.text().await?;
2058        if !status.is_success() {
2059            return Err(Error::Api {
2060                status: status.as_u16(),
2061                message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
2062                    .ok()
2063                    .and_then(|r| r.error)
2064                    .unwrap_or(body_text.clone()),
2065            });
2066        }
2067        Ok(serde_json::from_str(&body_text)?)
2068    }
2069
2070    /// ClickStack: Get Dashboard
2071    pub async fn click_stack_get_dashboard(
2072        &self,
2073        organization_id: &str,
2074        service_id: &str,
2075        click_stack_dashboard_id: &str,
2076    ) -> Result<ApiResponse<ClickStackDashboardResponse>, Error> {
2077        let path = format!("/v1/organizations/{organization_id}/services/{service_id}/clickstack/dashboards/{click_stack_dashboard_id}");
2078        let req = self.request(reqwest::Method::GET, &path);
2079        let resp = req.send().await?;
2080        let status = resp.status();
2081        let body_text = resp.text().await?;
2082        if !status.is_success() {
2083            return Err(Error::Api {
2084                status: status.as_u16(),
2085                message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
2086                    .ok()
2087                    .and_then(|r| r.error)
2088                    .unwrap_or(body_text.clone()),
2089            });
2090        }
2091        Ok(serde_json::from_str(&body_text)?)
2092    }
2093
2094    /// ClickStack: Update Dashboard
2095    pub async fn click_stack_update_dashboard(
2096        &self,
2097        organization_id: &str,
2098        service_id: &str,
2099        click_stack_dashboard_id: &str,
2100        body: &ClickStackUpdateDashboardRequest,
2101    ) -> Result<ApiResponse<ClickStackDashboardResponse>, Error> {
2102        let path = format!("/v1/organizations/{organization_id}/services/{service_id}/clickstack/dashboards/{click_stack_dashboard_id}");
2103        let mut req = self.request(reqwest::Method::PUT, &path);
2104        req = req.json(body);
2105        let resp = req.send().await?;
2106        let status = resp.status();
2107        let body_text = resp.text().await?;
2108        if !status.is_success() {
2109            return Err(Error::Api {
2110                status: status.as_u16(),
2111                message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
2112                    .ok()
2113                    .and_then(|r| r.error)
2114                    .unwrap_or(body_text.clone()),
2115            });
2116        }
2117        Ok(serde_json::from_str(&body_text)?)
2118    }
2119
2120    /// ClickStack: Delete Dashboard
2121    pub async fn click_stack_delete_dashboard(
2122        &self,
2123        organization_id: &str,
2124        service_id: &str,
2125        click_stack_dashboard_id: &str,
2126    ) -> Result<ApiResponse<serde_json::Value>, Error> {
2127        let path = format!("/v1/organizations/{organization_id}/services/{service_id}/clickstack/dashboards/{click_stack_dashboard_id}");
2128        let req = self.request(reqwest::Method::DELETE, &path);
2129        let resp = req.send().await?;
2130        let status = resp.status();
2131        let body_text = resp.text().await?;
2132        if !status.is_success() {
2133            return Err(Error::Api {
2134                status: status.as_u16(),
2135                message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
2136                    .ok()
2137                    .and_then(|r| r.error)
2138                    .unwrap_or(body_text.clone()),
2139            });
2140        }
2141        Ok(serde_json::from_str(&body_text)?)
2142    }
2143
2144    /// ClickStack: List Sources
2145    pub async fn click_stack_list_sources(
2146        &self,
2147        organization_id: &str,
2148        service_id: &str,
2149    ) -> Result<ApiResponse<Vec<ClickStackSource>>, Error> {
2150        let path = format!("/v1/organizations/{organization_id}/services/{service_id}/clickstack/sources");
2151        let req = self.request(reqwest::Method::GET, &path);
2152        let resp = req.send().await?;
2153        let status = resp.status();
2154        let body_text = resp.text().await?;
2155        if !status.is_success() {
2156            return Err(Error::Api {
2157                status: status.as_u16(),
2158                message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
2159                    .ok()
2160                    .and_then(|r| r.error)
2161                    .unwrap_or(body_text.clone()),
2162            });
2163        }
2164        Ok(serde_json::from_str(&body_text)?)
2165    }
2166
2167    /// ClickStack: List Webhooks
2168    pub async fn click_stack_list_webhooks(
2169        &self,
2170        organization_id: &str,
2171        service_id: &str,
2172    ) -> Result<ApiResponse<Vec<ClickStackWebhook>>, Error> {
2173        let path = format!("/v1/organizations/{organization_id}/services/{service_id}/clickstack/webhooks");
2174        let req = self.request(reqwest::Method::GET, &path);
2175        let resp = req.send().await?;
2176        let status = resp.status();
2177        let body_text = resp.text().await?;
2178        if !status.is_success() {
2179            return Err(Error::Api {
2180                status: status.as_u16(),
2181                message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
2182                    .ok()
2183                    .and_then(|r| r.error)
2184                    .unwrap_or(body_text.clone()),
2185            });
2186        }
2187        Ok(serde_json::from_str(&body_text)?)
2188    }
2189
2190    /// Update service password
2191    pub async fn instance_password_update(
2192        &self,
2193        organization_id: &str,
2194        service_id: &str,
2195        body: &ServicePasswordPatchRequest,
2196    ) -> Result<ApiResponse<ServicePasswordPatchResponse>, Error> {
2197        let path = format!("/v1/organizations/{organization_id}/services/{service_id}/password");
2198        let mut req = self.request(reqwest::Method::PATCH, &path);
2199        req = req.json(body);
2200        let resp = req.send().await?;
2201        let status = resp.status();
2202        let body_text = resp.text().await?;
2203        if !status.is_success() {
2204            return Err(Error::Api {
2205                status: status.as_u16(),
2206                message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
2207                    .ok()
2208                    .and_then(|r| r.error)
2209                    .unwrap_or(body_text.clone()),
2210            });
2211        }
2212        Ok(serde_json::from_str(&body_text)?)
2213    }
2214
2215    /// Create a private endpoint
2216    pub async fn instance_private_endpoint_create(
2217        &self,
2218        organization_id: &str,
2219        service_id: &str,
2220        body: &ServicPrivateEndpointePostRequest,
2221    ) -> Result<ApiResponse<InstancePrivateEndpoint>, Error> {
2222        let path = format!("/v1/organizations/{organization_id}/services/{service_id}/privateEndpoint");
2223        let mut req = self.request(reqwest::Method::POST, &path);
2224        req = req.json(body);
2225        let resp = req.send().await?;
2226        let status = resp.status();
2227        let body_text = resp.text().await?;
2228        if !status.is_success() {
2229            return Err(Error::Api {
2230                status: status.as_u16(),
2231                message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
2232                    .ok()
2233                    .and_then(|r| r.error)
2234                    .unwrap_or(body_text.clone()),
2235            });
2236        }
2237        Ok(serde_json::from_str(&body_text)?)
2238    }
2239
2240    /// Get private endpoint configuration
2241    pub async fn instance_private_endpoint_config_get(
2242        &self,
2243        organization_id: &str,
2244        service_id: &str,
2245    ) -> Result<ApiResponse<PrivateEndpointConfig>, Error> {
2246        let path = format!("/v1/organizations/{organization_id}/services/{service_id}/privateEndpointConfig");
2247        let req = self.request(reqwest::Method::GET, &path);
2248        let resp = req.send().await?;
2249        let status = resp.status();
2250        let body_text = resp.text().await?;
2251        if !status.is_success() {
2252            return Err(Error::Api {
2253                status: status.as_u16(),
2254                message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
2255                    .ok()
2256                    .and_then(|r| r.error)
2257                    .unwrap_or(body_text.clone()),
2258            });
2259        }
2260        Ok(serde_json::from_str(&body_text)?)
2261    }
2262
2263    /// Get service metrics
2264    pub async fn instance_prometheus_get(
2265        &self,
2266        organization_id: &str,
2267        service_id: &str,
2268        filtered_metrics: Option<&str>,
2269    ) -> Result<String, Error> {
2270        let path = format!("/v1/organizations/{organization_id}/services/{service_id}/prometheus");
2271        let mut req = self.request(reqwest::Method::GET, &path);
2272        if let Some(v) = filtered_metrics {
2273            req = req.query(&[("filtered_metrics", v)]);
2274        }
2275        let resp = req.send().await?;
2276        let status = resp.status();
2277        if !status.is_success() {
2278            let body_text = resp.text().await?;
2279            return Err(Error::Api {
2280                status: status.as_u16(),
2281                message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
2282                    .ok()
2283                    .and_then(|r| r.error)
2284                    .unwrap_or(body_text),
2285            });
2286        }
2287        Ok(resp.text().await?)
2288    }
2289
2290    /// Update service auto scaling settings
2291    pub async fn instance_replica_scaling_update(
2292        &self,
2293        organization_id: &str,
2294        service_id: &str,
2295        body: &ServiceReplicaScalingPatchRequest,
2296    ) -> Result<ApiResponse<ServiceScalingPatchResponse>, Error> {
2297        let path = format!("/v1/organizations/{organization_id}/services/{service_id}/replicaScaling");
2298        let mut req = self.request(reqwest::Method::PATCH, &path);
2299        req = req.json(body);
2300        let resp = req.send().await?;
2301        let status = resp.status();
2302        let body_text = resp.text().await?;
2303        if !status.is_success() {
2304            return Err(Error::Api {
2305                status: status.as_u16(),
2306                message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
2307                    .ok()
2308                    .and_then(|r| r.error)
2309                    .unwrap_or(body_text.clone()),
2310            });
2311        }
2312        Ok(serde_json::from_str(&body_text)?)
2313    }
2314
2315    /// Update service auto scaling settings
2316    #[deprecated]
2317    #[allow(deprecated)]
2318    pub async fn instance_scaling_update(
2319        &self,
2320        organization_id: &str,
2321        service_id: &str,
2322        body: &ServiceScalingPatchRequest,
2323    ) -> Result<ApiResponse<Service>, Error> {
2324        let path = format!("/v1/organizations/{organization_id}/services/{service_id}/scaling");
2325        let mut req = self.request(reqwest::Method::PATCH, &path);
2326        req = req.json(body);
2327        let resp = req.send().await?;
2328        let status = resp.status();
2329        let body_text = resp.text().await?;
2330        if !status.is_success() {
2331            return Err(Error::Api {
2332                status: status.as_u16(),
2333                message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
2334                    .ok()
2335                    .and_then(|r| r.error)
2336                    .unwrap_or(body_text.clone()),
2337            });
2338        }
2339        Ok(serde_json::from_str(&body_text)?)
2340    }
2341
2342    /// Get service autoscaling schedule
2343    pub async fn scaling_schedule_get(
2344        &self,
2345        organization_id: &str,
2346        service_id: &str,
2347    ) -> Result<ApiResponse<ScalingSchedule>, Error> {
2348        let path = format!("/v1/organizations/{organization_id}/services/{service_id}/scalingSchedule");
2349        let req = self.request(reqwest::Method::GET, &path);
2350        let resp = req.send().await?;
2351        let status = resp.status();
2352        let body_text = resp.text().await?;
2353        if !status.is_success() {
2354            return Err(Error::Api {
2355                status: status.as_u16(),
2356                message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
2357                    .ok()
2358                    .and_then(|r| r.error)
2359                    .unwrap_or(body_text.clone()),
2360            });
2361        }
2362        Ok(serde_json::from_str(&body_text)?)
2363    }
2364
2365    /// Create or replace service autoscaling schedule
2366    pub async fn scaling_schedule_upsert(
2367        &self,
2368        organization_id: &str,
2369        service_id: &str,
2370        body: &ScalingSchedulePostRequest,
2371    ) -> Result<ApiResponse<ScalingSchedule>, Error> {
2372        let path = format!("/v1/organizations/{organization_id}/services/{service_id}/scalingSchedule");
2373        let mut req = self.request(reqwest::Method::POST, &path);
2374        req = req.json(body);
2375        let resp = req.send().await?;
2376        let status = resp.status();
2377        let body_text = resp.text().await?;
2378        if !status.is_success() {
2379            return Err(Error::Api {
2380                status: status.as_u16(),
2381                message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
2382                    .ok()
2383                    .and_then(|r| r.error)
2384                    .unwrap_or(body_text.clone()),
2385            });
2386        }
2387        Ok(serde_json::from_str(&body_text)?)
2388    }
2389
2390    /// Delete service scheduled scaling
2391    pub async fn scaling_schedule_delete(
2392        &self,
2393        organization_id: &str,
2394        service_id: &str,
2395    ) -> Result<ApiResponse<serde_json::Value>, Error> {
2396        let path = format!("/v1/organizations/{organization_id}/services/{service_id}/scalingSchedule");
2397        let req = self.request(reqwest::Method::DELETE, &path);
2398        let resp = req.send().await?;
2399        let status = resp.status();
2400        let body_text = resp.text().await?;
2401        if !status.is_success() {
2402            return Err(Error::Api {
2403                status: status.as_u16(),
2404                message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
2405                    .ok()
2406                    .and_then(|r| r.error)
2407                    .unwrap_or(body_text.clone()),
2408            });
2409        }
2410        Ok(serde_json::from_str(&body_text)?)
2411    }
2412
2413    /// Get service upgrade window
2414    pub async fn upgrade_window_get(
2415        &self,
2416        organization_id: &str,
2417        service_id: &str,
2418    ) -> Result<ApiResponse<UpgradeWindow>, Error> {
2419        let path = format!("/v1/organizations/{organization_id}/services/{service_id}/upgradeWindow");
2420        let req = self.request(reqwest::Method::GET, &path);
2421        let resp = req.send().await?;
2422        let status = resp.status();
2423        let body_text = resp.text().await?;
2424        if !status.is_success() {
2425            return Err(Error::Api {
2426                status: status.as_u16(),
2427                message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
2428                    .ok()
2429                    .and_then(|r| r.error)
2430                    .unwrap_or(body_text.clone()),
2431            });
2432        }
2433        Ok(serde_json::from_str(&body_text)?)
2434    }
2435
2436    /// Set service upgrade window
2437    pub async fn upgrade_window_update(
2438        &self,
2439        organization_id: &str,
2440        service_id: &str,
2441        body: &UpgradeWindowPutRequest,
2442    ) -> Result<ApiResponse<UpgradeWindow>, Error> {
2443        let path = format!("/v1/organizations/{organization_id}/services/{service_id}/upgradeWindow");
2444        let mut req = self.request(reqwest::Method::PUT, &path);
2445        req = req.json(body);
2446        let resp = req.send().await?;
2447        let status = resp.status();
2448        let body_text = resp.text().await?;
2449        if !status.is_success() {
2450            return Err(Error::Api {
2451                status: status.as_u16(),
2452                message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
2453                    .ok()
2454                    .and_then(|r| r.error)
2455                    .unwrap_or(body_text.clone()),
2456            });
2457        }
2458        Ok(serde_json::from_str(&body_text)?)
2459    }
2460
2461    /// Delete service upgrade window
2462    pub async fn upgrade_window_delete(
2463        &self,
2464        organization_id: &str,
2465        service_id: &str,
2466    ) -> Result<ApiResponse<serde_json::Value>, Error> {
2467        let path = format!("/v1/organizations/{organization_id}/services/{service_id}/upgradeWindow");
2468        let req = self.request(reqwest::Method::DELETE, &path);
2469        let resp = req.send().await?;
2470        let status = resp.status();
2471        let body_text = resp.text().await?;
2472        if !status.is_success() {
2473            return Err(Error::Api {
2474                status: status.as_u16(),
2475                message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
2476                    .ok()
2477                    .and_then(|r| r.error)
2478                    .unwrap_or(body_text.clone()),
2479            });
2480        }
2481        Ok(serde_json::from_str(&body_text)?)
2482    }
2483
2484    /// Get the service query endpoint for a given instance
2485    pub async fn instance_query_endpoint_get(
2486        &self,
2487        organization_id: &str,
2488        service_id: &str,
2489    ) -> Result<ApiResponse<ServiceQueryAPIEndpoint>, Error> {
2490        let path = format!("/v1/organizations/{organization_id}/services/{service_id}/serviceQueryEndpoint");
2491        let req = self.request(reqwest::Method::GET, &path);
2492        let resp = req.send().await?;
2493        let status = resp.status();
2494        let body_text = resp.text().await?;
2495        if !status.is_success() {
2496            return Err(Error::Api {
2497                status: status.as_u16(),
2498                message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
2499                    .ok()
2500                    .and_then(|r| r.error)
2501                    .unwrap_or(body_text.clone()),
2502            });
2503        }
2504        Ok(serde_json::from_str(&body_text)?)
2505    }
2506
2507    /// Delete the service query endpoint for a given instance
2508    pub async fn instance_query_endpoint_delete(
2509        &self,
2510        organization_id: &str,
2511        service_id: &str,
2512    ) -> Result<ApiResponse<serde_json::Value>, Error> {
2513        let path = format!("/v1/organizations/{organization_id}/services/{service_id}/serviceQueryEndpoint");
2514        let req = self.request(reqwest::Method::DELETE, &path);
2515        let resp = req.send().await?;
2516        let status = resp.status();
2517        let body_text = resp.text().await?;
2518        if !status.is_success() {
2519            return Err(Error::Api {
2520                status: status.as_u16(),
2521                message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
2522                    .ok()
2523                    .and_then(|r| r.error)
2524                    .unwrap_or(body_text.clone()),
2525            });
2526        }
2527        Ok(serde_json::from_str(&body_text)?)
2528    }
2529
2530    /// Upsert the service query endpoint for a given instance
2531    pub async fn instance_query_endpoint_upsert(
2532        &self,
2533        organization_id: &str,
2534        service_id: &str,
2535        body: &InstanceServiceQueryApiEndpointsPostRequest,
2536    ) -> Result<ApiResponse<ServiceQueryAPIEndpoint>, Error> {
2537        let path = format!("/v1/organizations/{organization_id}/services/{service_id}/serviceQueryEndpoint");
2538        let mut req = self.request(reqwest::Method::POST, &path);
2539        req = req.json(body);
2540        let resp = req.send().await?;
2541        let status = resp.status();
2542        let body_text = resp.text().await?;
2543        if !status.is_success() {
2544            return Err(Error::Api {
2545                status: status.as_u16(),
2546                message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
2547                    .ok()
2548                    .and_then(|r| r.error)
2549                    .unwrap_or(body_text.clone()),
2550            });
2551        }
2552        Ok(serde_json::from_str(&body_text)?)
2553    }
2554
2555    /// Update service state
2556    pub async fn instance_state_update(
2557        &self,
2558        organization_id: &str,
2559        service_id: &str,
2560        body: &ServiceStatePatchRequest,
2561    ) -> Result<ApiResponse<Service>, Error> {
2562        let path = format!("/v1/organizations/{organization_id}/services/{service_id}/state");
2563        let mut req = self.request(reqwest::Method::PATCH, &path);
2564        req = req.json(body);
2565        let resp = req.send().await?;
2566        let status = resp.status();
2567        let body_text = resp.text().await?;
2568        if !status.is_success() {
2569            return Err(Error::Api {
2570                status: status.as_u16(),
2571                message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
2572                    .ok()
2573                    .and_then(|r| r.error)
2574                    .unwrap_or(body_text.clone()),
2575            });
2576        }
2577        Ok(serde_json::from_str(&body_text)?)
2578    }
2579
2580    /// Get organization usage costs
2581    pub async fn usage_cost_get(
2582        &self,
2583        organization_id: &str,
2584        from_date: &str,
2585        to_date: &str,
2586        filters: &[&str],
2587    ) -> Result<ApiResponse<UsageCost>, Error> {
2588        let path = format!("/v1/organizations/{organization_id}/usageCost");
2589        let mut req = self.request(reqwest::Method::GET, &path);
2590        req = req.query(&[("from_date", from_date)]);
2591        req = req.query(&[("to_date", to_date)]);
2592        for f in filters {
2593            req = req.query(&[("filter", f)]);
2594        }
2595        let resp = req.send().await?;
2596        let status = resp.status();
2597        let body_text = resp.text().await?;
2598        if !status.is_success() {
2599            return Err(Error::Api {
2600                status: status.as_u16(),
2601                message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
2602                    .ok()
2603                    .and_then(|r| r.error)
2604                    .unwrap_or(body_text.clone()),
2605            });
2606        }
2607        Ok(serde_json::from_str(&body_text)?)
2608    }
2609
2610    /// List ClickHouse settings
2611    pub async fn service_clickhouse_settings_list_get(
2612        &self,
2613        organization_id: &str,
2614        service_id: &str,
2615    ) -> Result<ApiResponse<ServiceClickhouseSettingsList>, Error> {
2616        let path = format!("/v1/organizations/{organization_id}/services/{service_id}/clickhouseSettings");
2617        let req = self.request(reqwest::Method::GET, &path);
2618        let resp = req.send().await?;
2619        let status = resp.status();
2620        let body_text = resp.text().await?;
2621        if !status.is_success() {
2622            return Err(Error::Api {
2623                status: status.as_u16(),
2624                message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
2625                    .ok()
2626                    .and_then(|r| r.error)
2627                    .unwrap_or(body_text.clone()),
2628            });
2629        }
2630        Ok(serde_json::from_str(&body_text)?)
2631    }
2632
2633    /// Update ClickHouse settings
2634    pub async fn service_clickhouse_settings_update(
2635        &self,
2636        organization_id: &str,
2637        service_id: &str,
2638        body: &ServiceClickhouseSettingsPatchRequest,
2639    ) -> Result<ApiResponse<ServiceClickhouseSettingsPatchResponse>, Error> {
2640        let path = format!("/v1/organizations/{organization_id}/services/{service_id}/clickhouseSettings");
2641        let mut req = self.request(reqwest::Method::PATCH, &path);
2642        req = req.json(body);
2643        let resp = req.send().await?;
2644        let status = resp.status();
2645        let body_text = resp.text().await?;
2646        if !status.is_success() {
2647            return Err(Error::Api {
2648                status: status.as_u16(),
2649                message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
2650                    .ok()
2651                    .and_then(|r| r.error)
2652                    .unwrap_or(body_text.clone()),
2653            });
2654        }
2655        Ok(serde_json::from_str(&body_text)?)
2656    }
2657
2658    /// Get ClickHouse settings schema
2659    pub async fn service_clickhouse_settings_schema_get(
2660        &self,
2661        organization_id: &str,
2662        service_id: &str,
2663    ) -> Result<ApiResponse<ServiceClickhouseSettingsSchema>, Error> {
2664        let path = format!("/v1/organizations/{organization_id}/services/{service_id}/clickhouseSettings/schema");
2665        let req = self.request(reqwest::Method::GET, &path);
2666        let resp = req.send().await?;
2667        let status = resp.status();
2668        let body_text = resp.text().await?;
2669        if !status.is_success() {
2670            return Err(Error::Api {
2671                status: status.as_u16(),
2672                message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
2673                    .ok()
2674                    .and_then(|r| r.error)
2675                    .unwrap_or(body_text.clone()),
2676            });
2677        }
2678        Ok(serde_json::from_str(&body_text)?)
2679    }
2680
2681    /// Get ClickHouse setting
2682    pub async fn service_clickhouse_setting_get(
2683        &self,
2684        organization_id: &str,
2685        service_id: &str,
2686        setting_name: &str,
2687    ) -> Result<ApiResponse<ServiceClickhouseSetting>, Error> {
2688        let path = format!("/v1/organizations/{organization_id}/services/{service_id}/clickhouseSettings/{setting_name}");
2689        let req = self.request(reqwest::Method::GET, &path);
2690        let resp = req.send().await?;
2691        let status = resp.status();
2692        let body_text = resp.text().await?;
2693        if !status.is_success() {
2694            return Err(Error::Api {
2695                status: status.as_u16(),
2696                message: serde_json::from_str::<ApiResponse<serde_json::Value>>(&body_text)
2697                    .ok()
2698                    .and_then(|r| r.error)
2699                    .unwrap_or(body_text.clone()),
2700            });
2701        }
2702        Ok(serde_json::from_str(&body_text)?)
2703    }
2704
2705}