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    ExponentialBackoff, duration_from_io_error, duration_from_reqwest_error, duration_from_response,
29};
30#[cfg(feature = "tracing")]
31use qcs_api_client_common::configuration::tokens::TokenRefresher;
32use qcs_dependencies_client::reqwest::{self, StatusCode};
33use serde::{Deserialize, Serialize};
34
35#[cfg(feature = "clap")]
36#[allow(unused, reason = "not used in all templates, but required in some")]
37use ::{miette::IntoDiagnostic as _, qcs_api_client_common::clap_utils::JsonMaybeStdin};
38
39/// Serialize command-line arguments for [`get_health`]
40#[cfg(feature = "clap")]
41#[derive(Debug, clap::Args)]
42pub struct GetHealthClapParams {}
43
44#[cfg(feature = "clap")]
45impl GetHealthClapParams {
46    pub async fn execute(
47        self,
48        configuration: &configuration::Configuration,
49    ) -> Result<models::Health, miette::Error> {
50        get_health(configuration).await.into_diagnostic()
51    }
52}
53
54/// Serialize command-line arguments for [`health_check`]
55#[cfg(feature = "clap")]
56#[derive(Debug, clap::Args)]
57pub struct HealthCheckClapParams {}
58
59#[cfg(feature = "clap")]
60impl HealthCheckClapParams {
61    pub async fn execute(
62        self,
63        configuration: &configuration::Configuration,
64    ) -> Result<(), miette::Error> {
65        health_check(configuration).await.into_diagnostic()
66    }
67}
68
69/// Serialize command-line arguments for [`health_check_deprecated`]
70#[cfg(feature = "clap")]
71#[derive(Debug, clap::Args)]
72pub struct HealthCheckDeprecatedClapParams {}
73
74#[cfg(feature = "clap")]
75impl HealthCheckDeprecatedClapParams {
76    pub async fn execute(
77        self,
78        configuration: &configuration::Configuration,
79    ) -> Result<serde_json::Value, miette::Error> {
80        health_check_deprecated(configuration)
81            .await
82            .into_diagnostic()
83    }
84}
85
86/// struct for typed errors of method [`get_health`]
87#[derive(Debug, Clone, Serialize, Deserialize)]
88#[serde(untagged)]
89pub enum GetHealthError {
90    UnknownValue(serde_json::Value),
91}
92
93/// struct for typed errors of method [`health_check`]
94#[derive(Debug, Clone, Serialize, Deserialize)]
95#[serde(untagged)]
96pub enum HealthCheckError {
97    UnknownValue(serde_json::Value),
98}
99
100/// struct for typed errors of method [`health_check_deprecated`]
101#[derive(Debug, Clone, Serialize, Deserialize)]
102#[serde(untagged)]
103pub enum HealthCheckDeprecatedError {
104    Status422(models::ValidationError),
105    UnknownValue(serde_json::Value),
106}
107
108async fn get_health_inner(
109    configuration: &configuration::Configuration,
110    backoff: &mut ExponentialBackoff,
111) -> Result<models::Health, Error<GetHealthError>> {
112    let local_var_configuration = configuration;
113
114    let local_var_client = &local_var_configuration.client;
115
116    let local_var_uri_str = format!("{}/", local_var_configuration.qcs_config.api_url());
117    let mut local_var_req_builder =
118        local_var_client.request(reqwest::Method::GET, local_var_uri_str.as_str());
119
120    #[cfg(feature = "tracing")]
121    {
122        // Ignore parsing errors if the URL is invalid for some reason.
123        // If it is invalid, it will turn up as an error later when actually making the request.
124        let local_var_do_tracing = local_var_uri_str
125            .parse::<::url::Url>()
126            .ok()
127            .is_none_or(|url| {
128                configuration
129                    .qcs_config
130                    .should_trace(&::urlpattern::UrlPatternMatchInput::Url(url))
131            });
132
133        if local_var_do_tracing {
134            ::tracing::debug!(
135                url=%local_var_uri_str,
136                method="GET",
137                "making get_health request",
138            );
139        }
140    }
141
142    // Use the QCS Bearer token if a client OAuthSession is present,
143    // but do not require one when the security schema says it is optional.
144    {
145        use qcs_api_client_common::configuration::TokenError;
146
147        #[allow(
148            clippy::nonminimal_bool,
149            clippy::eq_op,
150            reason = "Logic must be done at runtime since it cannot be handled by the mustache template engine."
151        )]
152        let is_jwt_bearer_optional: bool = false;
153
154        let token = local_var_configuration
155            .qcs_config
156            .get_bearer_access_token()
157            .await;
158
159        if is_jwt_bearer_optional && matches!(token, Err(TokenError::NoCredentials)) {
160            // the client is configured without any OAuthSession, but this call does not require one.
161            #[cfg(feature = "tracing")]
162            tracing::debug!(
163                "No client credentials found, but this call does not require authentication."
164            );
165        } else {
166            local_var_req_builder = local_var_req_builder.bearer_auth(token?.secret());
167        }
168    }
169
170    let local_var_req = local_var_req_builder.build()?;
171    let local_var_resp = local_var_client.execute(local_var_req).await?;
172
173    let local_var_status = local_var_resp.status();
174    let local_var_raw_content_type = local_var_resp
175        .headers()
176        .get("content-type")
177        .and_then(|v| v.to_str().ok())
178        .unwrap_or("application/octet-stream")
179        .to_string();
180    let local_var_content_type = super::ContentType::from(local_var_raw_content_type.as_str());
181
182    if !local_var_status.is_client_error() && !local_var_status.is_server_error() {
183        let local_var_content = local_var_resp.text().await?;
184        match local_var_content_type {
185            ContentType::Json => serde_path_to_error::deserialize(
186                &mut serde_json::Deserializer::from_str(&local_var_content),
187            )
188            .map_err(Error::from),
189            ContentType::Text => Err(Error::InvalidContentType {
190                content_type: local_var_raw_content_type,
191                return_type: "models::Health",
192            }),
193            ContentType::Unsupported(unknown_type) => Err(Error::InvalidContentType {
194                content_type: unknown_type,
195                return_type: "models::Health",
196            }),
197        }
198    } else {
199        let local_var_retry_delay =
200            duration_from_response(local_var_resp.status(), local_var_resp.headers(), backoff);
201        let local_var_content = local_var_resp.text().await?;
202        let local_var_entity: Option<GetHealthError> =
203            serde_json::from_str(&local_var_content).ok();
204        let local_var_error = ResponseContent {
205            status: local_var_status,
206            content: local_var_content,
207            entity: local_var_entity,
208            retry_delay: local_var_retry_delay,
209        };
210        Err(Error::ResponseError(local_var_error))
211    }
212}
213
214/// Retrieve the health status of the API
215pub async fn get_health(
216    configuration: &configuration::Configuration,
217) -> Result<models::Health, Error<GetHealthError>> {
218    let mut backoff = configuration.backoff.clone();
219    let mut refreshed_credentials = false;
220    let method = reqwest::Method::GET;
221    loop {
222        let result = get_health_inner(configuration, &mut backoff).await;
223
224        match result {
225            Ok(result) => return Ok(result),
226            Err(Error::ResponseError(response)) => {
227                if !refreshed_credentials
228                    && matches!(
229                        response.status,
230                        StatusCode::FORBIDDEN | StatusCode::UNAUTHORIZED
231                    )
232                {
233                    // Attempt to refresh credentials
234                    match configuration.qcs_config.refresh().await {
235                        Ok(_) => {
236                            refreshed_credentials = true;
237                            continue;
238                        }
239                        Err(::qcs_api_client_common::configuration::TokenError::Write {
240                            error,
241                            oauth_session: _,
242                        }) => {
243                            // Token refresh succeeded but persistence failed
244                            // The token is already in memory and will be used for this request
245                            #[cfg(feature = "tracing")]
246                            tracing::warn!(
247                                "Token refresh succeeded but failed to persist: {}. Continuing with in-memory token.",
248                                error
249                            );
250                            refreshed_credentials = true;
251                            continue;
252                        }
253                        Err(e) => return Err(e.into()),
254                    }
255                } else if let Some(duration) = response.retry_delay {
256                    tokio::time::sleep(duration).await;
257                    continue;
258                }
259
260                return Err(Error::ResponseError(response));
261            }
262            Err(Error::Reqwest(error)) => {
263                if let Some(duration) = duration_from_reqwest_error(&method, &error, &mut backoff) {
264                    tokio::time::sleep(duration).await;
265                    continue;
266                }
267
268                return Err(Error::Reqwest(error));
269            }
270            Err(Error::Io(error)) => {
271                if let Some(duration) = duration_from_io_error(&method, &error, &mut backoff) {
272                    tokio::time::sleep(duration).await;
273                    continue;
274                }
275
276                return Err(Error::Io(error));
277            }
278            Err(error) => return Err(error),
279        }
280    }
281}
282async fn health_check_inner(
283    configuration: &configuration::Configuration,
284    backoff: &mut ExponentialBackoff,
285) -> Result<(), Error<HealthCheckError>> {
286    let local_var_configuration = configuration;
287
288    let local_var_client = &local_var_configuration.client;
289
290    let local_var_uri_str = format!(
291        "{}/v1/healthcheck",
292        local_var_configuration.qcs_config.api_url()
293    );
294    let mut local_var_req_builder =
295        local_var_client.request(reqwest::Method::GET, local_var_uri_str.as_str());
296
297    #[cfg(feature = "tracing")]
298    {
299        // Ignore parsing errors if the URL is invalid for some reason.
300        // If it is invalid, it will turn up as an error later when actually making the request.
301        let local_var_do_tracing = local_var_uri_str
302            .parse::<::url::Url>()
303            .ok()
304            .is_none_or(|url| {
305                configuration
306                    .qcs_config
307                    .should_trace(&::urlpattern::UrlPatternMatchInput::Url(url))
308            });
309
310        if local_var_do_tracing {
311            ::tracing::debug!(
312                url=%local_var_uri_str,
313                method="GET",
314                "making health_check request",
315            );
316        }
317    }
318
319    // Use the QCS Bearer token if a client OAuthSession is present,
320    // but do not require one when the security schema says it is optional.
321    {
322        use qcs_api_client_common::configuration::TokenError;
323
324        #[allow(
325            clippy::nonminimal_bool,
326            clippy::eq_op,
327            reason = "Logic must be done at runtime since it cannot be handled by the mustache template engine."
328        )]
329        let is_jwt_bearer_optional: bool = false;
330
331        let token = local_var_configuration
332            .qcs_config
333            .get_bearer_access_token()
334            .await;
335
336        if is_jwt_bearer_optional && matches!(token, Err(TokenError::NoCredentials)) {
337            // the client is configured without any OAuthSession, but this call does not require one.
338            #[cfg(feature = "tracing")]
339            tracing::debug!(
340                "No client credentials found, but this call does not require authentication."
341            );
342        } else {
343            local_var_req_builder = local_var_req_builder.bearer_auth(token?.secret());
344        }
345    }
346
347    let local_var_req = local_var_req_builder.build()?;
348    let local_var_resp = local_var_client.execute(local_var_req).await?;
349
350    let local_var_status = local_var_resp.status();
351
352    if !local_var_status.is_client_error() && !local_var_status.is_server_error() {
353        Ok(())
354    } else {
355        let local_var_retry_delay =
356            duration_from_response(local_var_resp.status(), local_var_resp.headers(), backoff);
357        let local_var_content = local_var_resp.text().await?;
358        let local_var_entity: Option<HealthCheckError> =
359            serde_json::from_str(&local_var_content).ok();
360        let local_var_error = ResponseContent {
361            status: local_var_status,
362            content: local_var_content,
363            entity: local_var_entity,
364            retry_delay: local_var_retry_delay,
365        };
366        Err(Error::ResponseError(local_var_error))
367    }
368}
369
370/// Check the health of the service.
371pub async fn health_check(
372    configuration: &configuration::Configuration,
373) -> Result<(), Error<HealthCheckError>> {
374    let mut backoff = configuration.backoff.clone();
375    let mut refreshed_credentials = false;
376    let method = reqwest::Method::GET;
377    loop {
378        let result = health_check_inner(configuration, &mut backoff).await;
379
380        match result {
381            Ok(result) => return Ok(result),
382            Err(Error::ResponseError(response)) => {
383                if !refreshed_credentials
384                    && matches!(
385                        response.status,
386                        StatusCode::FORBIDDEN | StatusCode::UNAUTHORIZED
387                    )
388                {
389                    // Attempt to refresh credentials
390                    match configuration.qcs_config.refresh().await {
391                        Ok(_) => {
392                            refreshed_credentials = true;
393                            continue;
394                        }
395                        Err(::qcs_api_client_common::configuration::TokenError::Write {
396                            error,
397                            oauth_session: _,
398                        }) => {
399                            // Token refresh succeeded but persistence failed
400                            // The token is already in memory and will be used for this request
401                            #[cfg(feature = "tracing")]
402                            tracing::warn!(
403                                "Token refresh succeeded but failed to persist: {}. Continuing with in-memory token.",
404                                error
405                            );
406                            refreshed_credentials = true;
407                            continue;
408                        }
409                        Err(e) => return Err(e.into()),
410                    }
411                } else if let Some(duration) = response.retry_delay {
412                    tokio::time::sleep(duration).await;
413                    continue;
414                }
415
416                return Err(Error::ResponseError(response));
417            }
418            Err(Error::Reqwest(error)) => {
419                if let Some(duration) = duration_from_reqwest_error(&method, &error, &mut backoff) {
420                    tokio::time::sleep(duration).await;
421                    continue;
422                }
423
424                return Err(Error::Reqwest(error));
425            }
426            Err(Error::Io(error)) => {
427                if let Some(duration) = duration_from_io_error(&method, &error, &mut backoff) {
428                    tokio::time::sleep(duration).await;
429                    continue;
430                }
431
432                return Err(Error::Io(error));
433            }
434            Err(error) => return Err(error),
435        }
436    }
437}
438async fn health_check_deprecated_inner(
439    configuration: &configuration::Configuration,
440    backoff: &mut ExponentialBackoff,
441) -> Result<serde_json::Value, Error<HealthCheckDeprecatedError>> {
442    let local_var_configuration = configuration;
443
444    let local_var_client = &local_var_configuration.client;
445
446    let local_var_uri_str = format!("{}/v1/", local_var_configuration.qcs_config.api_url());
447    let mut local_var_req_builder =
448        local_var_client.request(reqwest::Method::GET, local_var_uri_str.as_str());
449
450    #[cfg(feature = "tracing")]
451    {
452        // Ignore parsing errors if the URL is invalid for some reason.
453        // If it is invalid, it will turn up as an error later when actually making the request.
454        let local_var_do_tracing = local_var_uri_str
455            .parse::<::url::Url>()
456            .ok()
457            .is_none_or(|url| {
458                configuration
459                    .qcs_config
460                    .should_trace(&::urlpattern::UrlPatternMatchInput::Url(url))
461            });
462
463        if local_var_do_tracing {
464            ::tracing::debug!(
465                url=%local_var_uri_str,
466                method="GET",
467                "making health_check_deprecated request",
468            );
469        }
470    }
471
472    // Use the QCS Bearer token if a client OAuthSession is present,
473    // but do not require one when the security schema says it is optional.
474    {
475        use qcs_api_client_common::configuration::TokenError;
476
477        #[allow(
478            clippy::nonminimal_bool,
479            clippy::eq_op,
480            reason = "Logic must be done at runtime since it cannot be handled by the mustache template engine."
481        )]
482        let is_jwt_bearer_optional: bool = false;
483
484        let token = local_var_configuration
485            .qcs_config
486            .get_bearer_access_token()
487            .await;
488
489        if is_jwt_bearer_optional && matches!(token, Err(TokenError::NoCredentials)) {
490            // the client is configured without any OAuthSession, but this call does not require one.
491            #[cfg(feature = "tracing")]
492            tracing::debug!(
493                "No client credentials found, but this call does not require authentication."
494            );
495        } else {
496            local_var_req_builder = local_var_req_builder.bearer_auth(token?.secret());
497        }
498    }
499
500    let local_var_req = local_var_req_builder.build()?;
501    let local_var_resp = local_var_client.execute(local_var_req).await?;
502
503    let local_var_status = local_var_resp.status();
504    let local_var_raw_content_type = local_var_resp
505        .headers()
506        .get("content-type")
507        .and_then(|v| v.to_str().ok())
508        .unwrap_or("application/octet-stream")
509        .to_string();
510    let local_var_content_type = super::ContentType::from(local_var_raw_content_type.as_str());
511
512    if !local_var_status.is_client_error() && !local_var_status.is_server_error() {
513        let local_var_content = local_var_resp.text().await?;
514        match local_var_content_type {
515            ContentType::Json => serde_path_to_error::deserialize(
516                &mut serde_json::Deserializer::from_str(&local_var_content),
517            )
518            .map_err(Error::from),
519            ContentType::Text => Err(Error::InvalidContentType {
520                content_type: local_var_raw_content_type,
521                return_type: "serde_json::Value",
522            }),
523            ContentType::Unsupported(unknown_type) => Err(Error::InvalidContentType {
524                content_type: unknown_type,
525                return_type: "serde_json::Value",
526            }),
527        }
528    } else {
529        let local_var_retry_delay =
530            duration_from_response(local_var_resp.status(), local_var_resp.headers(), backoff);
531        let local_var_content = local_var_resp.text().await?;
532        let local_var_entity: Option<HealthCheckDeprecatedError> =
533            serde_json::from_str(&local_var_content).ok();
534        let local_var_error = ResponseContent {
535            status: local_var_status,
536            content: local_var_content,
537            entity: local_var_entity,
538            retry_delay: local_var_retry_delay,
539        };
540        Err(Error::ResponseError(local_var_error))
541    }
542}
543
544/// Endpoint to return a status 200 for load balancer health checks
545#[deprecated]
546pub async fn health_check_deprecated(
547    configuration: &configuration::Configuration,
548) -> Result<serde_json::Value, Error<HealthCheckDeprecatedError>> {
549    let mut backoff = configuration.backoff.clone();
550    let mut refreshed_credentials = false;
551    let method = reqwest::Method::GET;
552    loop {
553        let result = health_check_deprecated_inner(configuration, &mut backoff).await;
554
555        match result {
556            Ok(result) => return Ok(result),
557            Err(Error::ResponseError(response)) => {
558                if !refreshed_credentials
559                    && matches!(
560                        response.status,
561                        StatusCode::FORBIDDEN | StatusCode::UNAUTHORIZED
562                    )
563                {
564                    // Attempt to refresh credentials
565                    match configuration.qcs_config.refresh().await {
566                        Ok(_) => {
567                            refreshed_credentials = true;
568                            continue;
569                        }
570                        Err(::qcs_api_client_common::configuration::TokenError::Write {
571                            error,
572                            oauth_session: _,
573                        }) => {
574                            // Token refresh succeeded but persistence failed
575                            // The token is already in memory and will be used for this request
576                            #[cfg(feature = "tracing")]
577                            tracing::warn!(
578                                "Token refresh succeeded but failed to persist: {}. Continuing with in-memory token.",
579                                error
580                            );
581                            refreshed_credentials = true;
582                            continue;
583                        }
584                        Err(e) => return Err(e.into()),
585                    }
586                } else if let Some(duration) = response.retry_delay {
587                    tokio::time::sleep(duration).await;
588                    continue;
589                }
590
591                return Err(Error::ResponseError(response));
592            }
593            Err(Error::Reqwest(error)) => {
594                if let Some(duration) = duration_from_reqwest_error(&method, &error, &mut backoff) {
595                    tokio::time::sleep(duration).await;
596                    continue;
597                }
598
599                return Err(Error::Reqwest(error));
600            }
601            Err(Error::Io(error)) => {
602                if let Some(duration) = duration_from_io_error(&method, &error, &mut backoff) {
603                    tokio::time::sleep(duration).await;
604                    continue;
605                }
606
607                return Err(Error::Io(error));
608            }
609            Err(error) => return Err(error),
610        }
611    }
612}