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

# Create Invoice

> Creates one invoice — the `invoice.created` action. The server mints the
invoice id and its display number (`INV-XXXXXX-XXX`) and returns the
whole refreshed document: the invoice row (with `headJournalId`, the
`If-Match` watermark for every subsequent write) and its (empty) payment
list. No `If-Match` on create.

**Idempotency.** `actionId` is a client-minted uuid that becomes the
action's journal id. Retrying the identical request replays the original
outcome — server-minted invoice id and number included — instead of
creating twice; reusing the id with a different payload is
`409 ACTION_ID_REUSED`.

**Links.** `links` is optional: an invoice may link to an event, plus an
optional payee. A request with `links.policy` is well-formed but refused
with `422 POLICY_INVOICE_BATCH_ONLY`: policy invoice documents are created,
voided, and replaced only through the atomic
[policy invoice batch](/api-reference/financials/update-policy-invoices).
Parsed invoices typically arrive unlinked and attach later via
[re-link](/api-reference/financials/re-link-invoice) for the price of one
action. Named targets must exist (`422 LINK_TARGET_MISSING`).

**Configuration ids.** `categoryId` and every line item's
`lineItemTypeId` must come from the company's configured vocabulary —
discover them with
`GET /api/v1/companies/{companyId}/financials/config/categories`. A type
outside the cited category is `422 UNKNOWN_ID`; a deprecated category is
`422 DEPRECATED_CONFIG`.

**Recognition dates.** `incurredDate` is a recognition date — which period
the amount lands in. On an event-linked or unlinked invoice a future
`incurredDate` is `422 FUTURE_DATE`. Scheduled policy installments use the
policy invoice batch instead. Payment dates are never allowed in the future.

**Drafts.** Pass `stage: "draft"` to create the invoice UNPOSTED — it gets
the derived status `draft` and posts nothing to the ledger until
[finalize](/api-reference/financials/finalize-invoice). This is the only
place a draft is born; draft-ness thereafter lives in the journal. A draft
parsed off an already-paid document may carry its payment marks as the
`draftPayments` annex (per-line settlement marks citing this payload's own
line items — no `paymentId`, server-assigned at finalize) — legal only
with the draft stage, and materialized as real payment marks when the
draft is finalized.

**Source documents.** `sourceFileIds` attaches already-uploaded files to
the created invoice server-side (one placement per file). Upload the bytes
first through the platform files API, then pass their ids here; an unknown
id is a `404` that rolls the whole create back. Attaching does not require
the draft stage.

**Required permission:** `company.payment:update`




## OpenAPI

