generated: '2026-08-17' method: derived source: >- openapi/_original/quandela-cloud-openapi.json (info.description, tag descriptions, parameters, responses) plus live anonymous probes of https://api.cloud.quandela.com on 2026-08-17 note: >- Cross-cutting runtime semantics of the Quandela Cloud API, derived from Quandela's own published OpenAPI and confirmed against live anonymous responses. The API-reference UI at https://api.cloud.quandela.com/api/docs/ 302-redirects to account.quandela.com/login, so the specification itself is the only readable normative description of these conventions. base_url: https://api.cloud.quandela.com/ authentication: style: bearer-token header: 'Authorization: Bearer ' scheme_name: BearerAuth spec_text: >- "All endpoints require an access token generated by the authorization server. Include the token in the request headers: Authorization: Bearer YOUR_ACCESS_TOKEN. Ensure the token is valid and not expired." two_token_classes: - name: account access token issued_by: account.quandela.com (the authorization server) used_on: /api/auth/tokens* and /api/tokens* token-administration endpoints failure: '401 ''{"detail":{},"error":"Authentication and authorization failed: token not found"}''' - name: Cloud Job Token issued_by: POST /api/tokens (or POST /api/auth/tokens) used_on: >- the job-execution surface — the tags "Api - Perceval Job", "Api - Perceval Job Token" and the /qt/* Quantum Toolbox and QRNG operations, whose tag descriptions read "Authenticate by `Cloud Job Token`" failure: 401 '{"detail":{},"error":"Invalid or expired job token"}' lifecycle: generate -> revoke -> reopen -> delete, with labels and expiry oauth2: false scopes: false detail: authentication/quandela-authentication.yml idempotency: supported: false header: null note: >- NO IDEMPOTENCY CONTRACT. There is no Idempotency-Key header, parameter or equivalent anywhere in the 59-operation spec (case-insensitive search for "idempoten" across the published openapi.json returns zero matches). The nearest facility is the caller-supplied `process_id` on POST /api/jobs, but a collision returns 400 "process_id is existed and assigned to another user job" rather than replaying the original response, so it is a uniqueness guard, not idempotent replay. A retried job submission after a timeout can therefore consume credits twice. No `Idempotency` pointer is emitted in apis.yml. pagination: style: limit-offset applies_to: - openapi/quandela-job-token-openapi.yml#get_api_auth_tokens - openapi/quandela-perceval-job-token-openapi.yml#get_api_tokens request_params: - name: limit in: query - name: offset in: query filter_params: - {name: user_id, in: query} - {name: include_expired, in: query} - {name: include_revoked, in: query} response_envelope: TokensListUnitResponse note: >- Offset pagination is present only on the two token-list operations. The job surface has no list endpoint at all — jobs are addressed individually by job_id, so there is no way to enumerate an account's jobs over REST. cursor: false async_pattern: style: submit-then-poll note: >- The defining convention of this API. Every quantum workload is asynchronous and is driven entirely by client polling; there is no callback, webhook, SSE or streaming surface (see asyncapi/ — absent). perceval_flow: submit: POST /api/jobs -> JobId poll_status: GET /api/jobs/{job_id}/status -> JobStatusResponse fetch_result: GET /api/jobs/{job_id}/result -> JobResult fetch_payload: GET /api/jobs/{job_id}/data cancel: POST /api/jobs/{job_id}/cancel rerun: POST /api/jobs/{job_id}/rerun quantum_toolbox_flow: estimate: POST /qt//estimate # cost/feasibility pre-flight before spending credits submit: POST /qt/ -> QTJobId poll_status: GET /qt//{job_id}/status fetch_result: GET /qt//{job_id}/results estimate_before_submit: >- Each of the five Quantum Toolbox algorithms publishes a paired /estimate operation. This is an unusual and genuinely agent-friendly convention: an agent can price a workload before committing credits. intermediate_results: >- The VQE algorithms expose Intermediate*VqeResults schemas, so status polls can return partial optimisation traces before the job terminates. resource_addressing: job_id: path parameter, appears on 19 operations token_id: path parameter, appears on 5 operations platform: >- addressed by `platform_name` (namespaced string, e.g. "qpu:belenos", "qpu:ascella", "sim:slos") or `platform_id` (UUID). Job creation requires exactly one; omitting both returns 400 "Require platform_id or platform_name". versioning: scheme: unversioned-path current: v2.8.0-rc4 where: openapi info.version note: >- Paths carry no version segment — the base is https://api.cloud.quandela.com/api/... with no /v1 or /v2. The version lives only in the spec's info.version, which currently advertises a release-candidate build (v2.8.0-rc4) as the production contract. Version evolution is instead expressed by path duplication: singular legacy paths (/api/job, /api/auth/token) are marked deprecated alongside plural successors (/api/jobs, /api/auth/tokens). See lifecycle/. detail: lifecycle/quandela-lifecycle.yml error_envelope: format: vendor-json shape: '{"detail": , "error": ""}' rfc9457: false detail: errors/quandela-problem-types.yml rate_limit_signalling: headers: none status_429: false note: >- Concurrency and credit ceilings exist but are signalled only as 400/403/401 messages with no header budget and no Retry-After. detail: rate-limits/quandela-rate-limits.yml request_tracing: request_id_header: null correlation_id: null note: >- No request-id or correlation header is defined in the spec or returned on live responses. The only caller-side correlator is the optional `process_id` on job creation. content_negotiation: request: application/json response: application/json media_types_declared: [application/json] note: All 258 declared responses across the spec use application/json exclusively. field_expansion: supported: false sparse_fieldsets: supported: false metadata: user_metadata_field: false note: >- Job tokens carry a `label`; jobs carry an optional caller-supplied `process_id`. There is no general-purpose metadata bag. undocumented_public_endpoints: note: >- Two anonymous endpoints answer 200 with real data but are NOT in the published openapi.json. They are recorded here as observed, not added to the specification. endpoints: - method: GET url: https://api.cloud.quandela.com/api/platforms/public status: 200 auth: none returns: >- array of platforms with name, description, type, status, maintenance{start_time,end_time} and statistic{date: {availability}} - method: GET url: https://api.cloud.quandela.com/api/status status: 200 auth: none returns: '{"db":"ok","server":"ok"}' cross_references: authentication: authentication/quandela-authentication.yml errors: errors/quandela-problem-types.yml lifecycle: lifecycle/quandela-lifecycle.yml rate_limits: rate-limits/quandela-rate-limits.yml data_model: data-model/quandela-data-model.yml