> ## Documentation Index
> Fetch the complete documentation index at: https://docs.usenexio.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Cancel run

> Ask Nexio to stop a queued or processing run.

## Behavior

A queued run becomes `cancelled` at once. A processing run stops at its next cancellation check, so poll until it is terminal. A run that is already terminal is returned unchanged with `200`. See [Runs](/engines/runs#cancel-a-run).


## OpenAPI

````yaml POST /api/v1/runs/{run_id}/cancel
openapi: 3.1.0
info:
  title: Nexio API
  version: '1.0'
  description: |
    The Nexio public API. Submit runs to configured engines and read their
    results, hold conversations with configured assistants, make authorized
    reads over the planes and families of a connected system of record, and
    manage webhooks and environments.

    Six engine types are registered: comparison, matching, entity_analysis,
    diligence, triage, and opportunity.

    Every route under /api/v1/ requires `Authorization: Bearer <key>`, except
    inbound event ingest (`POST /api/v1/events/ingest/{source_key}`), which
    authenticates each request against its ingest source instead: an
    HMAC-SHA256 signature for `nexio` and `github` sources, or a shared
    authentication code for an `ams360_ons` source. Error
    bodies share the `Error` schema. Call the API from servers only: it sends
    no CORS headers.
  contact:
    email: support@usenexio.com
    url: https://docs.usenexio.com
servers:
  - url: https://api.usenexio.com
    description: >-
      Nexio API. Sandbox or live is chosen by the API key's environment, not by
      the host.
security:
  - BearerAuth: []
tags:
  - name: EngineManagement
    description: >-
      Create, configure, version and manage engines. An engine is a
      configuration of one registered engine type.
  - name: Engines
    description: Engine-scoped endpoints for submitting runs and retrieving results.
  - name: Runs
    description: Retrieve and reconcile submitted runs.
  - name: Records
    description: >-
      Typed, authorized reads over the registered planes and families of a
      connected system of record, and governed writes to the action ledger. The
      generic family read is the core contract.
  - name: Graph
    description: >-
      The organization's data graph: a read-only map of connections and the
      derivations scheduled on them. Node kinds are a closed registry of 16; the
      API serves 14.
  - name: Environments
    description: >-
      The live environment and up to 5 sandbox environments in your org.
      Organization keys only.
  - name: Webhooks
    description: >-
      Manage webhook endpoints that receive terminal run events (run.completed,
      run.failed, run.cancelled) and run corrections (run.superseded).
  - name: Events
    description: >-
      Send inbound events to your organization's event log through an ingest
      source. Source kinds are nexio, github and ams360_ons; a nexio source
      sends event types from your own vocabulary.
  - name: Converse
    description: The raw stateless conversational model turn (caller-owned state).
  - name: Conversations
    description: >-
      Conversation instances (orchestrators over engines) and their managed
      conversations, turns, annotations, evals, and exports.
  - name: Platform
    description: Service health. No key needed.
paths:
  /api/v1/runs/{run_id}/cancel:
    post:
      tags:
        - Runs
      summary: Cancel Run
      description: >
        Request cancellation of a queued or running run. The first request

        records its timestamp and reason. Repeated requests preserve that

        original request. A queued run becomes terminal immediately. A running

        run stops cooperatively before terminal publication.


        Requires `runs:write`. A scoped key not bound to the run's engine gets

        `403 engine_binding_forbidden`. A run in another organization or

        environment returns `404 run_not_found`. See
        [Runs](/engines/runs#cancel-a-run).
      operationId: cancelRun
      parameters:
        - name: run_id
          in: path
          required: true
          schema:
            type: string
            format: uuid
      requestBody:
        required: false
        content:
          application/json:
            schema:
              type: object
              additionalProperties: false
              properties:
                reason:
                  type: string
                  description: >-
                    Free text stored with the first cancel request, trimmed. The
                    whole body is limited to 16 KiB.
      responses:
        '200':
          description: |
            The run was already terminal and is unchanged. The body is the
            run's status fields and stored `output`, built without solutions:
            it carries no `solutions`, `input`, `work_items`, `warnings`,
            `computed_at_head`, `served_head` or `stale`. `output` is the
            stored output as written: a matching run's operator block is not
            trimmed and no acting principal's field policy is applied. Read the
            served result with `GET /api/v1/runs/{run_id}`.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/RunStatusResponse'
        '202':
          description: |
            Cancellation was accepted. `status` is `cancelled` when the run was
            queued and `processing` when it was running.
          content:
            application/json:
              schema:
                type: object
                required:
                  - run_id
                  - status
                  - cancel_requested_at
                properties:
                  run_id:
                    type: string
                    format: uuid
                  status:
                    type: string
                  cancel_requested_at:
                    type: string
                    format: date-time
        '400':
          description: >-
            `invalid_run_id`: `run_id` is not a UUID. `invalid_request`: the
            body is not JSON, carries a field other than `reason`, or exceeds 16
            KiB.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          description: >-
            Missing `runs:write`, or the scoped key is not bound to the run's
            engine.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                code: engine_binding_forbidden
                message: API key is not bound to this run's engine
        '404':
          description: Run not found in this organization and environment.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                code: run_not_found
                message: Run not found
        '429':
          $ref: '#/components/responses/RateLimited'
        '500':
          description: >-
            `load_run_failed`, `cancel_run_failed`, `run_lookup_failed`, or
            another internal code. Retry; the first cancel request's timestamp
            and reason are kept.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '503':
          $ref: '#/components/responses/AuthUnavailable'
        '504':
          $ref: '#/components/responses/RequestTimeout'
components:
  schemas:
    RunStatusResponse:
      type: object
      required:
        - run_id
        - status
        - environment
        - attempt
        - created_at
      properties:
        run_id:
          type: string
          format: uuid
          description: Stable run identifier.
        engine_type:
          type: string
          description: |
            Runtime engine type: `comparison`, `matching`, `entity_analysis`,
            `diligence`, `triage` or `opportunity`. Runs recorded before the
            cutover keep `placement`. Omitted on legacy rows without engine
            metadata.
        engine_version:
          type: string
          description: |
            The engine version this run executed against, resolved at submit
            time and frozen for the run's lifetime. A released `major.minor`
            label when the run was pinned to a release (`N.M` or `N.x`) or sent
            no pin (an unpinned public submission resolves to the latest
            release). The literal `draft` when a sandbox key pinned `draft` and
            the run executed the unpublished configuration. Absent only on
            older or internal records that carry no version stamp.
          example: '1.3'
        engine_config_version_hash:
          type: string
          description: |
            Immutable hash of the archived engine configuration this run
            executed. Resolved and frozen at submission alongside
            `engine_version`. Absent on legacy unstamped runs.
          example: 297c960d80b848c9
        status:
          type: string
          enum:
            - queued
            - processing
            - completed
            - degraded
            - failed
            - cancelled
          description: >
            Current run status. `queued` and `processing` are non-terminal: keep

            polling. `completed`, `degraded`, `failed`, and `cancelled` are

            terminal. `degraded` carries output; read
            `output.degradation_reason`

            (entity analysis) or `output.partial` (matching). See

            [Runs](/engines/runs#degraded-runs).
        environment:
          type: string
          enum:
            - test
            - live
          description: Environment the run executed in.
        parked_until:
          type: string
          format: date-time
          description: >-
            Scheduled resume from the latest warehouse wait. Present while
            processing until a worker heartbeat confirms resume. Keep polling
            past this deadline.
        park_reason:
          type: string
          description: Reason for the active park. Present alongside parked_until.
        last_parked_until:
          type: string
          format: date-time
          description: >-
            Latest warehouse wait deadline, retained after resume so clients can
            extend their polling budget through the park.
        stage:
          type: string
          description: Last known pipeline stage (e.g. `EVALUATE`, `FILTER`).
        output:
          type: object
          additionalProperties: true
          description: >
            Run output. Present only on `completed` and `degraded` runs. The
            shape

            comes from the engine's declared response schema, which its type

            derives from its configuration; see [Engine
            types](/engines/overview#engine-types).

            The named properties below are written by specific types.
          properties:
            output_phase:
              type: string
              enum:
                - final
                - deterministic_draft
              description: >
                The stored block's own copy of the top-level `output_phase`.
                Always

                `final` on a served output. Written on `comparison` output
                blocks.
            enrichment:
              type: object
              description: Per-source enrichment outcome blocks keyed by handler kind.
              additionalProperties:
                $ref: '#/components/schemas/EnrichmentOutcomeBlock'
            diagnostic:
              oneOf:
                - type: string
                - type: 'null'
              description: '`comparison` type: why nothing was ranked.'
            degradation_reason:
              type: string
              enum:
                - no_requirements
                - no_offerings
                - no_combinations
                - input_quality
                - llm_degraded
                - enrichment_degraded
                - scoring_rule_failed
                - mixed
                - other
                - insufficient_corpus
              description: >
                Stable reason on `degraded` runs, and on comparison runs that
                completed

                with nothing ranked. Customer automation routes on this instead
                of

                parsing free-text from `diagnostic`. When multiple non-info
                diagnostics

                are present, strict precedence picks the most actionable single
                reason:

                `input_quality` > `llm_degraded` >

                `enrichment_degraded` > `other`. `mixed` and
                `scoring_rule_failed`

                are defined but not emitted. `insufficient_corpus` is set on

                `completed` runs by a decline gate that runs only when a
                platform

                setting enables it. Outputs of matching runs report loss in

                `output.partial` instead.
            requirement_count:
              type: integer
              description: '`comparison` type: number of required categories evaluated.'
            solutions_count:
              type: integer
              description: '`comparison` type: number of ranked results generated.'
            appetite_bucket:
              type: string
              description: >-
                `comparison` type: the weight profile the run ranked with
                (`coverage_first`, `cost_sensitive`, `balanced`, `simplicity`).
            top_label:
              oneOf:
                - type: string
                - type: 'null'
              description: >-
                `comparison` type: label of the top-ranked result (e.g.
                `recommended`, `best_value`).
            top_score:
              oneOf:
                - type: number
                - type: 'null'
              description: '`comparison` type: overall score of the top-ranked result.'
        duration_ms:
          type: integer
          description: Duration of the final execution attempt in milliseconds.
        total_duration_ms:
          type: integer
          description: Wall-clock milliseconds from creation to terminal completion.
        attempt:
          type: integer
          minimum: 0
          description: >-
            Execution attempt count. A terminal value of 1 means no worker
            retry.
        error:
          type: string
          description: Error message on failed runs.
        error_details:
          type: object
          additionalProperties: true
          description: Structured failure details.
        trace_id:
          type: string
          pattern: ^[0-9a-f]{32}$
          description: Trace identifier for support correlation.
        created_at:
          type: string
          format: date-time
          description: RFC 3339 timestamp when the run was created.
        completed_at:
          type: string
          format: date-time
          description: RFC 3339 timestamp when the run reached a terminal state.
        completed_deterministic_at:
          type: string
          format: date-time
          description: >
            When a run of the `comparison` type finished its deterministic
            scoring. Stamped

            mid-run, so it can appear while `status` is still `processing`. A

            timing fact only: no output is served until the run is `completed`

            or `degraded`. Absent on other engine types and on webhook payloads.
        output_phase:
          type: string
          enum:
            - final
            - deterministic_draft
          description: |
            Which answer `output` and `solutions` carry. Present on every
            `completed` and `degraded` run, and then always `final`, even when
            `solutions` (for example on an engine that produces none) or
            `output` is absent. Absent on `queued`, `processing`, `failed` and
            `cancelled` runs, and on webhook payloads.
        solutions:
          type: array
          description: >
            Ranked results. Present on `completed` and `degraded` runs of the

            types that rank them (`comparison`, `matching`), when at least one
            was

            produced.
          items:
            $ref: '#/components/schemas/Solution'
        warnings:
          description: >
            Structured input-quality warnings. Present only when the run
            recorded

            warnings and the engine's current saved configuration sets

            `expose_warnings: true` when the run is read. The setting is read on

            each request, not from the release the run used.
          oneOf:
            - type: object
              additionalProperties: true
            - type: array
              items:
                type: object
                additionalProperties: true
        started_at:
          type: string
          format: date-time
          description: When a worker first started the run.
        input:
          type: object
          additionalProperties: true
          description: The admitted submission. Present only with `include=input`.
        computed_at_head:
          type: string
          description: >-
            The source data head the run computed against, on runs of engines
            Nexio operates that are recorded as a result in a connected system
            of record.
        served_head:
          type: string
          description: The source data head served now, on the same runs.
        stale:
          type: boolean
          description: >-
            True when the assessed subject changed between the head the run
            computed against (`computed_at_head`) and the head that now serves
            it (`served_head`). A result carried to a newer head unchanged has
            `stale: false`. Present on the same runs as `computed_at_head`.
        work_items:
          type: object
          additionalProperties: true
          description: |
            Compact rollup of the run's work items: `total`, `required`,
            `required_complete`, `required_incomplete`, `required_failed`,
            `required_cancelled`, optional `problems`, and
            `suggested_terminal`.
    Error:
      type: object
      required:
        - code
        - message
      properties:
        code:
          type: string
          description: >
            Stable snake_case error identifier. Safe to match programmatically.

            New codes are added over time; treat an unknown code by its HTTP
            status.


            Known codes include:

            `invalid_request`, `invalid_input`, `unauthorized`,

            `auth_unavailable`, `rate_limited`, `missing_run_id`,

            `invalid_run_id`, `run_not_found`, `invalid_offerings`,

            `missing_input`, `queue_unreachable`, `engine_not_found`,

            `engine_slug_conflict`, `engine_archived`, `instance_not_found`,

            `instance_slug_conflict`, `instance_archived`,

            `instance_follows_canonical`, `instance_not_published`,

            `invalid_engine_type`, `validation_error`, `webhook_not_found`,

            `webhook_limit_exceeded`, `invalid_url`, `invalid_events`,

            `invalid_description`, `invalid_auth_token`,

            `missing_endpoint_id`, `invalid_endpoint_id`,

            `missing_delivery_id`, `invalid_delivery_id`,

            `delivery_not_found`, `delivery_not_resendable`,

            `insufficient_capability`, `engine_version_required`,

            `engine_version_exact_required`, `engine_version_not_found`,

            `engine_version_invalid_format`,

            `engine_version_draft_requires_sandbox_key`,

            `engine_version_none_released`, `test_scenario_sandbox_only`,

            `test_scenario_forbidden`, `test_scenario_exact_version_required`,

            `test_scenario_version_not_supported`, `invalid_test_scenario`,

            `request_bound_exceeded`, `run_cap_exceeded`,

            `scoped_key_required`, `engine_binding_forbidden`,

            `request_timeout`, `internal_error`, `idempotency_key_reused`,

            `invalid_idempotency_key`, `acting_principal_mismatch`,

            `run_requires_acting_principal`, `environment_slug_invalid`,

            `environment_slug_reserved`, `environment_slug_taken`,

            `environment_name_invalid`, `environment_limit_reached`,

            `environment_live_immutable`, `environment_not_found`,

            `environment_in_use`, `environment_operation_failed`,

            `list_environments_failed`, `engine_release_unservable`,

            `engine_config_hash_inconsistent`,

            `engine_config_hash_unavailable`,

            `engine_config_version_unavailable`,

            `engine_version_resolve_failed`,

            `engine_config_version_load_failed`,

            `engine_version_publish_mismatch`,

            `engine_version_schema_change_requires_major`,

            `engine_config_hash_missing`, `engine_config_changed`,

            `invalid_engine_config`, `cold_start_gate_not_met`,

            `cold_start_gate_failed`, `cold_start_gate_regressed`,

            `cancel_run_failed`, `event_id_reused`, `invalid_event_id`,

            `missing_event_id`, `invalid_event_type`, `invalid_payload`,

            `reason_text_too_long`, `reason_taxonomy_version_unknown`,

            `invalid_rating`, `missing_comment`, `invalid_target`,

            `invalid_time_on_task`, `scoped_annotation_required`,

            `missing_instance_slug`, `invalid_instance_config`,

            `invalid_eval_waiver`, `instance_config_hash_missing`,

            `config_changed_during_publish`,

            `scenario_set_changed_during_publish`,

            `conversation_eval_regressed`,

            `conversation_eval_execution_failed`,

            `conversation_eval_gate_unavailable`, `publish_failed`,

            `conversation_not_found`, `conversation_archived`,

            `invalid_cursor`, `message_not_found`, `invalid_turn_request`,

            `message_too_long`, `invalid_tool_result`, `invalid_confirmation`,

            `invalid_edit_target`, `turn_in_progress`, `pending_turn`,

            `turn_state_conflict`, `confirmation_environment_unpinned`,

            `instance_config_missing`, `instance_config_invalid`,

            `instance_model_unavailable`, `guardrail_evaluation_failed`,

            `guardrail_config_invalid`, `invalid_conversation_history`,

            `streaming_unsupported`, `converse_unavailable`, `provider_error`,

            `provider_unavailable`, `unknown_model`, `too_many_messages`,

            `too_many_tools`, `invalid_max_tokens`, `invalid_message_role`,

            `invalid_message`, `invalid_content_block`, `invalid_tool`,

            `attachments_not_enabled`, `attachments_unavailable`,

            `attachment_rejected`, `attachment_too_large`,

            `attachments_too_large`, `too_many_attachments`,

            `attachment_not_accepted`, `attachment_not_found`,

            `attachment_changed`, `attachment_read_failed`,

            `attachment_member_delete`, `attachment_not_reservable`,

            `invalid_offset`, `invalid_turn_id`, `invalid_comment`,

            `invalid_reason`, `invalid_feedback_key`, `turn_not_found`,

            `annotation_not_found`, `annotation_not_promotable`,

            `invalid_eval_scenario`, `conversation_eval_scenario_not_found`,

            `conversation_eval_scenario_cap`,

            `conversation_eval_run_not_found`,

            `conversation_eval_baseline_not_found`,

            `conversation_eval_unavailable`,

            `instance_version_invalid_format`, `instance_version_not_found`,

            `document_class_not_open`, `presign_failed`,

            `markets_directory_unavailable`, `book_unavailable`,

            `book_connection_ambiguous`, `identity_unmapped`,

            `identity_needs_review`, `identity_suspended`, `identity_stale`,

            `scope_unavailable`, `assertion_invalid`, `assertion_stale`,

            `cursor_filter_mismatch`, `cursor_expired`,

            `action_schema_unknown`, `action_payload_invalid`,

            `action_out_of_scope`, `action_list_too_large`,

            `overlay_read_only`, `unsupported_node_type`,

            `acting_principal_required`, `action_denied`,

            `appetite_read_denied`, `approval_required`,

            `catalog_access_denied`, `catalog_connection_ambiguous`,

            `create_webhook_failed`, `dataset_denied`, `delivery_id_reused`,

            `document_type_not_servable`, `document_unclassified`,

            `egress_manifest_version_mismatch`,

            `egress_manifest_version_required`, `event_type_not_allowed`,

            `event_type_reserved`, `execution_confirm_required`,

            `execution_prohibited`, `ingest_source_disabled`,

            `ingest_source_misconfigured`, `ingest_source_not_found`,

            `invalid_acting_assertion`, `invalid_active`,

            `invalid_credentials`, `invalid_payload_mode`,

            `invalid_signature`, `load_run_failed`, `load_solutions_failed`,

            `load_work_items_failed`, `missing_engine_slug`, `not_found`,

            `object_store_unconfigured`, `provider_not_approved`,

            `resolve_retry_exhausted`, `run_lookup_failed`,

            `service_identity_unknown`, `stale_timestamp`, `surface_denied`,

            `unresolved_market_question`, `unsupported_market_filter`.


            The full list with causes and fixes is at

            https://docs.usenexio.com/reference/errors.
        message:
          type: string
          description: Human-readable error message. May change between versions.
        details:
          description: |
            Optional request-specific details. Request-bound failures use the
            `RequestBoundDetails` object. Validation failures may use an array
            of field issues or another documented object.

            `409 environment_in_use` is the one exception to this envelope: it
            carries a top-level `blockers` object (see `EnvironmentInUseError`)
            instead of `details`.
    EnrichmentOutcomeBlock:
      type: object
      additionalProperties: false
      required:
        - kind
      description: >
        Terminal outcome for one configured and enabled enrichment source.

        `status` and `attempted` are present on every run completed under the

        current outcome contract; enrichment blocks retrieved from runs

        archived before that rollout omit them, so treat both as optional.
        `payload` is required for `succeeded` and

        `not_mapped` and absent for all other statuses. `fetched_at` is

        optional. Block diagnostics are byte-equivalent to the matching entries

        in the top-level output diagnostics array.


        `not_mapped` means the source returned no mapped feature. It does not

        mean no flood risk. Public-source data and cache entries may be stale.


        FEMA degraded and circuit-open diagnostics use bounded

        `details.upstream` values `google_geocoding` and `nfhl`.
      properties:
        kind:
          type: string
          example: fema_nfhl
        status:
          type: string
          enum:
            - succeeded
            - not_mapped
            - skipped
            - ambiguous
            - unavailable
        attempted:
          type: boolean
          description: >-
            False when no upstream attempt occurred, including a cache hit or
            pre-call skip.
        payload:
          type: object
          additionalProperties: true
          description: |
            Required for `succeeded` and `not_mapped`; absent otherwise. A
            successful `fema_nfhl` payload always includes `sfha`; it is a
            boolean when FEMA supplied T/F and explicit JSON null when unknown.
        fetched_at:
          type: string
          format: date-time
        diagnostics:
          type: array
          items:
            type: object
            additionalProperties: true
      allOf:
        - if:
            properties:
              status:
                enum:
                  - succeeded
                  - not_mapped
            required:
              - status
          then:
            required:
              - payload
        - if:
            properties:
              status:
                enum:
                  - skipped
                  - ambiguous
                  - unavailable
            required:
              - status
          then:
            not:
              required:
                - payload
        - if:
            properties:
              kind:
                const: fema_nfhl
              status:
                const: succeeded
            required:
              - kind
              - status
          then:
            properties:
              payload:
                required:
                  - sfha
                  - base_flood_elevation_feet
                properties:
                  sfha:
                    type:
                      - boolean
                      - 'null'
    Solution:
      type: object
      required:
        - id
        - offerings
        - requirements_met
        - provider_count
        - scorecard
      properties:
        id:
          type: string
          format: uuid
          description: Stable solution identifier within this run.
        offerings:
          type: array
          description: Offerings included in this solution package.
          items:
            $ref: '#/components/schemas/SolutionOffering'
        requirements_met:
          type: array
          items:
            type: string
          description: >-
            Requirement markers satisfied, as `lob_<category>` (for example
            `lob_home`).
        provider_count:
          type: integer
          description: Number of distinct providers in this solution.
        est_cost_low:
          type: integer
          description: Estimated annual cost, low end.
        est_cost_high:
          type: integer
          description: Estimated annual cost, high end.
        consolidation_discount:
          type: number
          description: |
            Bundling discount applied to this solution, as a fraction
            (0.0 to 1.0). Derived from
            `bundle.standalone_premium_annual` and
            `bundle.joined_premium_annual` when a bundle is applied; `0`
            otherwise.
        bundle:
          $ref: '#/components/schemas/AppliedBundle'
        scorecard:
          $ref: '#/components/schemas/Scorecard'
        cluster_label:
          type: string
          description: |
            Solution label indicating where it excels: `recommended`,
            `best_value`, `best_coverage`, `simplest`.
        rank:
          type: integer
          description: Rank position (1 = best).
        headline:
          type: string
          description: >-
            A one-line summary of the solution. Omitted when the run produced
            none.
        narrative:
          description: >-
            A structured explanation of the solution, as JSON. Omitted when the
            run produced none.
    SolutionOffering:
      type: object
      required:
        - id
        - provider_name
        - category
      description: Abbreviated offering reference within a ranked solution.
      properties:
        id:
          type: string
          description: >-
            Line-level offering identifier (matches an entry in the submitted
            `offerings`).
        provider_name:
          type: string
          description: Provider display name.
        category:
          type: string
          description: >-
            Requirement category (domain-specific, e.g. `home`, `auto`,
            `umbrella`).
        data_currency:
          allOf:
            - $ref: '#/components/schemas/DataCurrency'
          description: >
            Freshness of this offering's underlying source data. Serialized on

            each offering object within a ranked solution (the engine's

            `Offering`); clients read it at
            `solutions[].offerings[].data_currency`.

            Present only for offerings loaded from a materialized connection.
        alternates:
          type: array
          description: >
            Other offerings that would have filled THIS seat: offerings whose

            answer on every per-seat axis matches the seated one exactly, so

            the engine ranks one and carries the rest here instead

            of as near-identical ranked entries. Every alternate cleared the

            same eligibility this line's seated offering did, and each carries

            its own per-seat scorecard. Read at

            `solutions[].offerings[].alternates`. Present only on engine
            versions

            that emit alternates; omitted otherwise. Runs of the `matching` type

            do not populate it: they list other candidates by ID at

            `offerings[].attributes.matching.alternates`.
          items:
            $ref: '#/components/schemas/SeatAlternate'
    AppliedBundle:
      type: object
      description: |
        Present on a Solution when a provider-supplied bundle was applied.
        Lists the offerings that bundle together, the provider's joined annual
        price, the sum of standalone annual prices, and the dollar-per-year
        savings.
        Omitted on standalone solutions.
      required:
        - offering_ids
        - joined_premium_annual
        - standalone_premium_annual
        - savings_annual
      properties:
        offering_ids:
          type: array
          items:
            type: string
          description: IDs of every offering that participates in the applied bundle.
        joined_premium_annual:
          type: integer
          minimum: 0
        standalone_premium_annual:
          type: integer
          minimum: 0
        savings_annual:
          type: integer
          minimum: 0
          description: |
            `standalone_premium_annual` minus `joined_premium_annual`,
            clamped to zero when the provider's bundled price meets or
            exceeds the standalone sum.
    Scorecard:
      type: object
      required:
        - overall_level
      additionalProperties: true
      description: |
        Evaluation scorecard. `overall_level` is always present. Dimension
        keys are configured per released engine version; the named properties
        below are the default dimensions of the `comparison` type, not an
        exhaustive set.

        A dimension the run had no signal to score is present with `level`
        0 and `method` `suppressed`, and `overall_level` is the weighted
        level over the scored dimensions only. For a scored solution,
        `overall_level` is on a 1 to 4 scale where higher is better (a level 1
        dimension counts as 4). A solution from a matching run is not scored
        this way: its scorecard carries `overall_level: 0` and no dimensions or
        `fit_score`.
      properties:
        coverage_completeness:
          $ref: '#/components/schemas/Dimension'
        pricing_competitiveness:
          $ref: '#/components/schemas/Dimension'
        provider_quality:
          $ref: '#/components/schemas/Dimension'
        placement_likelihood:
          $ref: '#/components/schemas/Dimension'
        operational_simplicity:
          $ref: '#/components/schemas/Dimension'
        risk_alignment:
          $ref: '#/components/schemas/Dimension'
        overall_level:
          type: number
          description: |
            Raw weighted level across configured dimensions. Use the
            solution's emitted `rank`, not this value, as the ordering contract.
        assessed_weight_fraction:
          type: number
          minimum: 0
          maximum: 1
          description: >
            Share of the enabled scoring weight this scorecard actually scored.

            Emitted only by engine versions that declare an assessed-weight
            floor.
        run_position:
          $ref: '#/components/schemas/RunPosition'
    DataCurrency:
      type: object
      description: >
        Freshness of the underlying source data for an offering loaded from a

        materialized (replicate-then-index) connection. Advisory only; it labels

        the result and never changes ranking. Present only for
        materialize-sourced

        offerings; omitted otherwise.
      properties:
        effective_year:
          type: integer
          description: The source schedule's effective business year, when known.
        effective_date:
          type: string
          format: date
          description: The product's effective date (YYYY-MM-DD), when known.
        stale:
          type: boolean
          description: >
            True when the source data is older than the freshness window (more
            than

            one year old) or undated. Show a stale offering with a caution that
            its

            rates can be out of date.
        undated:
          type: boolean
          description: True when no effective year or date is known at all.
        effective_date_basis:
          type: string
          enum:
            - stated
            - schedule_year
            - absent
          description: |
            Where `effective_date` came from, so a synthesized day is never read
            as a stated one. `stated` means the source document reported a
            per-line date and it is the date shown. `schedule_year` means the
            document stated only a year, so the date is January 1 of that year:
            read the year, do not read the day. `absent` means no date is
            available at all. Present only on engines that emit seat facts;
            omitted otherwise.
    SeatAlternate:
      type: object
      required:
        - offering_id
        - provider_name
        - scorecard
      description: One offering that would have filled a seat in a ranked solution.
      properties:
        offering_id:
          type: string
          description: Line-level offering identifier, from this run's own candidates.
        provider_name:
          type: string
          description: Provider display name.
        scorecard:
          type: object
          additionalProperties: true
          description: |
            This alternate seat's own answer on the per-provider axes:
            `market_entity_key`, `line`, and one dimension per axis.
    Dimension:
      type: object
      required:
        - level
        - label
        - justification
        - method
      properties:
        level:
          type: integer
          minimum: 0
          maximum: 4
          description: >-
            Rating from 1 (best) to 4 (worst). 0 means the dimension was not
            scored (`method` is `suppressed`).
        label:
          type: string
          description: Human-readable label for this level.
        justification:
          type: string
          description: Reasoning for the assigned level.
        method:
          type: string
          enum:
            - deterministic
            - llm
            - fallback
            - suppressed
          description: >-
            How this dimension was scored. `suppressed` means there was no
            signal to score it and it is left out of `overall_level`.
    RunPosition:
      type: object
      required:
        - percentile
        - tied
        - population
        - population_unit
        - basis
        - field_best
        - field_worst
      description: |
        Where this solution sits inside its own run's field. Emitted only by
        engine versions that enable it. An absolute band does not discriminate
        on a narrow field, so position is measured against the run's own spread.

        The population is the solutions this run assembled, scored and ranked,
        excluding any that fell below the engine's assessed-weight floor: those
        did not compete, and they carry no `run_position` at all.
      properties:
        percentile:
          type: number
          description: |
            Midrank percentile of `overall_level` over the population, higher
            being better, with ties corrected. Every member of a fully tied
            field reads 50.
        margin:
          type: number
          description: |
            Gap in `basis` to the next solution down in the population. Absent
            on the lowest solution, which has no next. `0` is a real value and
            means an exact tie.
        tied:
          type: integer
          description: |
            How many solutions share this exact `basis` value, including this
            one. Counted in `population_unit`. 1 means unique.
        population:
          type: integer
          description: >-
            How many solutions the percentile was measured over, counted in
            `population_unit`.
        population_unit:
          type: string
          description: What `population` and `tied` count.
        basis:
          type: string
          description: What `percentile`, `margin`, `field_best` and `field_worst` measure.
        field_best:
          type: number
          description: The population's best value on `basis`.
        field_worst:
          type: number
          description: |
            The population's worst value on `basis`. With `field_best` it gives
            the field's own spread, which is what turns a margin into a
            judgment without holding the whole field.
  responses:
    Unauthorized:
      description: Missing or invalid API key.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            code: unauthorized
            message: Missing or invalid API key
    RateLimited:
      description: Rate limit exceeded. Retry after the window resets.
      headers:
        Retry-After:
          $ref: '#/components/headers/RetryAfter'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            code: rate_limited
            message: Rate limit exceeded
    AuthUnavailable:
      description: |
        `auth_unavailable`: API key authentication was briefly unavailable
        before the route ran. Transient; retry with backoff.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            code: auth_unavailable
            message: API key authentication is temporarily unavailable
    RequestTimeout:
      description: >-
        `request_timeout`: the 30 second route timeout expired before the
        handler answered.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            code: request_timeout
            message: Request timed out
  headers:
    RetryAfter:
      description: Whole seconds to wait before retrying, at least 1.
      schema:
        type: integer
        minimum: 1
  securitySchemes:
    BearerAuth:
      type: http
      scheme: bearer
      description: >
        Send the key as `Authorization: Bearer <key>`. Two kinds of key exist.


        Organization keys are issued in the portal (Settings, then API keys),

        each bound to one environment, shaped `nx_<environment slug>_<64 hex>`.
        They carry

        no capabilities and pass every capability check, with one exception:

        routes under /api/v1/records, /api/v1/engines/{id}/opportunities,

        /api/v1/graph and /api/v1/catalog/documents accept an

        organization key only when its environment is `live`, and refuse any

        other with 403 `scoped_key_required`. Revocation takes effect within 60

        seconds.


        Scoped keys are issued by Nexio on request, shaped

        `nxsk_v1_<24 hex key id>_<43 character secret>`. Each is bound to one

        org, one environment, a set of engines and a set of capabilities. A

        malformed, unknown or revoked `nxsk_` key fails with 401 and is never

        retried as an organization key. Revocation takes effect on the next

        request. A scoped key without a route's capability gets 403

        `insufficient_capability`; a scoped key not bound to the engine gets 403

        `engine_binding_forbidden`.


        Key-grantable capabilities: `engines:read`, `runs:write`, `runs:read`,

        `runs:defensibility:read`, `runs:test`, `catalog:read`,

        `catalog:documents:read`, `webhooks:manage`, `conversations:use`,

        `conversations:export`, `records:read`, `records:opportunities:run`,

        `actions:write`, `actions:read`, `graph:read`, `records:analyze`.


        Routes that accept organization keys only (every scoped key gets 403

        `insufficient_capability`): environment management, engine create,

        update, configuration and publish, and conversation instance

        authoring. Each operation description names the capability a scoped

        key needs.

````