````yaml /openapi/generated-external-api.yaml post /api/v1/companies/{companyId}/financials/invoices
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}/financials/invoices:
    post:
      tags:
        - Financials
      summary: Create Invoice
      description: >
        Creates one invoice — the `invoice.created` action. The server mints the

        invoice id and its display number (`INV-XXXXXX-XXX`) and returns the

        whole refreshed document: the invoice row (with `headJournalId`, the

        `If-Match` watermark for every subsequent write) and its (empty) payment

        list. No `If-Match` on create.


        **Idempotency.** `actionId` is a client-minted uuid that becomes the

        action's journal id. Retrying the identical request replays the original

        outcome — server-minted invoice id and number included — instead of

        creating twice; reusing the id with a different payload is

        `409 ACTION_ID_REUSED`.


        **Links.** `links` is optional: an invoice may link to an event, plus an

        optional payee. A request with `links.policy` is well-formed but refused

        with `422 POLICY_INVOICE_BATCH_ONLY`: policy invoice documents are
        created,

        voided, and replaced only through the atomic

        [policy invoice
        batch](/api-reference/financials/update-policy-invoices).

        Parsed invoices typically arrive unlinked and attach later via

        [re-link](/api-reference/financials/re-link-invoice) for the price of
        one

        action. Named targets must exist (`422 LINK_TARGET_MISSING`).


        **Configuration ids.** `categoryId` and every line item's

        `lineItemTypeId` must come from the company's configured vocabulary —

        discover them with

        `GET /api/v1/companies/{companyId}/financials/config/categories`. A type

        outside the cited category is `422 UNKNOWN_ID`; a deprecated category is

        `422 DEPRECATED_CONFIG`.


        **Recognition dates.** `incurredDate` is a recognition date — which
        period

        the amount lands in. On an event-linked or unlinked invoice a future

        `incurredDate` is `422 FUTURE_DATE`. Scheduled policy installments use
        the

        policy invoice batch instead. Payment dates are never allowed in the
        future.


        **Drafts.** Pass `stage: "draft"` to create the invoice UNPOSTED — it
        gets

        the derived status `draft` and posts nothing to the ledger until

        [finalize](/api-reference/financials/finalize-invoice). This is the only

        place a draft is born; draft-ness thereafter lives in the journal. A
        draft

        parsed off an already-paid document may carry its payment marks as the

        `draftPayments` annex (per-line settlement marks citing this payload's
        own

        line items — no `paymentId`, server-assigned at finalize) — legal only

        with the draft stage, and materialized as real payment marks when the

        draft is finalized.


        **Source documents.** `sourceFileIds` attaches already-uploaded files to

        the created invoice server-side (one placement per file). Upload the
        bytes

        first through the platform files API, then pass their ids here; an
        unknown

        id is a `404` that rolls the whole create back. Attaching does not
        require

        the draft stage.


        **Required permission:** `company.payment:update`
      operationId: createFinancialsInvoice
      parameters:
        - $ref: '#/components/parameters/companyId'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              additionalProperties: false
              required:
                - actionId
                - categoryId
                - lineItems
              properties:
                actionId:
                  type: string
                  format: uuid
                  description: >-
                    Client-minted idempotency key — becomes the action's journal
                    id. An identical retry replays the original outcome; reuse
                    with a different payload is `409 ACTION_ID_REUSED`
                author:
                  type: string
                  minLength: 1
                  maxLength: 255
                  description: >-
                    Optional display label for the source system's author (e.g.
                    the integrator-side user). Stamped as the journal record's
                    display attribution; the acting principal stays the External
                    API service user, so a label can never impersonate an in-app
                    user. Ignored on idempotent replays
                categoryId:
                  type: string
                  format: uuid
                  description: The transaction category the invoice belongs to
                stage:
                  type: string
                  enum:
                    - draft
                  description: >-
                    Set to `draft` to create the invoice UNPOSTED (derived
                    status `draft`) until it is finalized. Omit for a live,
                    posted invoice. The only stage marker — accepted on create
                    only
                incurredDate:
                  type: string
                  format: date
                  description: >-
                    The recognition date for the charges (ISO `YYYY-MM-DD`) —
                    the period the amount lands in. May be in the future on a
                    policy-linked invoice; on an event-linked or unlinked
                    invoice a future date is `422 FUTURE_DATE`
                dueDate:
                  type: string
                  format: date
                  description: When payment is owed — display metadata only
                memo:
                  type: string
                  description: Free-text memo
                fieldData:
                  type: object
                  additionalProperties: true
                  description: >-
                    Values for the tenant-defined custom invoice fields, keyed
                    by field referenceId — an opaque JSON object
                lineItems:
                  type: array
                  items:
                    $ref: '#/components/schemas/FinancialsV2WriteLineItem'
                links:
                  type: object
                  additionalProperties: false
                  description: >-
                    The invoice's initial links — all optional; absent means
                    unlinked. `event` and `policy` are mutually exclusive
                  properties:
                    event:
                      type: string
                      format: uuid
                      description: An event to link the invoice to
                    policy:
                      type: string
                      format: uuid
                      description: >-
                        A policy link is refused with `422
                        POLICY_INVOICE_BATCH_ONLY`; use the policy invoice batch
                    payee:
                      type: string
                      format: uuid
                      description: The invoice's payee entity
                draftPayments:
                  type: array
                  description: >-
                    Payment MARKS parsed off an already-paid source document,
                    carried on a DRAFT so finalize can apply them as real
                    payments. Legal only with `stage: "draft"`. One entry = one
                    per-line settlement mark citing this payload's own line
                    items; no `paymentId` — the server assigns ids at finalize
                  items:
                    type: object
                    additionalProperties: false
                    required:
                      - lineItemId
                      - amountCents
                      - paymentDate
                    properties:
                      lineItemId:
                        type: string
                        format: uuid
                        description: >-
                          The line item (of this payload's `lineItems`) the mark
                          settles
                      amountCents:
                        type: integer
                        description: >-
                          The mark's amount in signed integer cents, in its line
                          item's frame (nonzero; sign matching the line's
                          remaining, settling it toward zero)
                      paymentDate:
                        type: string
                        format: date
                        description: When the payment was made (`YYYY-MM-DD`)
                      memo:
                        type: string
                        description: Free-text memo for the mark
                      erodeReserves:
                        type: boolean
                        description: >-
                          Whether the mark erodes reserves — required on
                          reserved-category invoices
                sourceFileIds:
                  type: array
                  description: >-
                    Ids of already-uploaded files (platform files API) to attach
                    to the created invoice server-side. Deduplicated; an unknown
                    id is a `404` that rolls the create back
                  items:
                    type: string
                    format: uuid
            examples:
              expenseInvoice:
                summary: A single-line invoice linked to an event
                value:
                  actionId: 3f8a1c2e-9d4b-4f6a-8e2d-1b7c5a9e0f21
                  categoryId: 550e8400-e29b-41d4-a716-446655440100
                  incurredDate: '2026-06-01'
                  dueDate: '2026-07-15'
                  memo: Legal defense
                  lineItems:
                    - lineItemId: 550e8400-e29b-41d4-a716-446655440300
                      lineItemTypeId: 550e8400-e29b-41d4-a716-446655440110
                      amountCents: 10000
                  links:
                    event: 550e8400-e29b-41d4-a716-446655440200
              unlinkedParsedInvoice:
                summary: An unlinked invoice (links attach later via re-link)
                value:
                  actionId: 6b2f4d8a-1c3e-4a5b-9f7d-2e8c6a0b4d13
                  categoryId: 550e8400-e29b-41d4-a716-446655440100
                  incurredDate: '2026-06-01'
                  memo: Parsed from invoice-scan.pdf
                  lineItems:
                    - lineItemId: 550e8400-e29b-41d4-a716-446655440300
                      lineItemTypeId: 550e8400-e29b-41d4-a716-446655440110
                      amountCents: 12550
              parsedDraft:
                summary: A parsed draft with a source file and a paid-off annex
                value:
                  actionId: 9c4d2e1f-7a8b-4c3d-8e5f-1a2b3c4d5e6f
                  categoryId: 550e8400-e29b-41d4-a716-446655440100
                  stage: draft
                  incurredDate: '2026-06-01'
                  memo: Parsed from invoice-scan.pdf
                  lineItems:
                    - lineItemId: 550e8400-e29b-41d4-a716-446655440300
                      lineItemTypeId: 550e8400-e29b-41d4-a716-446655440110
                      amountCents: 12550
                  sourceFileIds:
                    - 550e8400-e29b-41d4-a716-446655440a01
                  draftPayments:
                    - lineItemId: 550e8400-e29b-41d4-a716-446655440300
                      amountCents: 12550
                      paymentDate: '2026-06-05'
                      erodeReserves: false
      responses:
        '200':
          description: >-
            The created invoice — refreshed read state with the server-minted id
            and invoice number (a replay returns the original outcome)
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/FinancialsV2InvoiceWriteResponse'
              examples:
                created:
                  summary: Created invoice
                  value:
                    journalIds:
                      - 3f8a1c2e-9d4b-4f6a-8e2d-1b7c5a9e0f21
                    invoice:
                      id: 550e8400-e29b-41d4-a716-446655440700
                      invoiceNumber: INV-389538-455
                      categoryId: 550e8400-e29b-41d4-a716-446655440100
                      status: owed
                      linkedEvent:
                        id: 550e8400-e29b-41d4-a716-446655440200
                        displayName: 'Claim #1042'
                      linkedPolicy: null
                      linkedPayee: null
                      incurredDate: '2026-06-01'
                      dueDate: '2026-07-15'
                      memo: Legal defense
                      fieldData: null
                      lineItems:
                        - lineItemId: 550e8400-e29b-41d4-a716-446655440300
                          lineItemTypeId: 550e8400-e29b-41d4-a716-446655440110
                          memo: null
                          amountCents: 10000
                      totalAmountCents: 10000
                      amountPaidCents: 0
                      balanceDueCents: 10000
                      paidDate: null
                      lastPaymentDate: null
                      voidedAt: null
                      deletedAt: null
                      createdAt: '2026-06-01T10:30:00.000Z'
                      updatedAt: '2026-06-01T10:30:00.000Z'
                      headJournalId: 3f8a1c2e-9d4b-4f6a-8e2d-1b7c5a9e0f21
                    payments: []
        '400':
          description: >-
            Bad Request — a malformed payload: unknown fields, a missing
            `actionId`, or `links.event` and `links.policy` both set
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              examples:
                bothLinks:
                  summary: Event and policy links are mutually exclusive
                  value:
                    error:
                      code: VALIDATION_ERROR
                      message: links.event and links.policy are mutually exclusive
                      userMessages:
                        - links.event and links.policy are mutually exclusive
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          description: >-
            Not Found — the company does not have this financials surface
            enabled (the endpoint behaves as if it does not exist)
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              examples:
                notFound:
                  summary: Not found
                  value:
                    error:
                      code: NotFoundError
                      message: Not found
                      userMessages:
                        - Not found
        '409':
          $ref: '#/components/responses/FinancialsV2ActionIdReused'
        '422':
          $ref: '#/components/responses/FinancialsV2PreconditionFailed'
        '500':
          $ref: '#/components/responses/InternalServerError'
