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

# Rate Saved Quote by Id

> Rates an **already-saved** quote, named by id, and returns the rating
results without persisting the returned field values.

**The rated field bag remains stateless.** No quote field or rating run is
persisted, and the quote row is byte-identical before and after — same field
values, same `updatedAt`. On a successful rate, the service records the
requested `ratingWorkflowName` as Quote system metadata so later saved-quote
workflows know which workflow was selected. A failed rating does not change
that selection. The rating results exist only in the response you receive,
so **if you want them stored on the quote, write them back
yourself** with `PATCH /api/v1/companies/{companyId}/entities/quote/{entityId}`
(for an in-force policy, a policy `endorse` transaction instead). That
write-back is the mutation — see the Rating overview's *Persisting rating
results*. Copy the returned `fullTermPricingInfo` (including
`pricingComponents` and computed totals) when it is present, read the quote
back to verify the committed values, and only then bind it. Bind reads the
persisted quote, not this rate response.

This is the by-id sibling of
`POST /api/v1/companies/{companyId}/quotes/rate`; the field-bag difference is
where the field bag comes from — loaded from the saved quote here, supplied
in the request body there. Only the by-id endpoint can record a saved quote's
workflow selection.

The quote id is a path parameter; the request body carries only
`ratingWorkflowName`. There are deliberately **no `data` overrides** — to
rate what-if values ("as if field X were Y"), `GET` the quote, tweak it, and
`POST` the full-body `/quotes/rate` endpoint, which supports inline overrides.

**Semantics.** The saved quote's stored field bag is validated with the
identical create-quote pipeline (shape, resolution, tenant invariants, entity
invariants), embedded exposure `id` references are looked up and merged from
their stored data exactly as the full-body endpoint does, and then the named
rating workflow runs. For a supported quote type there is **no quote-status
gate** — any saved quote rates regardless of `quoteStatus` (`bound` and
`cancelled` included), because rating a saved quote is a read-only
computation that can corrupt nothing. This status promise does not expand
the supported quote types: `cancellation` and `reinstatement` return a
structured `400 InvalidRequest` before any rater or vendor call because
those transactions preserve rating and derive or restore pricing.

The `200` response returns the saved quote's bag under `data`, enriched with
the rating outputs (e.g. `exposureRatingResponse` on each exposure and the
full-term policy rating containers).

**The response reflects only this run.** The rating workflow clears the
containers it owns before any rater runs and rebuilds them from this run's
output, so a rate that prices nothing returns those containers empty rather
than carrying the quote's previously stored figures. Writing such a response
back wholesale would therefore **clear** the stored money — check the
response for the values you expect before persisting it.

**Rating failures also return `200`** — with a `diagnostics` array
describing what went wrong and **no `data`**. Check for the presence of
`data` to detect success, not the HTTP status. Invalid requests (anything
under the `400`/`404`/`422` descriptions below) are still rejected with
their status codes; only failures during rating execution itself (e.g. a
rating vendor error) report as `200` + `diagnostics`.

**Required permission:** `quote.rate`




## OpenAPI

````yaml /openapi/generated-external-api.yaml post /api/v1/companies/{companyId}/quotes/{quoteId}/rate
openapi: 3.0.3
info:
  title: AI Insurance External API
  description: External API for AI Insurance platform
  version: 1.0.0
  contact:
    email: support@aiinsurance.io
servers:
  - url: https://go.aiinsurance.io
    description: Production
security:
  - ApiKeyAuth: []
