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

> Rates the quote a create-quote request WOULD create, and returns the rating
results — **without persisting anything**. No quote is stored, no rating run
is recorded. Use it to preview premium for a prospective quote, or to rate a
quote you manage in your own system.

The request body carries the exact create-quote payload under `data` (the
same flat field bag you would `POST` to
`/api/v1/companies/{companyId}/entities/quote`), plus the
`ratingWorkflowName` naming which configured rating workflow to run.

**Semantics — "rate the quote this body would create."** The `data` bag is
validated with the identical create-quote pipeline (shape, resolution,
tenant invariants, entity invariants) with the same rules an external
create applies: embedded exposures must reference existing Exposure records
by `id` (id-less / draft embedded values are rejected). A body that
create-quote would reject fails here with the identical structured `400`.
Then the named rating workflow runs over the resolved quote.

Hosted rating supports `newBusiness`, `renewal`, and `endorsement` quote
types. `cancellation` and `reinstatement` return a structured
`400 InvalidRequest` before any rater or vendor call because those
transactions preserve the source policy rating result and derive or restore
pricing instead of repricing.

**Exposure id references are looked up and merged.** Because an API-key
caller references exposures by `id` (embedded exposures cannot be
inline-created over the API), each referenced Exposure's stored fields are
fetched and merged under the reference before rating, so the exposure is
rated against its real stored data rather than a blank record. Fields you
**supply inline win** over the stored values, per top-level field (the body
is treated as a draft-edit over the stored exposure). This lookup is
read-only — nothing is persisted. (Note: this is an interim behavior for
`EmbeddedExposure` exposure references; join-linked entities are not
hydrated.)

The `200` response echoes the same bag back 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/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/rate:
    post:
      tags:
        - Field Model Rating
      summary: Rate Quote (Stateless)
      description: >
        Rates the quote a create-quote request WOULD create, and returns the
        rating

        results — **without persisting anything**. No quote is stored, no rating
        run

        is recorded. Use it to preview premium for a prospective quote, or to
        rate a

        quote you manage in your own system.


        The request body carries the exact create-quote payload under `data`
        (the

        same flat field bag you would `POST` to

        `/api/v1/companies/{companyId}/entities/quote`), plus the

        `ratingWorkflowName` naming which configured rating workflow to run.


        **Semantics — "rate the quote this body would create."** The `data` bag
        is

        validated with the identical create-quote pipeline (shape, resolution,

        tenant invariants, entity invariants) with the same rules an external

        create applies: embedded exposures must reference existing Exposure
        records

        by `id` (id-less / draft embedded values are rejected). A body that

        create-quote would reject fails here with the identical structured
        `400`.

        Then the named rating workflow runs over the resolved quote.


        Hosted rating supports `newBusiness`, `renewal`, and `endorsement` quote

        types. `cancellation` and `reinstatement` return a structured

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

        transactions preserve the source policy rating result and derive or
        restore

        pricing instead of repricing.


        **Exposure id references are looked up and merged.** Because an API-key

        caller references exposures by `id` (embedded exposures cannot be

        inline-created over the API), each referenced Exposure's stored fields
        are

        fetched and merged under the reference before rating, so the exposure is

        rated against its real stored data rather than a blank record. Fields
        you

        **supply inline win** over the stored values, per top-level field (the
        body

        is treated as a draft-edit over the stored exposure). This lookup is

        read-only — nothing is persisted. (Note: this is an interim behavior for

        `EmbeddedExposure` exposure references; join-linked entities are not

        hydrated.)


        The `200` response echoes the same bag back 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: rateQuote
      parameters:
        - $ref: '#/components/parameters/companyId'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - data
              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.
                  example: standard
                data:
                  type: object
                  description: >
                    The create-quote payload — the flat field bag, unchanged.

                    Custom fields are validated against your company's field

                    configuration (unknown fields rejected, required fields

                    enforced, values matched to their configured types).
                    Embedded

                    exposure values are validated per-field against the Exposure

                    configuration and must reference existing Exposure records
                    by

                    `id`; each referenced exposure's stored fields are then
                    merged

                    in for rating, with any fields you supply inline winning
                    over

                    the stored values.
                  additionalProperties: true
            examples:
              newBusinessQuote:
                summary: Rate a new-business quote with embedded exposures
                value:
                  ratingWorkflowName: standard
                  data:
                    quoteType: newBusiness
                    primaryInsured:
                      id: 550e8400-e29b-41d4-a716-446655440001
                      exposureName: Acme Co
                    otherExposures:
                      - id: 550e8400-e29b-41d4-a716-446655440002
                        exposureName: Beta LLC
      responses:
        '200':
          description: The quote data enriched with rating outputs. Nothing is persisted.
          content:
            application/json:
              schema:
                type: object
                required:
                  - data
                properties:
                  data:
                    type: object
                    description: |
                      The same field bag from the request, enriched with rating
                      outputs (per-exposure `exposureRatingResponse`, and the
                      full-term policy rating containers).
                    additionalProperties: true
              examples:
                ratedQuote:
                  summary: Rated new-business quote
                  value:
                    data:
                      quoteType: newBusiness
                      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: >
            The `data` bag failed create-quote validation, `ratingWorkflowName`

            is missing or names no configured workflow, or a rating target the

            selected workflow requires (e.g. exposures) is empty or missing on
            the

            quote, or `quoteType` is `cancellation` or `reinstatement`.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              examples:
                invalidData:
                  summary: >-
                    Body create-quote would reject (embedded exposure missing
                    id)
                  value:
                    error:
                      code: InvalidEmbeddedExposureReference
                      message: embedded Exposure at 'primaryInsured' is missing an 'id'
                unsupportedQuoteType:
                  summary: The quote type preserves rating instead of repricing
                  value:
                    error:
                      code: InvalidRequest
                      message: >-
                        Cancellation quotes cannot be rated: cancellation
                        preserves the source policy rating result and derives
                        pricing from earned amounts
                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.exposures",
                        which is empty or missing on the quote after hydration
                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
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '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
  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.

````