> ## 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 (Stateless)

> Rates an **already-saved** quote, named by id, and returns the rating
results — **without persisting anything**. The quote is never modified: no
field is written, no rating run is recorded, and the quote row is
byte-identical before and after. This is the by-id sibling of
`POST /api/v1/companies/{companyId}/quotes/rate`; the only difference is
where the field bag comes from — loaded from the saved quote here, supplied
in the request body there.

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).

**Required permission:** `company.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 (Stateless)
      description: >
        Rates an **already-saved** quote, named by id, and returns the rating

        results — **without persisting anything**. The quote is never modified:
        no

        field is written, no rating run is recorded, and the quote row is

        byte-identical before and after. This is the by-id sibling of

        `POST /api/v1/companies/{companyId}/quotes/rate`; the only difference is

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

        in the request body there.


        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).


        **Required permission:** `company.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 saved quote's data enriched with rating outputs. Nothing is
            persisted.
          content:
            application/json:
              schema:
                type: object
                required:
                  - data
                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).
                    additionalProperties: true
              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
        '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 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
                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:
    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
                  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.

````