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

# Endorse Policy Transaction

> Applies an ENDORSE transaction to an existing policy. An endorsement carries one
or more of **four channels**. The engine recomputes segments after applying every
channel — adjacent segments with identical data are automatically merged — and the
response includes the full resulting segment set.

**Input channel:**

- **`deltas`** — changes to policy field data. Each carries its own
  `startDate` / `endDate` within the policy term, a `path`, an `action`
  (Add / Remove / Overwrite), and a `value`.

**Amending the term.** Shortening a term is a `deltas` write to the ROOT
`policy.policyEndDate` (or `policy.policyStartDate`) stating the **whole term** as
its window. There is no separate policy-info channel — the retired `fullTermDeltas`
container channel was removed once the root fields became the single writable
source.

**Whole-term policy fields.** Four ROOT paths hold values that are invariant across
the policy term — `policy.policyNumber`, `policy.policyStartDate`,
`policy.policyEndDate` and `policy.previousPolicy`. A delta on `deltas` that touches
one of them (at any depth, and including an ancestor path such as a whole-`policy`
Overwrite) must state the **whole term** as its window (`startDate` = the policy start,
`endDate` = the policy end) or the write is rejected.

**A term bound may not move outward**, through either input channel and at any path
depth: moving `policyEndDate` later or `policyStartDate` earlier is rejected
(`TermLengtheningNotSupported`), because no endorsement path can create the extra days.

**Derived channels (additive on either input channel):**

- **`fullTermPricingInfo`** — whole-object overwrite of the policy-root pricing
  contract. Supply `pricingComponents` (each `{label, group, kind, value[,
  earningBasis]}`); the five rollups (`premium`, `taxes`, `fees`,
  `brokerCommission`, `programCommission`) are computed by the platform from the
  components — any caller-supplied rollup value is ignored and recomputed.
- **`fullTermPolicyRatingResult`** — whole-object overwrite of the policy-root canonical
  rating result (the twin of `fullTermPricingInfo`).
- **`crossSegmentRatingOutputs`** — element-level rating output, `[{ path, value }]`. Each
  `path` terminates at a `crossSegmentRatingOutputs` container on a list element (or the
  policy); `value` is the whole rating-output object for that host. There is no action
  (always an Overwrite) and no dates — the server derives each write's range from the
  host's presence across segments, so it applies cleanly to part-term hosts.

At least one channel is required.

**Path syntax — predicate addressing.** Index into a list by a predicate on any field:
`policy.exposures[id = '<uuid>'].bedCount`,
`policy.coverages[coverageType = 'GL'].limits[name = 'occurrence']`. The predicate must
resolve to **exactly one** element wherever it is applied (throws on zero or multiple
matches) — this uniqueness rule is the cross-segment identity guarantee.

**Policy invoices.** Optionally send `invoicePlan`, a fully explicit
keep/void/create plan. Nothing is defaulted or inferred. Once active
invoices exist, a pricing restatement must carry a conserving plan for the
new target; the version and invoices commit atomically.

**Required permission:** `policy:update`




## OpenAPI

