Skip to main content

qcs_api_client_openapi/apis/
default_api.rs

1// Copyright 2026 Rigetti Computing
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15/*
16 * Rigetti QCS API
17 *
18 * # Introduction  This is the documentation for the Rigetti QCS HTTP API.  You can find out more about Rigetti at [https://rigetti.com](https://rigetti.com), and also interact with QCS via the web at [https://qcs.rigetti.com](https://qcs.rigetti.com).  This API is documented in **OpenAPI format** and so is compatible with the dozens of language-specific client generators available [here](https://github.com/OpenAPITools/openapi-generator) and elsewhere on the web.  # Principles  This API follows REST design principles where appropriate, and otherwise an HTTP RPC paradigm. We adhere to the Google [API Improvement Proposals](https://google.aip.dev/general) where reasonable to provide a consistent, intuitive developer experience. HTTP response codes match their specifications, and error messages fit a common format.  # Authentication  All access to the QCS API requires OAuth2 authentication provided by Okta. You can request access [here](https://www.rigetti.com/get-quantum). Once you have a user account, you can download your access token from QCS [here](https://qcs.rigetti.com/auth/token).   That access token is valid for 24 hours after issuance. The value of `access_token` within the JSON file is the token used for authentication (don't use the entire JSON file).  Authenticate requests using the `Authorization` header and a `Bearer` prefix:  ``` curl --header \"Authorization: Bearer eyJraW...Iow\" ```  # Quantum Processor Access  Access to the quantum processors themselves is not yet provided directly by this HTTP API, but is instead performed over ZeroMQ/[rpcq](https://github.com/rigetti/rpcq). Until that changes, we suggest using [pyquil](https://github.com/rigetti/pyquil) to build and execute quantum programs via the Legacy API.  # Legacy API  Our legacy HTTP API remains accessible at https://forest-server.qcs.rigetti.com, and it shares a source of truth with this API's services. You can use either service with the same user account and means of authentication. We strongly recommend using the API documented here, as the legacy API is on the path to deprecation.
19 *
20 * The version of the OpenAPI document: 2020-07-31
21 * Contact: support@rigetti.com
22 * Generated by: https://openapi-generator.tech
23 */
24
25use super::{ContentType, Error, configuration};
26use crate::{apis::ResponseContent, models};
27use ::qcs_api_client_common::backoff::{
28    BackoffBuilder, ExponentialBackoff, duration_from_io_error, duration_from_reqwest_error,
29    duration_from_response,
30};
31#[cfg(feature = "tracing")]
32use qcs_api_client_common::configuration::tokens::TokenRefresher;
33use qcs_dependencies_client::reqwest::{self, StatusCode};
34use serde::{Deserialize, Serialize};
35
36#[cfg(feature = "clap")]
37#[allow(unused, reason = "not used in all templates, but required in some")]
38use ::{miette::IntoDiagnostic as _, qcs_api_client_common::clap_utils::JsonMaybeStdin};
39
40/// Serialize command-line arguments for [`get_health`]
41#[cfg(feature = "clap")]
42#[derive(Debug, clap::Args)]
43pub struct GetHealthClapParams {}
44
45#[cfg(feature = "clap")]
46impl GetHealthClapParams {
47    pub async fn execute(
48        self,
49        configuration: &configuration::Configuration,
50    ) -> Result<models::Health, miette::Error> {
51        get_health(configuration).await.into_diagnostic()
52    }
53}
54
55/// Serialize command-line arguments for [`health_check`]
56#[cfg(feature = "clap")]
57#[derive(Debug, clap::Args)]
58pub struct HealthCheckClapParams {}
59
60#[cfg(feature = "clap")]
61impl HealthCheckClapParams {
62    pub async fn execute(
63        self,
64        configuration: &configuration::Configuration,
65    ) -> Result<(), miette::Error> {
66        health_check(configuration).await.into_diagnostic()
67    }
68}
69
70/// Serialize command-line arguments for [`health_check_deprecated`]
71#[cfg(feature = "clap")]
72#[derive(Debug, clap::Args)]
73pub struct HealthCheckDeprecatedClapParams {}
74
75#[cfg(feature = "clap")]
76impl HealthCheckDeprecatedClapParams {
77    pub async fn execute(
78        self,
79        configuration: &configuration::Configuration,
80    ) -> Result<serde_json::Value, miette::Error> {
81        health_check_deprecated(configuration)
82            .await
83            .into_diagnostic()
84    }
85}
86
87/// struct for typed errors of method [`get_health`]
88#[derive(Debug, Clone, Serialize, Deserialize)]
89#[serde(untagged)]
90pub enum GetHealthError {
91    UnknownValue(serde_json::Value),
92}
93
94/// struct for typed errors of method [`health_check`]
95#[derive(Debug, Clone, Serialize, Deserialize)]
96#[serde(untagged)]
97pub enum HealthCheckError {
98    UnknownValue(serde_json::Value),
99}
100
101/// struct for typed errors of method [`health_check_deprecated`]
102#[derive(Debug, Clone, Serialize, Deserialize)]
103#[serde(untagged)]
104pub enum HealthCheckDeprecatedError {
105    Status422(models::ValidationError),
106    UnknownValue(serde_json::Value),
107}
108
109async fn get_health_inner(
110    configuration: &configuration::Configuration,
111    backoff: &mut ExponentialBackoff,
112) -> Result<models::Health, Error<GetHealthError>> {
113    let local_var_configuration = configuration;
114
115    let local_var_client = &local_var_configuration.client;
116
117    let local_var_uri_str = format!("{}/", local_var_configuration.qcs_config.api_url());
118    let mut local_var_req_builder =
119        local_var_client.request(reqwest::Method::GET, local_var_uri_str.as_str());
120
121    #[cfg(feature = "tracing")]
122    {
123        // Ignore parsing errors if the URL is invalid for some reason.
124        // If it is invalid, it will turn up as an error later when actually making the request.
125        let local_var_do_tracing = local_var_uri_str
126            .parse::<::url::Url>()
127            .ok()
128            .is_none_or(|url| {
129                configuration
130                    .qcs_config
131                    .should_trace(&::urlpattern::UrlPatternMatchInput::Url(url))
132            });
133
134        if local_var_do_tracing {
135            ::tracing::debug!(
136                url=%local_var_uri_str,
137                method="GET",
138                "making get_health request",
139            );
140        }
141    }
142
143    // Use the QCS Bearer token if a client OAuthSession is present,
144    // but do not require one when the security schema says it is optional.
145    {
146        use qcs_api_client_common::configuration::TokenError;
147
148        #[allow(
149            clippy::nonminimal_bool,
150            clippy::eq_op,
151            reason = "Logic must be done at runtime since it cannot be handled by the mustache template engine."
152        )]
153        let is_jwt_bearer_optional: bool = false;
154
155        let token = local_var_configuration
156            .qcs_config
157            .get_bearer_access_token()
158            .await;
159
160        if is_jwt_bearer_optional && matches!(token, Err(TokenError::NoCredentials)) {
161            // the client is configured without any OAuthSession, but this call does not require one.
162            #[cfg(feature = "tracing")]
163            tracing::debug!(
164                "No client credentials found, but this call does not require authentication."
165            );
166        } else {
167            local_var_req_builder = local_var_req_builder.bearer_auth(token?.secret());
168        }
169    }
170
171    let local_var_req = local_var_req_builder.build()?;
172    let local_var_resp = local_var_client.execute(local_var_req).await?;
173
174    let local_var_status = local_var_resp.status();
175    let local_var_raw_content_type = local_var_resp
176        .headers()
177        .get("content-type")
178        .and_then(|v| v.to_str().ok())
179        .unwrap_or("application/octet-stream")
180        .to_string();
181    let local_var_content_type = super::ContentType::from(local_var_raw_content_type.as_str());
182
183    if !local_var_status.is_client_error() && !local_var_status.is_server_error() {
184        let local_var_content = local_var_resp.text().await?;
185        match local_var_content_type {
186            ContentType::Json => serde_path_to_error::deserialize(
187                &mut serde_json::Deserializer::from_str(&local_var_content),
188            )
189            .map_err(Error::from),
190            ContentType::Text => Err(Error::InvalidContentType {
191                content_type: local_var_raw_content_type,
192                return_type: "models::Health",
193            }),
194            ContentType::Unsupported(unknown_type) => Err(Error::InvalidContentType {
195                content_type: unknown_type,
196                return_type: "models::Health",
197            }),
198        }
199    } else {
200        let local_var_retry_delay =
201            duration_from_response(local_var_resp.status(), local_var_resp.headers(), backoff);
202        let local_var_content = local_var_resp.text().await?;
203        let local_var_entity: Option<GetHealthError> =
204            serde_json::from_str(&local_var_content).ok();
205        let local_var_error = ResponseContent {
206            status: local_var_status,
207            content: local_var_content,
208            entity: local_var_entity,
209            retry_delay: local_var_retry_delay,
210        };
211        Err(Error::ResponseError(local_var_error))
212    }
213}
214
215/// Retrieve the health status of the API
216pub async fn get_health(
217    configuration: &configuration::Configuration,
218) -> Result<models::Health, Error<GetHealthError>> {
219    let mut backoff = configuration.backoff.build();
220    let mut refreshed_credentials = false;
221    let method = reqwest::Method::GET;
222    loop {
223        let result = get_health_inner(configuration, &mut backoff).await;
224
225        match result {
226            Ok(result) => return Ok(result),
227            Err(Error::ResponseError(response)) => {
228                if !refreshed_credentials
229                    && matches!(
230                        response.status,
231                        StatusCode::FORBIDDEN | StatusCode::UNAUTHORIZED
232                    )
233                {
234                    // Attempt to refresh credentials
235                    match configuration.qcs_config.refresh().await {
236                        Ok(_) => {
237                            refreshed_credentials = true;
238                            continue;
239                        }
240                        Err(::qcs_api_client_common::configuration::TokenError::Write {
241                            error,
242                            oauth_session: _,
243                        }) => {
244                            // Token refresh succeeded but persistence failed
245                            // The token is already in memory and will be used for this request
246                            #[cfg(feature = "tracing")]
247                            tracing::warn!(
248                                "Token refresh succeeded but failed to persist: {}. Continuing with in-memory token.",
249                                error
250                            );
251                            refreshed_credentials = true;
252                            continue;
253                        }
254                        Err(e) => return Err(e.into()),
255                    }
256                } else if let Some(duration) = response.retry_delay {
257                    tokio::time::sleep(duration).await;
258                    continue;
259                }
260
261                return Err(Error::ResponseError(response));
262            }
263            Err(Error::Reqwest(error)) => {
264                if let Some(duration) = duration_from_reqwest_error(&method, &error, &mut backoff) {
265                    tokio::time::sleep(duration).await;
266                    continue;
267                }
268
269                return Err(Error::Reqwest(error));
270            }
271            Err(Error::Io(error)) => {
272                if let Some(duration) = duration_from_io_error(&method, &error, &mut backoff) {
273                    tokio::time::sleep(duration).await;
274                    continue;
275                }
276
277                return Err(Error::Io(error));
278            }
279            Err(error) => return Err(error),
280        }
281    }
282}
283async fn health_check_inner(
284    configuration: &configuration::Configuration,
285    backoff: &mut ExponentialBackoff,
286) -> Result<(), Error<HealthCheckError>> {
287    let local_var_configuration = configuration;
288
289    let local_var_client = &local_var_configuration.client;
290
291    let local_var_uri_str = format!(
292        "{}/v1/healthcheck",
293        local_var_configuration.qcs_config.api_url()
294    );
295    let mut local_var_req_builder =
296        local_var_client.request(reqwest::Method::GET, local_var_uri_str.as_str());
297
298    #[cfg(feature = "tracing")]
299    {
300        // Ignore parsing errors if the URL is invalid for some reason.
301        // If it is invalid, it will turn up as an error later when actually making the request.
302        let local_var_do_tracing = local_var_uri_str
303            .parse::<::url::Url>()
304            .ok()
305            .is_none_or(|url| {
306                configuration
307                    .qcs_config
308                    .should_trace(&::urlpattern::UrlPatternMatchInput::Url(url))
309            });
310
311        if local_var_do_tracing {
312            ::tracing::debug!(
313                url=%local_var_uri_str,
314                method="GET",
315                "making health_check request",
316            );
317        }
318    }
319
320    // Use the QCS Bearer token if a client OAuthSession is present,
321    // but do not require one when the security schema says it is optional.
322    {
323        use qcs_api_client_common::configuration::TokenError;
324
325        #[allow(
326            clippy::nonminimal_bool,
327            clippy::eq_op,
328            reason = "Logic must be done at runtime since it cannot be handled by the mustache template engine."
329        )]
330        let is_jwt_bearer_optional: bool = false;
331
332        let token = local_var_configuration
333            .qcs_config
334            .get_bearer_access_token()
335            .await;
336
337        if is_jwt_bearer_optional && matches!(token, Err(TokenError::NoCredentials)) {
338            // the client is configured without any OAuthSession, but this call does not require one.
339            #[cfg(feature = "tracing")]
340            tracing::debug!(
341                "No client credentials found, but this call does not require authentication."
342            );
343        } else {
344            local_var_req_builder = local_var_req_builder.bearer_auth(token?.secret());
345        }
346    }
347
348    let local_var_req = local_var_req_builder.build()?;
349    let local_var_resp = local_var_client.execute(local_var_req).await?;
350
351    let local_var_status = local_var_resp.status();
352
353    if !local_var_status.is_client_error() && !local_var_status.is_server_error() {
354        Ok(())
355    } else {
356        let local_var_retry_delay =
357            duration_from_response(local_var_resp.status(), local_var_resp.headers(), backoff);
358        let local_var_content = local_var_resp.text().await?;
359        let local_var_entity: Option<HealthCheckError> =
360            serde_json::from_str(&local_var_content).ok();
361        let local_var_error = ResponseContent {
362            status: local_var_status,
363            content: local_var_content,
364            entity: local_var_entity,
365            retry_delay: local_var_retry_delay,
366        };
367        Err(Error::ResponseError(local_var_error))
368    }
369}
370
371/// Check the health of the service.
372pub async fn health_check(
373    configuration: &configuration::Configuration,
374) -> Result<(), Error<HealthCheckError>> {
375    let mut backoff = configuration.backoff.build();
376    let mut refreshed_credentials = false;
377    let method = reqwest::Method::GET;
378    loop {
379        let result = health_check_inner(configuration, &mut backoff).await;
380
381        match result {
382            Ok(result) => return Ok(result),
383            Err(Error::ResponseError(response)) => {
384                if !refreshed_credentials
385                    && matches!(
386                        response.status,
387                        StatusCode::FORBIDDEN | StatusCode::UNAUTHORIZED
388                    )
389                {
390                    // Attempt to refresh credentials
391                    match configuration.qcs_config.refresh().await {
392                        Ok(_) => {
393                            refreshed_credentials = true;
394                            continue;
395                        }
396                        Err(::qcs_api_client_common::configuration::TokenError::Write {
397                            error,
398                            oauth_session: _,
399                        }) => {
400                            // Token refresh succeeded but persistence failed
401                            // The token is already in memory and will be used for this request
402                            #[cfg(feature = "tracing")]
403                            tracing::warn!(
404                                "Token refresh succeeded but failed to persist: {}. Continuing with in-memory token.",
405                                error
406                            );
407                            refreshed_credentials = true;
408                            continue;
409                        }
410                        Err(e) => return Err(e.into()),
411                    }
412                } else if let Some(duration) = response.retry_delay {
413                    tokio::time::sleep(duration).await;
414                    continue;
415                }
416
417                return Err(Error::ResponseError(response));
418            }
419            Err(Error::Reqwest(error)) => {
420                if let Some(duration) = duration_from_reqwest_error(&method, &error, &mut backoff) {
421                    tokio::time::sleep(duration).await;
422                    continue;
423                }
424
425                return Err(Error::Reqwest(error));
426            }
427            Err(Error::Io(error)) => {
428                if let Some(duration) = duration_from_io_error(&method, &error, &mut backoff) {
429                    tokio::time::sleep(duration).await;
430                    continue;
431                }
432
433                return Err(Error::Io(error));
434            }
435            Err(error) => return Err(error),
436        }
437    }
438}
439async fn health_check_deprecated_inner(
440    configuration: &configuration::Configuration,
441    backoff: &mut ExponentialBackoff,
442) -> Result<serde_json::Value, Error<HealthCheckDeprecatedError>> {
443    let local_var_configuration = configuration;
444
445    let local_var_client = &local_var_configuration.client;
446
447    let local_var_uri_str = format!("{}/v1/", local_var_configuration.qcs_config.api_url());
448    let mut local_var_req_builder =
449        local_var_client.request(reqwest::Method::GET, local_var_uri_str.as_str());
450
451    #[cfg(feature = "tracing")]
452    {
453        // Ignore parsing errors if the URL is invalid for some reason.
454        // If it is invalid, it will turn up as an error later when actually making the request.
455        let local_var_do_tracing = local_var_uri_str
456            .parse::<::url::Url>()
457            .ok()
458            .is_none_or(|url| {
459                configuration
460                    .qcs_config
461                    .should_trace(&::urlpattern::UrlPatternMatchInput::Url(url))
462            });
463
464        if local_var_do_tracing {
465            ::tracing::debug!(
466                url=%local_var_uri_str,
467                method="GET",
468                "making health_check_deprecated request",
469            );
470        }
471    }
472
473    // Use the QCS Bearer token if a client OAuthSession is present,
474    // but do not require one when the security schema says it is optional.
475    {
476        use qcs_api_client_common::configuration::TokenError;
477
478        #[allow(
479            clippy::nonminimal_bool,
480            clippy::eq_op,
481            reason = "Logic must be done at runtime since it cannot be handled by the mustache template engine."
482        )]
483        let is_jwt_bearer_optional: bool = false;
484
485        let token = local_var_configuration
486            .qcs_config
487            .get_bearer_access_token()
488            .await;
489
490        if is_jwt_bearer_optional && matches!(token, Err(TokenError::NoCredentials)) {
491            // the client is configured without any OAuthSession, but this call does not require one.
492            #[cfg(feature = "tracing")]
493            tracing::debug!(
494                "No client credentials found, but this call does not require authentication."
495            );
496        } else {
497            local_var_req_builder = local_var_req_builder.bearer_auth(token?.secret());
498        }
499    }
500
501    let local_var_req = local_var_req_builder.build()?;
502    let local_var_resp = local_var_client.execute(local_var_req).await?;
503
504    let local_var_status = local_var_resp.status();
505    let local_var_raw_content_type = local_var_resp
506        .headers()
507        .get("content-type")
508        .and_then(|v| v.to_str().ok())
509        .unwrap_or("application/octet-stream")
510        .to_string();
511    let local_var_content_type = super::ContentType::from(local_var_raw_content_type.as_str());
512
513    if !local_var_status.is_client_error() && !local_var_status.is_server_error() {
514        let local_var_content = local_var_resp.text().await?;
515        match local_var_content_type {
516            ContentType::Json => serde_path_to_error::deserialize(
517                &mut serde_json::Deserializer::from_str(&local_var_content),
518            )
519            .map_err(Error::from),
520            ContentType::Text => Err(Error::InvalidContentType {
521                content_type: local_var_raw_content_type,
522                return_type: "serde_json::Value",
523            }),
524            ContentType::Unsupported(unknown_type) => Err(Error::InvalidContentType {
525                content_type: unknown_type,
526                return_type: "serde_json::Value",
527            }),
528        }
529    } else {
530        let local_var_retry_delay =
531            duration_from_response(local_var_resp.status(), local_var_resp.headers(), backoff);
532        let local_var_content = local_var_resp.text().await?;
533        let local_var_entity: Option<HealthCheckDeprecatedError> =
534            serde_json::from_str(&local_var_content).ok();
535        let local_var_error = ResponseContent {
536            status: local_var_status,
537            content: local_var_content,
538            entity: local_var_entity,
539            retry_delay: local_var_retry_delay,
540        };
541        Err(Error::ResponseError(local_var_error))
542    }
543}
544
545/// Endpoint to return a status 200 for load balancer health checks
546#[deprecated]
547pub async fn health_check_deprecated(
548    configuration: &configuration::Configuration,
549) -> Result<serde_json::Value, Error<HealthCheckDeprecatedError>> {
550    let mut backoff = configuration.backoff.build();
551    let mut refreshed_credentials = false;
552    let method = reqwest::Method::GET;
553    loop {
554        let result = health_check_deprecated_inner(configuration, &mut backoff).await;
555
556        match result {
557            Ok(result) => return Ok(result),
558            Err(Error::ResponseError(response)) => {
559                if !refreshed_credentials
560                    && matches!(
561                        response.status,
562                        StatusCode::FORBIDDEN | StatusCode::UNAUTHORIZED
563                    )
564                {
565                    // Attempt to refresh credentials
566                    match configuration.qcs_config.refresh().await {
567                        Ok(_) => {
568                            refreshed_credentials = true;
569                            continue;
570                        }
571                        Err(::qcs_api_client_common::configuration::TokenError::Write {
572                            error,
573                            oauth_session: _,
574                        }) => {
575                            // Token refresh succeeded but persistence failed
576                            // The token is already in memory and will be used for this request
577                            #[cfg(feature = "tracing")]
578                            tracing::warn!(
579                                "Token refresh succeeded but failed to persist: {}. Continuing with in-memory token.",
580                                error
581                            );
582                            refreshed_credentials = true;
583                            continue;
584                        }
585                        Err(e) => return Err(e.into()),
586                    }
587                } else if let Some(duration) = response.retry_delay {
588                    tokio::time::sleep(duration).await;
589                    continue;
590                }
591
592                return Err(Error::ResponseError(response));
593            }
594            Err(Error::Reqwest(error)) => {
595                if let Some(duration) = duration_from_reqwest_error(&method, &error, &mut backoff) {
596                    tokio::time::sleep(duration).await;
597                    continue;
598                }
599
600                return Err(Error::Reqwest(error));
601            }
602            Err(Error::Io(error)) => {
603                if let Some(duration) = duration_from_io_error(&method, &error, &mut backoff) {
604                    tokio::time::sleep(duration).await;
605                    continue;
606                }
607
608                return Err(Error::Io(error));
609            }
610            Err(error) => return Err(error),
611        }
612    }
613}