components:
  parameters:
    companyId:
      name: companyId
      in: path
      required: true
      schema:
        type: string
        format: uuid
      description: Company identifier
  schemas:
    FinancialsV2WriteLineItem:
      type: object
      description: >-
        One line item of an invoice write. `lineItemId` is caller-minted and
        stable across updates — payment marks target it. Amounts are integer
        cents; direction never rides the sign: `amountCents` is the magnitude a
        user would type, and a negative amount is a credit within the item's own
        frame — it posts opposite the line item type's expected direction (e.g.
        a reversal or refund); the posting rule always comes from the type,
        never the sign.
      required:
        - lineItemId
        - lineItemTypeId
        - amountCents
      properties:
        lineItemId:
          type: string
          format: uuid
          description: >-
            Caller-minted id for the line item — keep it stable across updates
            to preserve the item's identity (payment marks reference it)
        lineItemTypeId:
          type: string
          format: uuid
          description: >-
            A configured line item type OF THE CITED CATEGORY — discover ids
            with `GET
            /api/v1/companies/{companyId}/financials/config/categories`. A type
            outside the invoice's category is `422 UNKNOWN_ID`
        memo:
          type: string
          description: Free-text memo
        amountCents:
          type: integer
          description: >-
            The line item's amount in integer cents — the user-typed magnitude;
            negative = a credit within the item's frame, posting opposite the
            type's expected direction
    FinancialsV2InvoiceWriteResponse:
      type: object
      description: >-
        The response of every single-invoice write — refreshed read state, not
        an ack: the emitted journal id(s), THE invoice row (identical shape to
        the reads — one invoice representation everywhere; its `headJournalId`
        is the next `If-Match`), and the invoice's live payments. An idempotent
        `actionId` replay returns this same shape rebuilt from the original
        outcome, server-minted values included.
      required:
        - journalIds
        - invoice
        - payments
      properties:
        journalIds:
          type: array
          minItems: 1
          items:
            type: string
            format: uuid
          description: >-
            Every journal id the write emitted — the anchor action's id (the
            `actionId` you supplied) first, then any engine-minted siblings (a
            multi-mark payment's additional marks) and any companion the horizon
            rule composed (e.g. the reserve unwind of a pre-horizon eroding
            payment's removal, or a delete's payment sweep)
        invoice:
          $ref: '#/components/schemas/FinancialsV2Invoice'
        payments:
          type: array
          description: The invoice's live payment marks after the write, newest first
          items:
            $ref: '#/components/schemas/FinancialsV2Payment'
    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
    FinancialsV2Invoice:
      type: object
      description: >-
        THE invoice representation — the same shape everywhere an endpoint
        returns an invoice (listing rows, the detail read, and every write's
        refreshed-row response). `headJournalId` is the invoice's current
        journal head — the optimistic-concurrency token subsequent writes echo
        back as `If-Match`.
      required:
        - id
        - invoiceNumber
        - categoryId
        - status
        - linkedEvent
        - linkedPolicy
        - linkedPayee
        - incurredDate
        - dueDate
        - memo
        - fieldData
        - lineItems
        - totalAmountCents
        - amountPaidCents
        - balanceDueCents
        - draftAmountPaidCents
        - paidDate
        - lastPaymentDate
        - voidedAt
        - deletedAt
        - approved
        - approvedAt
        - createdAt
        - updatedAt
        - headJournalId
      properties:
        id:
          type: string
          format: uuid
          description: The invoice's id
        invoiceNumber:
          type: string
          description: The invoice's system-minted display number
        categoryId:
          type: string
          format: uuid
          description: The transaction category the invoice belongs to
        status:
          type: string
          enum:
            - no_charges
            - owed
            - partially_paid
            - paid
            - voided
            - deleted
          description: >-
            Derived status, first match wins: `deleted` → `voided` →
            `no_charges` (every line item's amount is zero) → `paid` (every line
            item is settled — its amount minus its live marks is exactly zero) →
            `owed` (no live payment marks) → `partially_paid`. Settlement is per
            line: no scalar makes a document paid, and a zero-due document with
            unsettled lines still reads `owed`
        linkedEvent:
          type: object
          nullable: true
          description: >-
            The linked event, display-ready (the server resolves the display
            name), or `null` when not linked to an event
          required:
            - id
            - displayName
          properties:
            id:
              type: string
              format: uuid
              description: The linked event's id
            displayName:
              type: string
              description: The linked event's display name
        linkedPolicy:
          type: object
          nullable: true
          description: >-
            The linked policy, display-ready, or `null`. An invoice links to an
            event or a policy, never both
          required:
            - id
            - displayName
          properties:
            id:
              type: string
              format: uuid
              description: The linked policy's id
            displayName:
              type: string
              description: The linked policy's display name
        linkedPayee:
          type: object
          nullable: true
          description: >-
            The invoice's payee, display-ready, or `null` when none is set.
            `entityType` is an open string (e.g. `Person`, `Organization`) — the
            payee vocabulary is the entity module's, not part of this contract
          required:
            - id
            - entityType
            - displayName
          properties:
            id:
              type: string
              format: uuid
              description: The payee entity's id
            entityType:
              type: string
              description: The payee's entity type (e.g. Person, Organization)
            displayName:
              type: string
              description: The payee's display name
        incurredDate:
          type: string
          format: date
          nullable: true
          description: The date the charges were incurred (ISO `YYYY-MM-DD`), or `null`
        dueDate:
          type: string
          format: date
          nullable: true
          description: When payment is owed (display metadata only), or `null`
        memo:
          type: string
          nullable: true
          description: Free-text memo, or `null`
        fieldData:
          type: object
          nullable: true
          additionalProperties: true
          description: >-
            Values for the tenant-defined custom invoice fields, keyed by field
            referenceId — an opaque JSON object, or `null`
        lineItems:
          type: array
          description: The invoice's line items
          items:
            $ref: '#/components/schemas/FinancialsV2InvoiceLineItem'
        totalAmountCents:
          type: integer
          description: >-
            Sum of the ORIENTED line-item amounts (a payable-direction line
            counts +, a receivable-direction line counts −), in integer cents —
            the net cash the document commits to move
        amountPaidCents:
          type: integer
          description: >-
            Sum of the ORIENTED live payment marks, in integer cents — the net
            cash moved so far
        balanceDueCents:
          type: integer
          description: >-
            `totalAmountCents - amountPaidCents`, in integer cents — the net
            cash remaining to move: positive = out, negative = in. May move
            non-monotonically as opposite-direction lines settle
        draftAmountPaidCents:
          type: integer
          nullable: true
          description: >-
            A DRAFT's annex-derived paid total: the oriented net-cash sum of the
            payment marks the draft was born carrying (the same frame as
            `amountPaidCents`, which counts LIVE posted marks only and reads 0
            while drafting) — what a draft's underlying payment picture will
            read once finalized. `null` on non-draft invoices (the annex is
            spent at finalize). Display-only — never a posted ledger amount
        paidDate:
          type: string
          format: date
          nullable: true
          description: >-
            Payment date of the mark that first made every line item settled;
            clears (`null`) whenever any line reopens
        lastPaymentDate:
          type: string
          format: date
          nullable: true
          description: Date of the most recent live payment, or `null`
        voidedAt:
          type: string
          format: date-time
          nullable: true
          description: When the invoice was voided, or `null`
        deletedAt:
          type: string
          format: date-time
          nullable: true
          description: When the invoice was deleted, or `null`
        approved:
          type: boolean
          description: >-
            The approval projection: `true` after `invoice.approved`, cleared
            only by `invoice.unapproved` — an edit never resets approval (the
            approval-relevant facts, line items and category, are immutable once
            posted). Only meaningful while the approvals feature is enabled;
            reads `false` otherwise
        approvedAt:
          type: string
          format: date-time
          nullable: true
          description: >-
            When the approval landed (`invoice.approved`), or `null` while
            unapproved — `approved` is exactly `approvedAt != null`. Like
            `approved`, only meaningful while the approvals feature is enabled;
            reads `null` otherwise
        createdAt:
          type: string
          format: date-time
          description: When the invoice was created
        updatedAt:
          type: string
          format: date-time
          description: When the invoice last changed
        headJournalId:
          type: string
          format: uuid
          description: >-
            The invoice's current journal head — send it as `If-Match` on the
            next write to this invoice; a mismatch is a `409` carrying the
            current row
    FinancialsV2Payment:
      type: object
      description: >-
        A recorded payment MARK on an invoice: one row = one per-line settlement
        mark against `lineItemId`. `amountCents` is signed in the LINE's frame —
        its sign matches the line's open remaining, and the mark settles that
        line toward zero. One journal action per mark (`journalId` is the record
        that created it), each independently removable by `id`; one gesture
        (e.g. paying a document's whole balance due) may create several marks.
        `erodeReserves` is the caller's choice at record time (`null` where the
        invoice's category has no reserves to erode).
      required:
        - id
        - journalId
        - lineItemId
        - amountCents
        - paymentDate
        - erodeReserves
        - memo
        - createdAt
      properties:
        id:
          type: string
          format: uuid
          description: The payment mark's id — the handle for removing it
        journalId:
          type: string
          format: uuid
          description: The journal record that recorded the mark
        lineItemId:
          type: string
          format: uuid
          description: The invoice line item the mark settles
        amountCents:
          type: integer
          description: >-
            The mark's amount in signed integer cents, in its line item's frame
            — the sign matches the line's remaining and the mark settles it
            toward zero
        paymentDate:
          type: string
          format: date
          description: The payment date (ISO `YYYY-MM-DD`)
        erodeReserves:
          type: boolean
          nullable: true
          description: >-
            Whether the mark erodes the linked event's reserves; `null` where
            the invoice's category carries no reserves
        memo:
          type: string
          nullable: true
          description: Free-text memo, or `null`
        createdAt:
          type: string
          format: date-time
          description: When the mark was recorded
    FinancialsV2PreconditionError:
      type: object
      description: >-
        A failed write precondition (`422`): the request was well-formed but the
        books reject it. Preconditions fail closed — a rejected write leaves no
        journal record, no ledger change, and no read-state change. `error.code`
        is one of the STABLE financials error codes (single source:
        `FINANCIALS_V2_PRECONDITION_CODES` in the engine's error module,
        re-exported to this surface as `FINANCIALS_V2_API_ERROR_CODES`) —
        messages may be reworded, the codes will not.
      required:
        - error
      properties:
        error:
          type: object
          required:
            - code
            - message
          properties:
            code:
              type: string
              enum:
                - LIVE_PAYMENTS
                - AMOUNT_EXCEEDS_BALANCE_DUE
                - INVALID_AMOUNT
                - LINE_ITEMS_IMMUTABLE
                - INVOICE_DELETED
                - INVOICE_VOIDED
                - INVOICE_DRAFT
                - INVOICE_NOT_DRAFT
                - PAYMENT_NOT_FOUND
                - ERODE_RESERVES_MISMATCH
                - ERODE_REQUIRES_EVENT
                - DEPRECATED_CONFIG
                - NOT_RESERVED_CATEGORY
                - FUTURE_DATE
                - UNKNOWN_ID
                - LINK_TARGET_MISSING
                - UNAPPROVE_PAID
                - NOT_APPROVED
                - POLICY_INVOICE_BATCH_ONLY
              description: >-
                The stable precondition code — one per guard. `LIVE_PAYMENTS`
                (the action — re-link, payee change, or void — needs the
                invoice's live payments removed first);
                `AMOUNT_EXCEEDS_BALANCE_DUE` (a payment mark's magnitude
                overshoots its line item's remaining — per line, never a
                document scalar); `INVALID_AMOUNT` (a zero mark, or a mark whose
                sign opposes its line item's open remaining — a `payBalanceDue`
                against a document with nothing open included);
                `LINE_ITEMS_IMMUTABLE` (a posted invoice's line items — ids,
                types, amounts — and its category are fixed from the posting
                moment: any post-posting change is rejected, at any payment
                count; corrections are void-and-recreate, payments removed
                first; drafts edit freely until finalize); `INVOICE_DELETED` /
                `INVOICE_VOIDED` (lifecycle closures); `INVOICE_DRAFT` (drafts
                are unposted — money may not touch one: recording a payment on
                or voiding a draft is rejected; finalize it first);
                `INVOICE_NOT_DRAFT` (finalize targets exactly a draft);
                `PAYMENT_NOT_FOUND` (no live payment mark with that id on that
                invoice); `ERODE_RESERVES_MISMATCH` / `ERODE_REQUIRES_EVENT`
                (the erode flag missing on a reserved category or present on
                operating; eroding needs a linked event — there is no headroom
                bound: the remaining reserve is a signed balance and may cross
                zero); `DEPRECATED_CONFIG` / `NOT_RESERVED_CATEGORY` /
                `UNKNOWN_ID` (cited configuration guards); `FUTURE_DATE`;
                `LINK_TARGET_MISSING` (the named link target does not exist);
                `UNAPPROVE_PAID` (an approval cannot be revoked once payments
                have been recorded — remove them first); `NOT_APPROVED` (money
                cannot post against an unapproved invoice AND the calling key
                does not hold `company.payment:approve`, so it cannot approve it
                either — a key that holds the permission auto-approves instead
                of failing here); `POLICY_INVOICE_BATCH_ONLY` (the write touches
                a POLICY-LINKED invoice's document — creating one with
                `links.policy`, or updating, voiding, restoring, deleting, or
                re-linking one that is already policy-linked. A policy's
                invoices are issued as one set so that every price component of
                the policy's pricing contract stays netted to its own line item,
                so they are written only by the policy invoice batch: `POST
                /api/v1/companies/{companyId}/financials/policies/{policyId}/invoices/batch`.
                Change the policy or submit an explicit batch and the invoices
                are reissued. Payments, payee changes, and approvals on a policy
                invoice are unaffected)
            message:
              type: string
              description: Human-readable description of the failed precondition
            userMessages:
              type: array
              description: Clean, verbatim-displayable messages
              items:
                type: string
    FinancialsV2InvoiceLineItem:
      type: object
      description: A stored invoice line item as rendered on invoice reads.
      required:
        - lineItemId
        - lineItemTypeId
        - memo
        - amountCents
      properties:
        lineItemId:
          type: string
          format: uuid
          description: The line item's id
        lineItemTypeId:
          type: string
          format: uuid
          description: >-
            The configured line item type this item cites — discover ids with
            `GET /api/v1/companies/{companyId}/financials/config/categories`
        memo:
          type: string
          nullable: true
          description: Free-text memo, or `null`
        amountCents:
          type: integer
          description: >-
            The line item's amount in integer cents — the magnitude a user would
            type; a negative amount is a credit within the item's own frame — it
            posts opposite the line item type's expected direction (e.g. a
            reversal or refund); the posting rule always comes from the type,
            never the sign
  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
    FinancialsV2ActionIdReused:
      description: >-
        Conflict — the `actionId` was already used by a DIFFERENT action
        (different action type, target, or client payload). Supply a fresh uuid.
        An IDENTICAL retry never conflicts: it replays the original outcome
        (`200`) instead.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          examples:
            actionIdReused:
              summary: actionId reused by a different action
              value:
                error:
                  code: ACTION_ID_REUSED
                  message: >-
                    actionId 550e8400-e29b-41d4-a716-446655440000 was already
                    used by a different action; supply a fresh uuid (or retry
                    with the identical action to replay it)
                  userMessages:
                    - >-
                      actionId 550e8400-e29b-41d4-a716-446655440000 was already
                      used by a different action; supply a fresh uuid (or retry
                      with the identical action to replay it)
    FinancialsV2PreconditionFailed:
      description: >-
        Unprocessable — a write precondition failed. Fails closed: no journal
        record, no ledger change, no read-state change. `error.code` is one of
        the stable financials error codes; each operation's description names
        its signature codes.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/FinancialsV2PreconditionError'
          examples:
            livePayments:
              summary: The action requires the invoice's live payments removed first
              value:
                error:
                  code: LIVE_PAYMENTS
                  message: >-
                    The invoice has live payments; remove them before this
                    action
                  userMessages:
                    - >-
                      The invoice has live payments; remove them before this
                      action
            unknownId:
              summary: >-
                A cited configuration id is unknown (or outside the cited
                category)
              value:
                error:
                  code: UNKNOWN_ID
                  message: lineItemTypeId does not belong to the cited category
                  userMessages:
                    - lineItemTypeId does not belong to the cited category
            policyInvoiceBatchOnly:
              summary: >-
                Policy-linked invoice documents are changed only as one policy
                batch
              value:
                error:
                  code: POLICY_INVOICE_BATCH_ONLY
                  message: >-
                    Policy-linked invoice documents can only be changed through
                    POST
                    /api/v1/companies/{companyId}/financials/policies/{policyId}/invoices/batch
                  userMessages:
                    - >-
                      Policy-linked invoice documents can only be changed
                      through POST
                      /api/v1/companies/{companyId}/financials/policies/{policyId}/invoices/batch
    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.

````