paths:
  /api/v1/companies/{companyId}/quotes/{quoteId}/rate:
    post:
      tags:
        - Field Model Rating
      summary: Rate Saved Quote by Id
      description: >
        Rates an **already-saved** quote, named by id, and returns the rating

        results without persisting the returned field values.


        **The rated field bag remains stateless.** No quote field or rating run
        is

        persisted, and the quote row is byte-identical before and after — same
        field

        values, same `updatedAt`. On a successful rate, the service records the

        requested `ratingWorkflowName` as Quote system metadata so later
        saved-quote

        workflows know which workflow was selected. A failed rating does not
        change

        that selection. The rating results exist only in the response you
        receive,

        so **if you want them stored on the quote, write them back

        yourself** with `PATCH
        /api/v1/companies/{companyId}/entities/quote/{entityId}`

        (for an in-force policy, a policy `endorse` transaction instead). That

        write-back is the mutation — see the Rating overview's *Persisting
        rating

        results*. Copy the returned `fullTermPricingInfo` (including

        `pricingComponents` and computed totals) when it is present, read the
        quote

        back to verify the committed values, and only then bind it. Bind reads
        the

        persisted quote, not this rate response.


        This is the by-id sibling of

        `POST /api/v1/companies/{companyId}/quotes/rate`; the field-bag
        difference is

        where the field bag comes from — loaded from the saved quote here,
        supplied

        in the request body there. Only the by-id endpoint can record a saved
        quote's

        workflow selection.


        The quote id is a path parameter; the request body carries only

        `ratingWorkflowName`. There are deliberately **no `data` overrides** —
        to

        rate what-if values ("as if field X were Y"), `GET` the quote, tweak it,
        and

        `POST` the full-body `/quotes/rate` endpoint, which supports inline
        overrides.


        **Semantics.** The saved quote's stored field bag is validated with the

        identical create-quote pipeline (shape, resolution, tenant invariants,
        entity

        invariants), embedded exposure `id` references are looked up and merged
        from

        their stored data exactly as the full-body endpoint does, and then the
        named

        rating workflow runs. For a supported quote type there is **no
        quote-status

        gate** — any saved quote rates regardless of `quoteStatus` (`bound` and

        `cancelled` included), because rating a saved quote is a read-only

        computation that can corrupt nothing. This status promise does not
        expand

        the supported quote types: `cancellation` and `reinstatement` return a

        structured `400 InvalidRequest` before any rater or vendor call because

        those transactions preserve rating and derive or restore pricing.


        The `200` response returns the saved quote's bag under `data`, enriched
        with

        the rating outputs (e.g. `exposureRatingResponse` on each exposure and
        the

        full-term policy rating containers).


        **The response reflects only this run.** The rating workflow clears the

        containers it owns before any rater runs and rebuilds them from this
        run's

        output, so a rate that prices nothing returns those containers empty
        rather

        than carrying the quote's previously stored figures. Writing such a
        response

        back wholesale would therefore **clear** the stored money — check the

        response for the values you expect before persisting it.


        **Rating failures also return `200`** — with a `diagnostics` array

        describing what went wrong and **no `data`**. Check for the presence of

        `data` to detect success, not the HTTP status. Invalid requests
        (anything

        under the `400`/`404`/`422` descriptions below) are still rejected with

        their status codes; only failures during rating execution itself (e.g. a

        rating vendor error) report as `200` + `diagnostics`.


        **Required permission:** `quote.rate`
      operationId: rateQuoteById
      parameters:
        - $ref: '#/components/parameters/companyId'
        - $ref: '#/components/parameters/quoteIdPath'
      requestBody:
        required: false
        content:
          application/json:
            schema:
              type: object
              properties:
                ratingWorkflowName:
                  type: string
                  description: >
                    The configured rating workflow to run. **Required in
                    practice** —

                    there is no default even when a single workflow is
                    configured —

                    but it is not schema-required: rather than a shape
                    rejection, a

                    missing or unknown name returns a `400` listing the
                    configured

                    workflow names (and a company with no workflows configured

                    returns a `422`), so callers get an actionable error naming
                    the

                    valid options. There is no fallback to any per-quote
                    persisted

                    selection.
                  example: standard
            examples:
              standard:
                summary: Rate a saved quote with the standard workflow
                value:
                  ratingWorkflowName: standard
      responses:
        '200':
          description: >
            The rating outcome. A successful rate records the requested workflow

            selection, but the returned field values remain caller-persisted.


            **Success:** `data` carries the saved quote's bag enriched with
            rating

            outputs.


            **Rating failure:** the response is still `200`, with `diagnostics`

            describing what went wrong and **no `data`** — the absent `data` is

            the failure signal, so do not treat the presence of `diagnostics`

            alone as failure: `severity: warning` diagnostics ride alongside a

            successful `data` when a rater reports them. Rating failures are

            engine/vendor faults during rating execution; an invalid *request*
            is

            still a `4xx`, and an unexpected application fault is still a `500`.
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    description: |
                      The saved quote's stored field bag, enriched with rating
                      outputs (per-exposure `exposureRatingResponse`, and the
                      full-term policy rating containers). Absent when the rate
                      failed.
                    additionalProperties: true
                  diagnostics:
                    type: array
                    description: >
                      Rating diagnostics. Present with `severity: error` entries

                      when the rate failed (in which case `data` is absent), or

                      with `severity: warning` entries beside a successful
                      `data`.
                    items:
                      $ref: '#/components/schemas/RatingDiagnostic'
              examples:
                ratedQuote:
                  summary: Rated saved quote
                  value:
                    data:
                      quoteType: newBusiness
                      quoteNumber: Q-000123
                      quoteStatus: inProgress
                      primaryInsured:
                        id: 550e8400-e29b-41d4-a716-446655440001
                        exposureName: Acme Co
                        exposureRatingResponse:
                          premium: 1000
                      otherExposures:
                        - id: 550e8400-e29b-41d4-a716-446655440002
                          exposureName: Beta LLC
                          exposureRatingResponse:
                            premium: 1000
                      fullTermPolicyRatingResult:
                        policyPremium: 3000
                        policyGrandTotal: 3500
                erroredRate:
                  summary: Rating failed — diagnostics returned, no data
                  value:
                    diagnostics:
                      - severity: error
                        code: inscipher-tax-calculation-failed
                        message: >-
                          An error occurred - please contact support, the
                          technical details are: InsCipher tax calculation
                          failed for exposure: server_error
        '400':
          description: >
            `ratingWorkflowName` is missing or names no configured workflow, a

            rating target the selected workflow requires (e.g. exposures) is
            empty

            or missing on the quote, or the workflow's configured preconditions
            are

            unmet, or the saved quote's stored data no longer validates against
            the

            current field configuration (the identical structured `400` the

            full-body endpoint returns for the same data), or the saved quote's

            `quoteType` is `cancellation` or `reinstatement`.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              examples:
                unknownWorkflow:
                  summary: Unknown rating workflow name
                  value:
                    error:
                      code: unknown-rating-workflow-name
                      message: >-
                        No rating workflow named "premium" is configured;
                        available: standard
                missingWorkflow:
                  summary: No ratingWorkflowName supplied
                  value:
                    error:
                      code: no-rating-workflow-name-supplied
                      message: >-
                        No rating workflow name was supplied; pass
                        ratingWorkflowName on the rate request as one of:
                        standard
                targetMissing:
                  summary: A rating target the workflow requires is empty or missing
                  value:
                    error:
                      code: rating-workflow-target-missing
                      message: >-
                        Rating workflow "standard" targets
                        "quote.otherExposures", which is empty or missing on the
                        quote after hydration
                preconditionsUnmet:
                  summary: The workflow's configured preconditions are unmet
                  value:
                    error:
                      code: rating-workflow-preconditions-unmet
                      message: >-
                        Rating workflow "standard" has 1 unmet precondition(s):
                        Add at least one exposure before rating
                staleConfig:
                  summary: Stored quote data no longer validates against current config
                  value:
                    error:
                      code: InvalidFieldModelV1Data
                      message: Field 'premiumEstimate' expected number, got string
                unsupportedQuoteType:
                  summary: The quote type preserves rating instead of repricing
                  value:
                    error:
                      code: InvalidRequest
                      message: >-
                        Reinstatement quotes cannot be rated: reinstatement
                        preserves the source policy rating result and restores
                        pre-cancellation pricing
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          description: >
            No quote with the given id exists for this company — the id is
            unknown,

            the quote was deleted, it belongs to another company, or it names a

            non-quote entity.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              examples:
                notFound:
                  summary: Unknown quote id
                  value:
                    error:
                      code: NotFoundError
                      message: Quote not found
        '422':
          description: The company has no rating workflows configured.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              examples:
                noWorkflows:
                  summary: No rating workflows configured
                  value:
                    error:
                      code: no-rating-workflows-configured
                      message: >-
                        No rating workflows are configured for this company;
                        rating requires a configured rating workflow
        '500':
          $ref: '#/components/responses/InternalServerError'
