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

# Bind Quote by Reference or by Value

> **Quote door by reference, value door by value**
([Invoicing a policy](/api-reference/invoicing/overview)). By reference,
the policy's invoices come from the quote, which the bind's `invoices`
names as on [Bind Quote](/api-reference/policies/bind-quote); by value,
they come from the request: the `invoicePlan` you send, or none.

Binds a policy transaction through your company's configured Conversion
Rules, in one of two forms — discriminated by the presence of `quoteId` in
the body:

- **By reference** — `{ "quoteId": …, "invoices": … }`: binds a persisted
  quote exactly like `POST …/quotes/{quoteId}/bind`, and `invoices` works
  the same: `generate` builds the invoices from the quote's invoice
  settings, `saved` binds the plan saved on the quote, and leaving it out
  binds none, refused while the quote holds a plan. It answers with the
  **full policy-version result** the transaction endpoints return instead
  of the bare `{ policyId }`.
- **By value** — `{ "transactionType": …, "data": …, "invoicePlan": … }`:
  the caller sends the whole change, so it sends the `invoicePlan` too, or
  none. Nothing is inferred. It binds an **unpersisted** Quote field bag —
  typically one returned by `POST …/quotes/generate` and edited
  client-side. No Quote row is created or linked; the transaction lands
  directly on the policy plane.

**What produces the policy writes.** Your company's
(`QUOTE_TO_POLICY`, `transactionType`) Conversion Rules are evaluated
server-side over `{ source: data, transaction }`. `NEW_BUSINESS` and
`RENEW` bind the converted bag as the new policy payload; `ENDORSE` diffs
the converted destinations against the segment in force at
`effectiveDate` — a destination no rule writes is left untouched. `CANCEL`
and `REINSTATE` are lifecycle transactions: the platform derives their
pricing itself. With invoicing enabled they store
`data.fullTermBillingInfo` as sent (see **Billing with invoicing
enabled** below); otherwise a `data` payload changes nothing beyond the
framework rows.

**Required policy fields come from the quote data.** A policy field that
no rule writes and no policy calculation fills has no value after the
bind. A required policy field, such as `policyNumber`, therefore reaches
the policy one of two ways: the Quote data carries a value that a rule
copies, or your configuration calculates it at bind (for example, from a
policy-number sequence). Export your configuration to see which applies to
each field. When neither supplies a value, the bind returns
`400 InvalidEntityShape` naming the field (for example,
`'policyNumber' is required but null`). By value, include the value in
`data` under the Quote field the rule reads (`data.policyNumber` for a rule
that copies `source.policyNumber`). By reference, set it on the quote with
[Update Entity](/api-reference/entities/update-entity)
(`PATCH …/entities/quote/{quoteId}`) before you bind.

**The server stores nothing between generate and bind.** There is no draft
session, token, or receipt. `expectedPolicyVersion` — echo it from
generate's `sourcePolicy.policyVersion` — is the ONLY precondition: when it
is stated and the source policy's version has moved, the bind is refused
with `409 PolicyVersionConflict` **without performing the transaction**.
Consequently a duplicated by-value `NEW_BUSINESS` bind mints a second
policy, exactly as a duplicated create-then-bind does today; deduplicate on
your side or bind new business by reference.