````yaml /openapi/generated-external-api.yaml post /api/v1/companies/{companyId}/policies/{policyId}/transaction/endorse
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}/policies/{policyId}/transaction/endorse:
    post:
      tags:
        - Field Model Policy Transactions
      summary: Endorse Policy Transaction
      description: >
        Applies an ENDORSE transaction to an existing policy. An endorsement
        carries one

        or more of **four channels**. The engine recomputes segments after
        applying every

        channel — adjacent segments with identical data are automatically merged
        — and the

        response includes the full resulting segment set.


        **Input channel:**


        - **`deltas`** — changes to policy field data. Each carries its own
          `startDate` / `endDate` within the policy term, a `path`, an `action`
          (Add / Remove / Overwrite), and a `value`.

        **Amending the term.** Shortening a term is a `deltas` write to the ROOT

        `policy.policyEndDate` (or `policy.policyStartDate`) stating the **whole
        term** as

        its window. There is no separate policy-info channel — the retired
        `fullTermDeltas`

        container channel was removed once the root fields became the single
        writable

        source.


        **Whole-term policy fields.** Four ROOT paths hold values that are
        invariant across

        the policy term — `policy.policyNumber`, `policy.policyStartDate`,

        `policy.policyEndDate` and `policy.previousPolicy`. A delta on `deltas`
        that touches

        one of them (at any depth, and including an ancestor path such as a
        whole-`policy`

        Overwrite) must state the **whole term** as its window (`startDate` =
        the policy start,

        `endDate` = the policy end) or the write is rejected.


        **A term bound may not move outward**, through either input channel and
        at any path

        depth: moving `policyEndDate` later or `policyStartDate` earlier is
        rejected

        (`TermLengtheningNotSupported`), because no endorsement path can create
        the extra days.


        **Derived channels (additive on either input channel):**


        - **`fullTermPricingInfo`** — whole-object overwrite of the policy-root
        pricing
          contract. Supply `pricingComponents` (each `{label, group, kind, value[,
          earningBasis]}`); the five rollups (`premium`, `taxes`, `fees`,
          `brokerCommission`, `programCommission`) are computed by the platform from the
          components — any caller-supplied rollup value is ignored and recomputed.
        - **`fullTermPolicyRatingResult`** — whole-object overwrite of the
        policy-root canonical
          rating result (the twin of `fullTermPricingInfo`).
        - **`crossSegmentRatingOutputs`** — element-level rating output, `[{
        path, value }]`. Each
          `path` terminates at a `crossSegmentRatingOutputs` container on a list element (or the
          policy); `value` is the whole rating-output object for that host. There is no action
          (always an Overwrite) and no dates — the server derives each write's range from the
          host's presence across segments, so it applies cleanly to part-term hosts.

        At least one channel is required.


        **Path syntax — predicate addressing.** Index into a list by a predicate
        on any field:

        `policy.exposures[id = '<uuid>'].bedCount`,

        `policy.coverages[coverageType = 'GL'].limits[name = 'occurrence']`. The
        predicate must

        resolve to **exactly one** element wherever it is applied (throws on
        zero or multiple

        matches) — this uniqueness rule is the cross-segment identity guarantee.


        **Policy invoices.** Optionally send `invoicePlan`, a fully explicit

        keep/void/create plan. Nothing is defaulted or inferred. Once active

        invoices exist, a pricing restatement must carry a conserving plan for
        the

        new target; the version and invoices commit atomically.


        **Required permission:** `policy:update`
      operationId: endorsePolicyTransaction
      parameters:
        - $ref: '#/components/parameters/companyId'
        - $ref: '#/components/parameters/policyIdPath'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              additionalProperties: false
              required:
                - effectiveDate
              properties:
                effectiveDate:
                  type: string
                  format: date
                  description: >
                    The effective date of the endorsement in ISO 8601 format. It
                    must fall

                    within the policy term.
                transactionTimestamp:
                  type: string
                  format: date-time
                  description: >
                    When the business decision was made. Defaults to the current
                    time if omitted.

                    Set explicitly for imports (e.g., aligning to a bordereau
                    booking date).
                displayAuthor:
                  type: string
                  maxLength: 255
                  description: >-
                    Optional user-visible author label (trimmed; must be
                    non-empty). When set, the transaction is displayed as filed
                    by this label (e.g. "Data Import") instead of the acting
                    user; audit attribution (`createdBy`) stays server-set.
                deltas:
                  type: array
                  description: >
                    Policy-data deltas. Each delta specifies a date range
                    (`startDate` /

                    `endDate`) within the policy term, a predicate path, an
                    action

                    (Add / Remove / Overwrite), and the new value. Paths must
                    not contain any

                    reserved full-term container (`fullTermPricingInfo`,

                    `fullTermPolicyRatingResult`, `crossSegmentRatingOutputs`) —
                    those have

                    their own channel. A delta on one of the four whole-term
                    ROOT paths

                    (`policy.policyNumber`, `policy.policyStartDate`,
                    `policy.policyEndDate`,

                    `policy.previousPolicy`) must span the whole term.
                  items:
                    type: object
                    required:
                      - startDate
                      - endDate
                      - path
                      - action
                      - value
                    properties:
                      startDate:
                        type: string
                        format: date
                        description: >-
                          Start of the date range this delta applies to. Must be
                          `<=` endDate.
                      endDate:
                        type: string
                        format: date
                        description: End of the date range this delta applies to.
                      path:
                        type: string
                        description: >
                          Predicate path into the policy data (e.g.
                          `policy.annualPremium`,

                          `policy.exposures`, `policy.exposures[id =
                          '<uuid>'].bedCount`). Must not

                          contain a reserved full-term container.
                      action:
                        type: string
                        enum:
                          - Add
                          - Remove
                          - Overwrite
                        description: >
                          Delta action. `Overwrite` overwrites the value at the
                          path. `Add` appends

                          to a collection with set semantics (objects matched by
                          `id`, primitives by

                          equality; no-op if already present). `Remove` removes
                          matching values from a

                          collection; no-op if not present.
                      value:
                        description: >-
                          The new value to set at the path. Type depends on the
                          field.
                fullTermPricingInfo:
                  type: object
                  description: >
                    Optional whole-object overwrite of the policy-root full-term
                    pricing

                    contract. Supply `pricingComponents` (each `{label, group,
                    kind, value[,

                    earningBasis]}`; `kind` one of `Premium`, `Taxes`, `Fees`,

                    `BrokerCommission`, `ProgramCommission`, `Other`; `value` a
                    plain number;

                    `earningBasis` optional — omitted means pro-rata). The five
                    rollups

                    (`premium`, `taxes`, `fees`, `brokerCommission`,
                    `programCommission`)

                    are computed by the platform from the components;
                    caller-supplied rollup

                    values are ignored and recomputed. Additive on either input
                    channel.
                  additionalProperties: true
                fullTermPolicyRatingResult:
                  type: object
                  description: >
                    Optional whole-object overwrite of the policy-root canonical
                    rating result.

                    The twin of `fullTermPricingInfo`; additive on either input
                    channel.
                  additionalProperties: true
                crossSegmentRatingOutputs:
                  type: array
                  description: >
                    Optional element-level rating output. Each entry overwrites
                    the

                    `crossSegmentRatingOutputs` container at its host; the
                    server derives the write

                    range from the host's presence across segments (write where
                    the host-selector

                    resolves to exactly one element, skip where zero, throw on
                    many or if it never

                    resolves). Additive; ENDORSE only.
                  items:
                    type: object
                    required:
                      - path
                      - value
                    properties:
                      path:
                        type: string
                        description: >
                          Predicate path terminating at a
                          `crossSegmentRatingOutputs` container on a

                          list element or the policy (e.g.

                          `policy.exposures[id =
                          '<uuid>'].crossSegmentRatingOutputs`,

                          `policy.crossSegmentRatingOutputs`).
                      value:
                        type: object
                        description: The whole rating-output object for that host.
                        additionalProperties: true
                invoicePlan:
                  $ref: '#/components/schemas/PolicyInvoiceTransactionPlan'
            examples:
              midTermPremiumChange:
                summary: Mid-term premium adjustment + billing
                value:
                  effectiveDate: '2025-04-01'
                  deltas:
                    - startDate: '2025-04-01'
                      endDate: '2025-12-31'
                      path: policy.annualPremium
                      action: Overwrite
                      value: 102000
                  fullTermPricingInfo:
                    pricingComponents:
                      - label: Policy Premium
                        group: Policy Invoice
                        kind: Premium
                        value: 102000
                      - label: Policy Fee
                        group: Policy Invoice
                        kind: Fees
                        value: 500
              addExposure:
                summary: Add exposure mid-term
                value:
                  effectiveDate: '2025-06-01'
                  deltas:
                    - startDate: '2025-06-01'
                      endDate: '2025-12-31'
                      path: policy.exposures
                      action: Add
                      value:
                        id: 550e8400-e29b-41d4-a716-446655440020
                        exposureType: MedicalFacility
                        bedCount: 80
                  fullTermPricingInfo:
                    pricingComponents:
                      - label: Policy Premium
                        group: Policy Invoice
                        kind: Premium
                        value: 120000
                      - label: Policy Fee
                        group: Policy Invoice
                        kind: Fees
                        value: 500
              shortenTerm:
                summary: Shorten the term (a whole-term root write on `deltas`)
                description: >
                  The term bound is a ROOT field, so the delta must state the
                  whole term as

                  its window.
                value:
                  effectiveDate: '2025-01-01'
                  deltas:
                    - startDate: '2025-01-01'
                      endDate: '2025-12-31'
                      path: policy.policyEndDate
                      action: Overwrite
                      value:
                        year: 2025
                        month: 9
                        day: 30
                        timezone: America/New_York
              elementRatingOutput:
                summary: Element-level rating output for an exposure
                value:
                  effectiveDate: '2025-06-01'
                  deltas:
                    - startDate: '2025-06-01'
                      endDate: '2025-12-31'
                      path: >-
                        policy.exposures[id =
                        '550e8400-e29b-41d4-a716-446655440010'].bedCount
                      action: Overwrite
                      value: 110
                  crossSegmentRatingOutputs:
                    - path: >-
                        policy.exposures[id =
                        '550e8400-e29b-41d4-a716-446655440010'].crossSegmentRatingOutputs
                      value:
                        annualPremium: 96000
                        dailyProratedPremium: 263
              withTimestamp:
                summary: Endorsement with explicit transaction timestamp
                value:
                  effectiveDate: '2025-04-01'
                  transactionTimestamp: '2025-03-28T14:30:00Z'
                  deltas:
                    - startDate: '2025-04-01'
                      endDate: '2025-12-31'
                      path: policy.customPolicyText
                      action: Overwrite
                      value: updated value
      responses:
        '201':
          description: Endorsement applied successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PolicyTransactionVersionResponse'
              examples:
                success:
                  summary: Endorsement transaction response
                  value:
                    policyId: 550e8400-e29b-41d4-a716-446655440001
                    policyVersion: 2
                    transactionId: 550e8400-e29b-41d4-a716-446655440030
                    startDate: '2025-01-01'
                    endDate: '2025-12-31'
                    createdAt: '2025-04-01T10:30:00.000Z'
                    policyNumber: POL-2025-0001
                    policyStartDate:
                      year: 2025
                      month: 1
                      day: 1
                      timezone: America/New_York
                    policyEndDate:
                      year: 2025
                      month: 12
                      day: 31
                      timezone: America/New_York
                    fullTermPricingInfo:
                      premium: 102000
                      taxes: 0
                      fees: 500
                      brokerCommission: 0
                      programCommission: 0
                      pricingComponents:
                        - label: Policy Premium
                          group: Policy Invoice
                          kind: Premium
                          earningBasis: null
                          value: 102000
                        - label: Policy Fee
                          group: Policy Invoice
                          kind: Fees
                          earningBasis: null
                          value: 500
                    fullTermPolicyRatingResult: null
                    segments:
                      - startDate: '2025-01-01'
                        endDate: '2025-03-31'
                        data:
                          policyStatus: active
                          annualPremium: 85000
                          fullTermPricingInfo:
                            premium: 102000
                            taxes: 0
                            fees: 500
                            brokerCommission: 0
                            programCommission: 0
                            pricingComponents:
                              - label: Policy Premium
                                group: Policy Invoice
                                kind: Premium
                                earningBasis: null
                                value: 102000
                              - label: Policy Fee
                                group: Policy Invoice
                                kind: Fees
                                earningBasis: null
                                value: 500
                      - startDate: '2025-04-01'
                        endDate: '2025-12-31'
                        data:
                          policyStatus: active
                          annualPremium: 102000
                          fullTermPricingInfo:
                            premium: 102000
                            taxes: 0
                            fees: 500
                            brokerCommission: 0
                            programCommission: 0
                            pricingComponents:
                              - label: Policy Premium
                                group: Policy Invoice
                                kind: Premium
                                earningBasis: null
                                value: 102000
                              - label: Policy Fee
                                group: Policy Invoice
                                kind: Fees
                                earningBasis: null
                                value: 500
        '400':
          description: Validation error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              examples:
                noChannel:
                  summary: No channel provided
                  value:
                    error:
                      code: InvalidRequest
                      message: >-
                        At least one channel is required (deltas,
                        fullTermPricingInfo, fullTermPolicyRatingResult, or
                        crossSegmentRatingOutputs)
                termLengthening:
                  summary: A write that would lengthen the policy term
                  value:
                    error:
                      code: TermLengtheningNotSupported
                      message: >-
                        Cannot lengthen the policy term: policy.policyEndDate
                        moves the term end from 2025-12-31 to 2026-03-31, which
                        claims days no endorsement can create (empty-day
                        generation is new-business-only). Shortening the term is
                        allowed — send it as a whole-term root write on
                        `deltas`. A real term extension is tracked in #5844.
                effectiveDateOutsideTerm:
                  summary: Transaction effectiveDate outside the policy term
                  value:
                    error:
                      code: InvalidRequest
                      message: >-
                        Transaction effectiveDate (2026-03-01) must be within
                        policy period [2025-01-01, 2025-12-31]
                timestampNotMonotonic:
                  summary: >-
                    transactionTimestamp earlier than the latest existing
                    transaction
                  value:
                    error:
                      code: InvalidRequest
                      message: >-
                        transactionTimestamp (2025-03-28T14:30:00Z) is earlier
                        than the latest existing transaction on this policy
                        (2025-04-01T10:30:00.000Z)
                noExistingVersion:
                  summary: Policy has no NEW_BUSINESS transaction
                  value:
                    error:
                      code: InvalidRequest
                      message: >-
                        Policy has no existing version — NEW_BUSINESS must be
                        created first
                deltaOutsidePolicyPeriod:
                  summary: Delta date range outside policy term
                  value:
                    error:
                      code: InvalidDelta
                      message: >-
                        Delta date range [2026-06-01, 2026-12-31] falls outside
                        policy period [2025-01-01, 2025-12-31]
                deltaStartAfterEnd:
                  summary: Delta startDate after endDate
                  value:
                    error:
                      code: InvalidDelta
                      message: >-
                        Delta startDate (2025-12-31) must be <= endDate
                        (2025-01-01)
                deltaStartNotEffectiveDate:
                  summary: >-
                    Per-segment delta startDate does not equal the transaction
                    effectiveDate
                  value:
                    error:
                      code: InvalidDelta
                      message: >-
                        Per-segment delta startDate (2025-05-01) for path
                        "policy.annualPremium" must equal transaction
                        effectiveDate (2025-04-01)
                duplicatePath:
                  summary: Two deltas in one transaction share the same path
                  value:
                    error:
                      code: InvalidDelta
                      message: >-
                        Two deltas in this transaction share the path
                        "policy.annualPremium" — within-transaction conflicts
                        cannot be resolved by insertion order
                pathPrefixConflict:
                  summary: >-
                    One delta targets an object and another targets its
                    descendant
                  value:
                    error:
                      code: InvalidDelta
                      message: >-
                        Delta paths "policy.exposures" and "policy.exposures[id
                        = '550e8400-e29b-41d4-a716-446655440010'].bedCount"
                        overlap — a delta cannot target both an object and one
                        of its descendants in the same transaction
                fullTermPathInDeltas:
                  summary: Reserved full-term container sent via deltas
                  value:
                    error:
                      code: InvalidDelta
                      message: >-
                        Invalid deltas path "policy.fullTermPricingInfo.premium"
                        — full-term container paths cannot be written by a
                        caller. The pricing and rating-result containers have
                        their own endorse channels
                wholeTermWindowRequired:
                  summary: A whole-term ROOT field delta stated over a part-term window
                  value:
                    error:
                      code: InvalidDelta
                      message: >-
                        Delta path "policy.policyEndDate" is invariant across
                        the policy term, so its window must be the whole term
                        [2025-01-01, 2025-12-31] — got [2025-04-01, 2025-12-31]
                ambiguousPredicate:
                  summary: Predicate path resolves to multiple elements
                  value:
                    error:
                      code: InvalidDelta
                      message: >-
                        Predicate exposures[exposureType = 'MedicalFacility']
                        matched 2 elements — it must resolve to exactly one
                predicateMatchesNoElement:
                  summary: Predicate path resolves to zero elements
                  value:
                    error:
                      code: InvalidDelta
                      message: >-
                        No element in 'exposures' matches id =
                        '550e8400-e29b-41d4-a716-446655440099'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          description: Policy or an invoice referenced by invoicePlan not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              examples:
                policyNotFound:
                  summary: Policy does not exist
                  value:
                    error:
                      code: NOT_FOUND
                      message: Policy 550e8400-e29b-41d4-a716-446655440099 not found
        '409':
          description: >-
            A void watermark in invoicePlan is stale; no policy version or
            invoice action was committed.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '422':
          description: >-
            invoicePlan failed policy-invoice binding, conservation,
            payment-lock, or restating preconditions; no policy version or
            invoice action was committed.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          $ref: '#/components/responses/InternalServerError'