components:
  parameters:
    companyId:
      name: companyId
      in: path
      required: true
      schema:
        type: string
        format: uuid
      description: Company identifier
    quoteIdPath:
      name: quoteId
      in: path
      required: true
      schema:
        type: string
        format: uuid
      description: Quote identifier
  schemas:
    RatingDiagnostic:
      type: object
      description: >
        A rating diagnostic — the rate ran and this is what it has to report.

        `severity: error` entries explain why a rate failed (a failed rate
        returns

        HTTP `200` with `diagnostics` and **no `data`** — the missing `data` is
        the

        failure signal). `severity: warning` entries ride alongside a successful

        `data`, so the presence of diagnostics alone does not mean the rate
        failed.
      required:
        - severity
        - code
        - message
      properties:
        severity:
          type: string
          enum:
            - error
            - warning
          description: >
            `error` — the rate failed and no rated quote is returned. `warning`
            —

            informational; it does not by itself fail the rate. Warnings usually

            ride beside a successful `data`, but warnings emitted before a
            failing

            step also appear on a failed rate's diagnostics — always check for
            the

            presence of `data`, never for warning entries, to detect success.
        code:
          type: string
          description: |
            Stable, machine-readable failure code, safe to branch on (e.g.
            `inscipher-tax-calculation-failed`, `rating-service-error`).
          example: inscipher-tax-calculation-failed
        message:
          type: string
          description: Human-readable description of what went wrong.
          example: Rating failed - please contact support.
        location:
          type: object
          description: >
            Where in the rating workflow the diagnostic arose. Present when a
            rater

            reported the diagnostic mid-run (the engine stamps the stage,
            target,

            and rated window(s)) — including most rating-vendor failures, which
            the

            failing stage's rater now reports itself; absent for failures
            classified

            outside any one stage (e.g. a rating-service transport failure).
          required:
            - stageIndex
            - raterDebugName
            - segmentWindows
          properties:
            stageIndex:
              type: integer
              minimum: 0
              description: 0-based index into the rating workflow's stages.
            raterDebugName:
              type: string
              description: The configured debug name of the stage's rater.
              example: exposure-rater-1
            targetPath:
              type: string
              description: |
                The rated target that produced the diagnostic; absent for a
                stage-level failure with no single target.
              example: quote.exposures[0]
            segmentWindows:
              type: array
              description: >
                The rated window(s) the diagnostic applies to, as ISO-8601

                date-time instants. One entry for a per-segment stage; a
                full-term

                stage lists every window its target covers.
              items:
                type: object
                required:
                  - startDate
                  - endDate
                properties:
                  startDate:
                    type: string
                    format: date-time
                  endDate:
                    type: string
                    format: date-time
    ErrorResponse:
      type: object
      description: Standard error response for all external API endpoints
      required:
        - error
      properties:
        error:
          type: object
          required:
            - code
            - message
          properties:
            code:
              type: string
              description: Machine-readable error code
              example: VALIDATION_ERROR
            message:
              type: string
              description: Human-readable error message
              example: 'submissionId: Required field is missing'
            userMessages:
              type: array
              description: >-
                Clean, verbatim-displayable messages — one entry per failure,
                free of error-code tags, field paths, and internal noise.
                Suitable for showing to end users as-is.
              items:
                type: string
              example:
                - Exposures of type 'company' require an address
            details:
              type: array
              description: Additional details for validation errors (field-level errors)
              items:
                type: object
                properties:
                  field:
                    type: string
                    description: The field that caused the error
                    example: submissionId
                  code:
                    type: string
                    description: Stable problem code for this individual validation failure
                    example: BLANK_LIST_ELEMENT
                  reason:
                    type: string
                    description: Stable reason the value violates its canonical contract
                    example: blank-list-element
                  expected:
                    type: string
                    description: The expected canonical value contract
                    example: nonblank trimmed string
                  message:
                    type: string
                    description: Description of the field error
                    example: Required field is missing
  responses:
    Unauthorized:
      description: Unauthorized - Invalid or missing API key
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          examples:
            missingApiKey:
              summary: Missing API key
              value:
                error:
                  code: AuthenticationError
                  message: API key authentication required
                  userMessages:
                    - API key authentication required
            invalidApiKey:
              summary: >-
                Invalid API key (e.g. unknown key, or a Bearer token used
                instead of an API key)
              value:
                error:
                  code: AuthenticationError
                  message: Invalid API key
                  userMessages:
                    - Invalid API key
    Forbidden:
      description: Forbidden - Insufficient permissions
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          examples:
            insufficientPermissions:
              summary: Insufficient permissions
              value:
                error:
                  code: AuthorizationError
                  message: User is not authorized to perform the requested action
                  userMessages:
                    - User is not authorized to perform the requested action
            companyMismatch:
              summary: A valid API key naming another company in the URL
              value:
                error:
                  code: AuthorizationError
                  message: API key is not scoped to the requested company
                  userMessages:
                    - API key is not scoped to the requested company
    InternalServerError:
      description: Internal Server Error - Unexpected error occurred
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          examples:
            internalError:
              summary: Unexpected server error
              value:
                error:
                  code: UncaughtActionError
                  message: Uncaught error occurred in <actionName>
                  userMessages:
                    - An unexpected error occurred. Please try again later.
  securitySchemes:
    ApiKeyAuth:
      type: apiKey
      in: header
      name: Authorization
      description: >-
        API key authentication. Send your raw API key as the `Authorization`
        header value with NO scheme prefix — `Authorization: YOUR-API-KEY`. Do
        NOT prefix it with `Bearer ` or `ApiKey `, and do not use an `X-API-Key`
        header; those are not accepted.

````