**Per-type field rules (by value).** `policyId` and `effectiveDate` are
required for every type except `NEW_BUSINESS`, which forbids them (its term
comes from the bag's own `policyStartDate` / `policyEndDate`). `endDate` is
an `ENDORSE`-only optional window end. `expectedPolicyVersion` is forbidden
for `NEW_BUSINESS` (no source policy to name).

**Checks.** The `quoteId` form runs the same checks as
`…/{quoteId}/bind`. The by-value form keeps its existing transaction
validation and financial-integrity rules; it creates no Quote resource.

**Invoices.** By reference, `invoices` works exactly as on
`…/{quoteId}/bind`, with the same refusals, and the form takes no
`invoicePlan`: put a plan you wrote on the quote first with
[Attach Quote Invoice Plan](/api-reference/invoicing/attach-quote-invoice-plan).
By value, `invoicePlan` is the plan the policy transactions take, which
[Invoice plans](/api-reference/invoicing/invoice-plans) describes; it
commits atomically with the policy version, and a change that moves the
billing an invoiced policy's invoices add up to needs one. The by-value
form takes no `invoices`. Either form's invoices require invoicing to be
enabled (otherwise `403 finv2-policy-invoicing-disabled`).

Both forms use the company’s explicitly authored Conversion Rules.

**Billing with invoicing enabled.** Stores the quote's or caller's billing as stated,
without scaling, restoring or carrying billing from the policy. A billed term must
restate `fullTermBillingInfo` on ENDORSE, CANCEL and REINSTATE; omission or unstated
billing returns `400 finv2-policy-billing-required`. A change that voids every active
invoice while any billing line still owes returns `400 finv2-policy-invoices-required`.
New terms and unbilled policies may have no billing. An uninvoiced policy may bind
with billing and no invoices; existing invoices must still add up to it, as
[Invoice plans](/api-reference/invoicing/invoice-plans) explains.

**Billing with invoicing disabled.** The policy stores null billing. A
non-null `fullTermBillingInfo` in the by-value `data`, malformed or not, or
held by the quote bound by reference, is refused with
`403 finv2-policy-invoicing-disabled`, and nothing is saved: send null or
leave it out. Companies awaiting their billing migration keep their
existing derivation and carry behavior while invoicing is disabled.

**Required permission:** `quote.bind`




## OpenAPI

````yaml /openapi/generated-external-api.yaml post /api/v1/companies/{companyId}/quotes/bind
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/bind:
    post:
      tags:
        - Field Model Policy Transactions
      summary: Bind Quote by Reference or by Value
      description: >
        **Quote door by reference, value door by value**

        ([Invoicing a policy](/api-reference/invoicing/overview)). By reference,

        the policy's invoices come from the quote, which the bind's `invoices`

        names as on [Bind Quote](/api-reference/policies/bind-quote); by value,

        they come from the request: the `invoicePlan` you send, or none.


        Binds a policy transaction through your company's configured Conversion

        Rules, in one of two forms — discriminated by the presence of `quoteId`
        in

        the body:


        - **By reference** — `{ "quoteId": …, "invoices": … }`: binds a
        persisted
          quote exactly like `POST …/quotes/{quoteId}/bind`, and `invoices` works
          the same: `generate` builds the invoices from the quote's invoice
          settings, `saved` binds the plan saved on the quote, and leaving it out
          binds none, refused while the quote holds a plan. It answers with the
          **full policy-version result** the transaction endpoints return instead
          of the bare `{ policyId }`.
        - **By value** — `{ "transactionType": …, "data": …, "invoicePlan": …
        }`:
          the caller sends the whole change, so it sends the `invoicePlan` too, or
          none. Nothing is inferred. It binds an **unpersisted** Quote field bag —
          typically one returned by `POST …/quotes/generate` and edited
          client-side. No Quote row is created or linked; the transaction lands
          directly on the policy plane.

        **What produces the policy writes.** Your company's

        (`QUOTE_TO_POLICY`, `transactionType`) Conversion Rules are evaluated

        server-side over `{ source: data, transaction }`. `NEW_BUSINESS` and

        `RENEW` bind the converted bag as the new policy payload; `ENDORSE`
        diffs

        the converted destinations against the segment in force at

        `effectiveDate` — a destination no rule writes is left untouched.
        `CANCEL`

        and `REINSTATE` are lifecycle transactions: the platform derives their

        pricing itself. With invoicing enabled they store

        `data.fullTermBillingInfo` as sent (see **Billing with invoicing

        enabled** below); otherwise a `data` payload changes nothing beyond the

        framework rows.


        **Required policy fields come from the quote data.** A policy field that

        no rule writes and no policy calculation fills has no value after the

        bind. A required policy field, such as `policyNumber`, therefore reaches

        the policy one of two ways: the Quote data carries a value that a rule

        copies, or your configuration calculates it at bind (for example, from a

        policy-number sequence). Export your configuration to see which applies
        to

        each field. When neither supplies a value, the bind returns

        `400 InvalidEntityShape` naming the field (for example,

        `'policyNumber' is required but null`). By value, include the value in

        `data` under the Quote field the rule reads (`data.policyNumber` for a
        rule

        that copies `source.policyNumber`). By reference, set it on the quote
        with

        [Update Entity](/api-reference/entities/update-entity)

        (`PATCH …/entities/quote/{quoteId}`) before you bind.


        **The server stores nothing between generate and bind.** There is no
        draft

        session, token, or receipt. `expectedPolicyVersion` — echo it from

        generate's `sourcePolicy.policyVersion` — is the ONLY precondition: when
        it

        is stated and the source policy's version has moved, the bind is refused

        with `409 PolicyVersionConflict` **without performing the transaction**.

        Consequently a duplicated by-value `NEW_BUSINESS` bind mints a second

        policy, exactly as a duplicated create-then-bind does today; deduplicate
        on

        your side or bind new business by reference.


        **Per-type field rules (by value).** `policyId` and `effectiveDate` are

        required for every type except `NEW_BUSINESS`, which forbids them (its
        term

        comes from the bag's own `policyStartDate` / `policyEndDate`). `endDate`
        is

        an `ENDORSE`-only optional window end. `expectedPolicyVersion` is
        forbidden

        for `NEW_BUSINESS` (no source policy to name).


        **Checks.** The `quoteId` form runs the same checks as

        `…/{quoteId}/bind`. The by-value form keeps its existing transaction

        validation and financial-integrity rules; it creates no Quote resource.


        **Invoices.** By reference, `invoices` works exactly as on

        `…/{quoteId}/bind`, with the same refusals, and the form takes no

        `invoicePlan`: put a plan you wrote on the quote first with

        [Attach Quote Invoice
        Plan](/api-reference/invoicing/attach-quote-invoice-plan).

        By value, `invoicePlan` is the plan the policy transactions take, which

        [Invoice plans](/api-reference/invoicing/invoice-plans) describes; it

        commits atomically with the policy version, and a change that moves the

        billing an invoiced policy's invoices add up to needs one. The by-value

        form takes no `invoices`. Either form's invoices require invoicing to be

        enabled (otherwise `403 finv2-policy-invoicing-disabled`).


        Both forms use the company’s explicitly authored Conversion Rules.


        **Billing with invoicing enabled.** Stores the quote's or caller's
        billing as stated,

        without scaling, restoring or carrying billing from the policy. A billed
        term must

        restate `fullTermBillingInfo` on ENDORSE, CANCEL and REINSTATE; omission
        or unstated

        billing returns `400 finv2-policy-billing-required`. A change that voids
        every active

        invoice while any billing line still owes returns `400
        finv2-policy-invoices-required`.

        New terms and unbilled policies may have no billing. An uninvoiced
        policy may bind

        with billing and no invoices; existing invoices must still add up to it,
        as

        [Invoice plans](/api-reference/invoicing/invoice-plans) explains.


        **Billing with invoicing disabled.** The policy stores null billing. A

        non-null `fullTermBillingInfo` in the by-value `data`, malformed or not,
        or

        held by the quote bound by reference, is refused with

        `403 finv2-policy-invoicing-disabled`, and nothing is saved: send null
        or

        leave it out. Companies awaiting their billing migration keep their

        existing derivation and carry behavior while invoicing is disabled.


        **Required permission:** `quote.bind`
      operationId: bindQuoteByValue
      parameters:
        - $ref: '#/components/parameters/companyId'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              oneOf:
                - type: object
                  title: Bind by reference
                  additionalProperties: false
                  required:
                    - quoteId
                  properties:
                    quoteId:
                      type: string
                      format: uuid
                      description: The persisted quote to bind.
                    invoices:
                      type: string
                      enum:
                        - generate
                        - saved
                      description: >
                        Which of the quote's invoices the bind applies:
                        `generate`

                        builds them from the quote's invoice settings, `saved`

                        binds the plan saved on the quote. Omit it to bind none;

                        that is refused with `409` while the quote holds a plan.
                - type: object
                  title: Bind by value
                  additionalProperties: false
                  required:
                    - transactionType
                    - data
                  properties:
                    transactionType:
                      type: string
                      enum:
                        - NEW_BUSINESS
                        - ENDORSE
                        - CANCEL
                        - REINSTATE
                        - RENEW
                      description: The policy transaction to bind.
                    data:
                      type: object
                      description: >
                        The quote-shaped source field bag your Conversion Rules

                        read as `source.*` — typically `quotes/generate`'s
                        `data`,

                        edited.
                    policyId:
                      type: string
                      format: uuid
                      description: |
                        The source policy. Required unless `NEW_BUSINESS`, which
                        forbids it.
                    effectiveDate:
                      type: string
                      format: date
                      description: |
                        The transaction's effective date. Required unless
                        `NEW_BUSINESS`, which forbids it.
                    endDate:
                      type: string
                      format: date
                      description: |
                        An `ENDORSE`'s optional window end; forbidden for every
                        other type.
                    expectedPolicyVersion:
                      type: integer
                      minimum: 0
                      description: >
                        Optimistic-concurrency precondition — echo

                        `sourcePolicy.policyVersion` from `quotes/generate`. On

                        mismatch the bind is refused with `409

                        PolicyVersionConflict` without performing the
                        transaction.

                        Forbidden for `NEW_BUSINESS`.
                    invoicePlan:
                      $ref: '#/components/schemas/PolicyInvoiceTransactionPlan'
            examples:
              byReference:
                summary: Bind a persisted quote and the plan saved on it
                value:
                  quoteId: 550e8400-e29b-41d4-a716-446655440002
                  invoices: saved
              byValueEndorse:
                summary: Bind a generated-and-edited endorsement by value
                value:
                  transactionType: ENDORSE
                  policyId: 550e8400-e29b-41d4-a716-446655440000
                  effectiveDate: '2026-06-01'
                  expectedPolicyVersion: 3
                  data:
                    quoteType: endorsement
                    policyType: claimsMade
                    customPolicyText: updated mid-term
              byValueEndorseWithInvoicePlan:
                summary: Bind a re-priced endorsement by value and restate its invoices
                value:
                  transactionType: ENDORSE
                  policyId: 550e8400-e29b-41d4-a716-446655440000
                  effectiveDate: '2026-06-01'
                  expectedPolicyVersion: 3
                  data:
                    quoteType: endorsement
                    fullTermPricingInfo:
                      pricingComponents:
                        - label: Premium
                          classification: premium
                          value: 1200
                    fullTermBillingInfo:
                      lines:
                        - invoiceType: Policy Invoice
                          lineItem: Premium
                          direction: receivable
                          amount: 1200
                  invoicePlan:
                    incurredDate: '2026-06-01'
                    voidInvoices:
                      - invoiceId: 550e8400-e29b-41d4-a716-446655440710
                        headJournalId: 550e8400-e29b-41d4-a716-446655440910
                    creates:
                      - group: Policy Invoice
                        payeeId: 550e8400-e29b-41d4-a716-446655440020
                        dueDate: '2026-06-15'
                        lineItems:
                          - label: Premium
                            amountCents: 120000
              byValueNewBusiness:
                summary: Bind a new-business field bag by value
                value:
                  transactionType: NEW_BUSINESS
                  data:
                    quoteType: newBusiness
                    policyType: claimsMade
                    policyTimeZone: America/New_York
                    policyStartDate:
                      date: '2026-01-01'
                      timezone: America/New_York
                    policyEndDate:
                      date: '2026-12-31'
                      timezone: America/New_York
      responses:
        '201':
          description: |
            The transaction was bound. Returns the full policy-version result —
            the same shape the five transaction endpoints return.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PolicyTransactionVersionResponse'
        '400':
          description: >
            The body matched neither form, an unknown key was sent (`invoices`
            by

            value, or `invoicePlan` by reference, included), a per-type field
            rule

            was violated (e.g. `policyId` on `NEW_BUSINESS`), or the converted

            payload failed policy-create validation.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          description: >
            The API key lacks `quote.bind`; or, while invoicing is disabled

            (`finv2-policy-invoicing-disabled`), `invoices` (by reference) or an

            `invoicePlan` (by value) was sent, the by-value `data` states a

            non-null `fullTermBillingInfo`, or the quote bound by reference
            holds

            one. Nothing is saved.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: |
            No quote with the given `quoteId` (by reference), no policy with the
            given `policyId` (by value), or no invoice an `invoicePlan` voids,
            exists for this company.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '409':
          description: >
            The bind conflicts with current state; the `error.code` names which

            precondition failed, and the listed extra fields ride the error
            body:


            - `QuoteAlreadyBound` — the referenced quote is already bound;
            carries
              `referencingPolicy`, the policy it is bound to. A `cancelled` quote
              is a `QuoteNotBindable` conflict with no extra field.
            - `finv2-quote-has-invoice-plan` — by reference, `invoices` was left
              out while the quote holds a saved plan. Bind with
              `invoices: "saved"`, or clear the plan.
            - `finv2-quote-invoice-plan-missing` — by reference,
              `invoices: "saved"` on a quote with no saved plan. Generate or attach
              one, or bind with `invoices: "generate"`.
            - `PolicyVersionConflict` — `expectedPolicyVersion` no longer
            matches;
              carries `expectedPolicyVersion` and `actualPolicyVersion`. The
              transaction was NOT performed — regenerate and retry.
            - `PolicyAlreadyRenewed` — a `RENEW` while a live successor exists;
              carries `renewedIntoPolicy`, the existing successor.
            - `finv2-invoice-head-conflict` — a void watermark in `invoicePlan`
            is
              stale. Nothing was committed; the message names the invoice and how
              to rebuild the plan.
          content:
            application/json:
              schema:
                type: object
                required:
                  - error
                properties:
                  error:
                    type: object
                    required:
                      - code
                      - message
                    properties:
                      code:
                        type: string
                        description: Machine-readable error code
                      message:
                        type: string
                        description: Human-readable error message
                      userMessages:
                        type: array
                        items:
                          type: string
                      referencingPolicy:
                        type: string
                        format: uuid
                        nullable: true
                        description: |
                          `QuoteAlreadyBound` only: the policy the quote is
                          already bound to.
                      expectedPolicyVersion:
                        type: integer
                        description: |
                          `PolicyVersionConflict` only: the version the caller
                          stated.
                      actualPolicyVersion:
                        type: integer
                        description: |
                          `PolicyVersionConflict` only: the source policy's
                          current version.
                      renewedIntoPolicy:
                        type: string
                        format: uuid
                        description: >
                          `PolicyAlreadyRenewed` only: the live successor
                          policy.
              examples:
                versionConflict:
                  summary: The source policy moved between generate and bind
                  value:
                    error:
                      code: PolicyVersionConflict
                      message: >-
                        Policy 550e8400-e29b-41d4-a716-446655440000 has moved
                        since the bind was prepared: expected version 3, actual
                        version 4. Regenerate from the current version and
                        retry.
                      expectedPolicyVersion: 3
                      actualPolicyVersion: 4
                quoteHasInvoicePlan:
                  summary: >-
                    By reference, no invoices named while the quote holds a
                    saved plan
                  value:
                    error:
                      code: finv2-quote-has-invoice-plan
                      message: >-
                        Quote 550e8400-e29b-41d4-a716-446655440002 has a saved
                        invoice plan. Bind with invoices: "saved" to apply it,
                        or clear it with DELETE
                        /api/v1/companies/550e8400-e29b-41d4-a716-446655440001/quotes/550e8400-e29b-41d4-a716-446655440002/invoicing/plan.
                      userMessages:
                        - >-
                          Quote 550e8400-e29b-41d4-a716-446655440002 has a saved
                          invoice plan. Bind with invoices: "saved" to apply it,
                          or clear it with DELETE
                          /api/v1/companies/550e8400-e29b-41d4-a716-446655440001/quotes/550e8400-e29b-41d4-a716-446655440002/invoicing/plan.
        '422':
          description: >
            The bind could not be derived; the `error.code` says why:


            - `no-conversion-rules-configured` — the company declares no
              `QUOTE_TO_POLICY` rules for this transaction type.
            - `conversion-rule-evaluation-failed` — a rule could not produce its
              destination value; the message names every failing rule. Nothing was
              bound.
            - `finv2-…` — the by-value `invoicePlan` failed policy-invoice
            binding,
              conservation, payment-lock or restating preconditions, as on the
              policy transactions; the message names the fix, and
              [Invoice plans](/api-reference/invoicing/invoice-plans#refusals)
              lists each. Nothing was committed.
            - By reference, the invoice refusals of `…/{quoteId}/bind`
              (`finv2-quote-invoices-do-not-match-pricing`,
              `finv2-payment-generation-refused`) apply unchanged.
          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
  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 each line item of the policy's stated billing. With invoicing
        enabled, a line item a kept invoice carries but billing omits conserves
        at 0: a create may credit it on the same line with a negative amount.
        [Invoice plans](/api-reference/invoicing/invoice-plans) explains each
        field, the rule and every refusal.
    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
        - primaryInsuredName
        - primaryInsuredId
        - policyNumber
        - policyStartDate
        - policyEndDate
        - fullTermPricingInfo
        - fullTermBillingInfo
        - fullTermPolicyRatingResult
        - 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` plus the
            four

            server-computed, read-only rollups — `premium`, `taxes` and `fees`
            (each

            the sum of the components whose `classification` reports into it)
            and

            `total` (`premium + taxes + fees`). All four

            are always present. The retired `brokerCommission` /
            `programCommission`

            rollups are no longer computed; a version stored before their
            retirement

            may still return the two keys until the per-tenant data sweeps.


            Each newly written component carries

            `{label, value, classification, qualifier, earningSchedule}` —

            `<classification, qualifier>` is its identity, and `label` is
            cosmetic.

            The legacy vocabulary is retired: a component stored before the

            retirement may still echo the `group` / `kind` / `earningBasis` keys

            until the per-tenant data sweeps remove them — treat those as
            historical

            output, never as identity, and do not rely on their presence.
          additionalProperties: true
        fullTermBillingInfo:
          type: object
          nullable: true
          description: >
            The policy's Billing Aggregate for the term, hoisted as a read-once

            convenience (also duplicated in every segment). Null when the policy
            states

            no billing obligations.
          allOf:
            - $ref: '#/components/schemas/FullTermBillingInfo'
        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
                  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
    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. Pricing-fallback plans use the fixed
            Policy Invoice type; Billing Aggregate plans use each line's native
            invoiceType.
        dueDate:
          type: string
          format: date
        scheduledDate:
          type: string
          format: date
          description: >-
            The installment's send date, usually its due date minus the lead
            days. When present, the invoice is recognized and sent on this date,
            and the invoice read shows it as the invoice's `incurredDate`. Until
            it arrives the installment is not yet sent; the invoice read reports
            it as `owed`.
        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 `Date` value: a calendar day pinned to an IANA time zone
        —

        the day a person wrote on the policy, not an instant.


        `date` is the day as `YYYY-MM-DD` and must name a real calendar day

        (`2026-02-30` is rejected with `400`). `timezone` is an IANA tz database

        identifier (e.g. `America/New_York`, `UTC`); an unknown zone is rejected

        with `400`. On a write `timezone` may be omitted, in which case it
        defaults

        to `America/New_York`. Every value the API returns carries both members.


        This is the one Date shape the API accepts, stores and returns, for
        every

        field typed `Date` — entity fields, policy term dates, custom-object

        sub-fields, embedded exposure items and the event lifecycle dates alike.
        The

        retired `{ day, month, year, timezone }` spelling is refused with `400`

        (see the API changelog, 2026-09-08). The policy endorsement `deltas`
        channel

        additionally requires both members stated, because it stores each value

        exactly as sent (2026-09-04).
      required:
        - date
      additionalProperties: false
      properties:
        date:
          type: string
          format: date
          description: The calendar day as `YYYY-MM-DD`, zero-padded.
          example: '2026-03-15'
        timezone:
          type: string
          description: >
            IANA time zone identifier the day is anchored in (e.g.
            "America/New_York",

            "UTC"). Optional on a write (defaults to `America/New_York`); always

            present in a response.
          example: America/New_York
    FullTermBillingInfo:
      type: object
      nullable: true
      description: >
        The policy's **Billing Aggregate** for the term: what is owed, per line
        item,

        free of invoices.


        It is the billing sibling of `fullTermPricingInfo` — a policy states its
        price

        in one container and its billing obligations in the other — and, like
        it, is a

        reserved full-term container: invariant across every segment of the
        term,

        banned from a `deltas` path at any depth (it has its own channel), and
        hoisted

        onto responses beside `fullTermPricingInfo`.


        It deliberately carries no pricing `classification` and no rollup, so

        per-rollup cash stays a naming convention over line items rather than
        schema.


        **Conditional ownership during migration:** at new and migrated
        companies

        with invoicing OFF, billing is null. Quote writes ignore supplied
        billing,

        including malformed content, and persist/return null: Quote billing is
        an

        always-owned calculation whose OFF expression is `NO_BILLING()`. A bind
        or

        policy transaction that states a non-null value, or binds a quote that
        still

        holds one, is refused with `403 finv2-policy-invoicing-disabled` and
        saves

        nothing; null or omitted billing stores null. Existing companies
        awaiting

        migration retain their previous billing behavior. With invoicing ON,
        by-value

        bind and Policy API inputs remain caller-valued.


        **Structure is validated when billing is accepted** — shape, `direction`
        membership,

        finite `amount`s, and `<invoiceType, lineItem>` uniqueness.


        **Two further laws apply unconditionally,**

        on every persisted version that states an aggregate:


        - **The receivable checksum.** The `amount`s of the `receivable` lines
        sum
          exactly to `fullTermPricingInfo.total`. A transaction that moves the price
          without restating the lines is refused with a `400` and the error code
          `finv2-policy-billing-checksum`, which carries the gap in cents. This is also
          the endorsement restate-or-refuse gate: paid invoices are never edited, and a
          delta lands as new signed invoices. With invoicing enabled the message states
          the signed price-minus-receivables gap: a policy transaction is told to
          restate `fullTermBillingInfo` to match `fullTermPricingInfo.total`, and a
          quote bind to re-rate the quote.
        - **Per-line vocabulary and direction.** Each `<invoiceType, lineItem>`
        must
          name a live policy invoice type and line item type, and the `direction` you
          state must be the one that line item is configured with — a checked
          assertion, not an input. Otherwise the write is refused with a `400` and the
          code `finv2-policy-billing-vocabulary`, naming every offending line rather
          than the first.

        An aggregate you do not state is exempt from both, and a policy with no
        billing

        configuration still prices and earns.


        **With invoicing enabled, every transaction stores the billing you state
        as

        is.** A cancel does not scale it and a reinstate does not restore it;
        pricing

        still follows the earned-floor and restore rules, so state billing whose

        `receivable` lines add up to that price. Once a term has billing, every

        endorse, cancel and reinstate must state it again, changed or unchanged:

        omission or unstated billing is refused with a `400` and the code

        `finv2-policy-billing-required`. A term with no billing that you do not
        state

        stores none.


        **With invoicing disabled, companies awaiting their billing migration
        keep

        lifecycle derivation:** when you omit the aggregate, a cancel scales the

        `receivable` lines down to the earned floor, allocating cents by largest

        remainder, and leaves `payable` lines exactly as they are — commission

        clawback is contractual, so there is no defensible default to apply. A

        reinstate restores the pre-cancel lines verbatim. State an aggregate

        explicitly to override either; it is checked like any other statement,
        so the

        override cannot escape the laws above.


        This is **not** the retired pre-2026-08-05 `fullTermPolicyBillingInfo`,
        which

        stays rejected: that name belonged to the container now called

        `fullTermPricingInfo`. `fullTermBillingInfo` is a new container holding
        a

        genuinely different fact — a price is not an obligation.
      properties:
        lines:
          type: array
          nullable: true
          description: >
            The term's billing lines, each `{invoiceType, lineItem, direction,

            amount}`. Nullable: a policy with no billing configuration still
            prices

            and earns, so an absent aggregate is an ordinary state rather than a

            defect.
          items:
            $ref: '#/components/schemas/BillingLine'
      additionalProperties: true
    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
        - transactionType
      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
        transactionType:
          type: string
          nullable: true
          enum:
            - NEW_BUSINESS
            - ENDORSE
            - CANCEL
            - REINSTATE
            - RENEW
          description: >
            The policy transaction that wrote this segment. Every transaction
            rewrites

            the full segment set at its own policy version, so this is the
            version's

            transaction type: the segments of a renewed term read `RENEW`, and
            an

            endorsement's version reads `ENDORSE` while the versions beneath it
            keep

            the type that wrote them.


            `null` means UNKNOWN — the segment was written before this member
            existed.

            Do not read a null as new business.
    PolicyInvoiceBatchCreateLine:
      type: object
      additionalProperties: false
      required:
        - label
        - amountCents
      properties:
        label:
          type: string
          minLength: 1
          description: >-
            Line-item name on this invoice type: a line item the policy's stated
            billing names or, with invoicing enabled, one an existing kept
            invoice carries.
        amountCents:
          type: integer
          description: >-
            Signed integer cents in the configured line-item type's own frame. A
            negative amount reverses the line: a credit on the same line.
        memo:
          type: string
    BillingLine:
      type: object
      description: >
        One line of a policy's term-level **Billing Aggregate** — the element
        type of

        `fullTermBillingInfo.lines`.


        A billing line is deliberately a NAME, a DIRECTION and a SIGNED AMOUNT,
        and

        nothing else. It carries no pricing `classification` and feeds no
        rollup,

        exactly as a pricing component carries no invoice type and no line item:
        the

        pricing and billing vocabularies are disjoint.


        The line's identity is the pair `<invoiceType, lineItem>`, unique within
        one

        `fullTermBillingInfo` container — two lines sharing that pair are
        rejected

        with a `400`.
      required:
        - invoiceType
        - lineItem
        - direction
        - amount
      properties:
        invoiceType:
          type: string
          minLength: 1
          description: >
            The kind of invoice the obligation belongs to, e.g. `"Policy
            Invoice"` or

            `"Commission Invoice"`. Free text (not a closed enum), and must be

            non-empty.
        lineItem:
          type: string
          minLength: 1
          description: >
            The line item within that invoice type, e.g. `"Premium Installment"`
            or

            `"Producer Commission"`. Free text (not a closed enum), and must be

            non-empty.
        direction:
          type: string
          enum:
            - receivable
            - payable
          description: >
            Which way the money moves. `receivable` is owed TO us (premium,
            taxes,

            fees); `payable` is owed BY us (commission). The direction comes
            from the

            line item type's own configuration, so the value you send is a
            **checked

            assertion** rather than an input: a mismatch is refused. That is
            what lets a

            payable commission line sit in the same aggregate as the receivables
            and

            self-exclude from the receivable checksum.
        amount:
          type: number
          description: >
            The line's amount as a plain number in USD. It is **signed** and
            must be

            finite: a price refund is a negative receivable.
      additionalProperties: true
  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
    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.

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.