components:
  parameters:
    companyId:
      name: companyId
      in: path
      required: true
      schema:
        type: string
        format: uuid
      description: Company identifier
    policyIdPath:
      name: policyId
      in: path
      required: true
      schema:
        type: string
        format: uuid
      description: Policy identifier
  schemas:
    PolicyInvoiceTransactionPlan:
      type: object
      additionalProperties: false
      required:
        - incurredDate
        - voidInvoices
        - creates
      properties:
        incurredDate:
          type: string
          format: date
          description: >-
            Explicit recognition date for non-scheduled creates. It is never
            inferred from a transaction effective date or the server clock.
        voidInvoices:
          type: array
          items:
            $ref: '#/components/schemas/PolicyInvoiceBatchVoid'
        creates:
          type: array
          items:
            $ref: '#/components/schemas/PolicyInvoiceBatchCreate'
      description: >-
        A fully explicit, detached policy-invoice batch. Existing invoices not
        named in voidInvoices are kept. The complete kept-plus-created set must
        conserve every bound component of the policy's current pricing contract.
    PolicyTransactionVersionResponse:
      type: object
      description: >
        Response returned by policy transaction endpoints. Contains the policy
        version

        produced by the transaction, including all derived segments.
      required:
        - policyId
        - policyVersion
        - transactionId
        - startDate
        - endDate
        - createdAt
        - segments
      properties:
        policyId:
          type: string
          format: uuid
          description: Policy identifier
        policyVersion:
          type: integer
          description: Sequential version number produced by this transaction
        transactionId:
          type: string
          format: uuid
          description: Identifier of the transaction that produced this version
        startDate:
          type: string
          format: date
          description: Policy term start date (ISO 8601)
        endDate:
          type: string
          format: date
          description: Policy term end date (ISO 8601)
        createdAt:
          type: string
          format: date-time
          description: When the transaction was created (ISO 8601)
        primaryInsuredName:
          type: string
          nullable: true
          description: >
            Plain-text primary-insured name, read from the policy's own

            `primaryInsuredName` field — the source of truth for the primary
            insured.

            Reported as of the END of

            the term, so a policy whose insured changed mid-term returns the
            later name;

            `segments[]` carries the per-segment history. Null only when the
            version

            carries no policy data.
        primaryInsuredId:
          type: string
          nullable: true
          description: |
            Id of the entity behind `primaryInsuredName`. Null when the policy's
            configuration does not populate it.
        policyNumber:
          type: string
          nullable: true
          description: >
            The policy number, read from the policy's own `policyNumber` field —
            the

            source of truth, invariant across the whole term. Null only when the
            version

            carries no policy data.
        policyStartDate:
          type: object
          nullable: true
          description: >
            Policy term start date as the structured date object, read from the
            policy's

            own `policyStartDate` field — the source of truth, invariant across
            the whole

            term. This is **not** `startDate` above: that is the ISO

            span this version covers, which a cancellation makes shorter than
            the term.

            Null only when the version carries no policy data.
          allOf:
            - $ref: '#/components/schemas/Fmv1Date'
        policyEndDate:
          type: object
          nullable: true
          description: >
            Policy term end date as the structured date object, read from the
            policy's own

            `policyEndDate` field — the source of truth, invariant across the
            whole term.

            This is **not** `endDate` above: that is the ISO

            span this version covers. Null only when the version carries no
            policy data.
          allOf:
            - $ref: '#/components/schemas/Fmv1Date'
        fullTermPricingInfo:
          type: object
          nullable: true
          description: >
            The policy's full-term pricing contract, hoisted as a read-once
            convenience

            (also duplicated in every segment): `pricingComponents` (each

            `{label, group, kind, value[, earningBasis]}`) plus the five
            server-computed,

            read-only rollups (`premium`, `taxes`, `fees`, `brokerCommission`,

            `programCommission` — each the sum of its kind's components).
          additionalProperties: true
        fullTermPolicyRatingResult:
          type: object
          nullable: true
          description: >
            Derived canonical policy-level rating result for the full term,
            hoisted as a

            read-once convenience (also duplicated in every segment).
            Element-level rating

            output (`crossSegmentRatingOutputs`) stays inline at its host and is
            not hoisted.
          additionalProperties: true
        segments:
          type: array
          description: >
            Derived segments for this policy version. Each segment represents a
            maximal contiguous

            date range where policy state is identical. Adjacent segments with
            identical data are

            automatically merged.
          items:
            $ref: '#/components/schemas/PolicyTransactionSegmentResponse'
    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
    PolicyInvoiceBatchVoid:
      type: object
      additionalProperties: false
      required:
        - invoiceId
        - headJournalId
      properties:
        invoiceId:
          type: string
          format: uuid
        headJournalId:
          type: string
          format: uuid
          description: >-
            The invoice watermark read while composing the plan. A stale
            watermark rejects the whole batch with 409.
    PolicyInvoiceBatchCreate:
      type: object
      additionalProperties: false
      required:
        - group
        - lineItems
      properties:
        group:
          type: string
          minLength: 1
          description: Policy invoice type name, matching a pricing component group.
        dueDate:
          type: string
          format: date
        scheduledDate:
          type: string
          format: date
          description: >-
            Installment recognition anchor. When present, incurredDate for this
            invoice is this date and the invoice remains scheduled until it
            arrives.
        payeeId:
          type: string
          format: uuid
          description: Canonical Person, Organization, or Exposure entity billed or paid.
        memo:
          type: string
        lineItems:
          type: array
          minItems: 1
          items:
            $ref: '#/components/schemas/PolicyInvoiceBatchCreateLine'
    Fmv1Date:
      type: object
      description: >
        Field Model V1 object primitive representing a calendar date with an

        explicit timezone.


        `day`, `month`, and `year` are required when this object is provided in
        a

        write payload; `timezone` is optional. Partial date components are

        rejected with `400`.


        **Two accepted input shapes** — the API canonicalizes both into the

        internal `{ day, month, year, timezone }` form before storage:

        * `{ date: "YYYY-MM-DD", timezone: "America/New_York" }` — ISO form

        * `{ day, month, year, timezone }` — DMY form (returned in responses)


        Day, month, and year are 1-based integers. `timezone` is an IANA tz

        database identifier (e.g. "America/New_York", "UTC").
      required:
        - day
        - month
        - year
      properties:
        day:
          type: integer
          minimum: 1
          maximum: 31
          description: Day of month, 1-based (1-31)
        month:
          type: integer
          minimum: 1
          maximum: 12
          description: Month, 1-based (1=January, 12=December)
        year:
          type: integer
          description: Four-digit calendar year (e.g. 2026)
        timezone:
          type: string
          description: IANA timezone identifier (e.g. "America/New_York", "UTC")
    PolicyTransactionSegmentResponse:
      type: object
      description: >
        A derived policy segment representing a date range where policy state is
        identical.

        Contains the full policy data (policy-level fields and nested exposures)
        for this period.
      required:
        - startDate
        - endDate
        - data
      properties:
        startDate:
          type: string
          format: date
          description: Segment start date (ISO 8601)
        endDate:
          type: string
          format: date
          description: Segment end date (ISO 8601)
        data:
          type: object
          description: >
            Policy state for this segment: the policy-level fields and their
            nested

            exposure containers, at the top level of this object.


            Before 2026-08-05 this member was named `fieldModelV1Data` and
            wrapped the

            same fields in an extra `policy` key. Read `data.policyNumber` where
            you

            read `fieldModelV1Data.policy.policyNumber`.
          additionalProperties: true
    PolicyInvoiceBatchCreateLine:
      type: object
      additionalProperties: false
      required:
        - label
        - amountCents
      properties:
        label:
          type: string
          minLength: 1
          description: Line-item label from the pricing contract and bound invoice type.
        amountCents:
          type: integer
          description: Signed integer cents in the configured line-item type's own frame.
        memo:
          type: string
  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.

````