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

# Unapprove Invoice

> Revokes the invoice's approval — the `invoice.unapproved` action: it clears
`approved` / `approvedAt` and posts NOTHING to the books. The inverse of
[approve](/api-reference/financials/approve-invoice).

**Authority.** Granting and revoking an approval are the SAME authority:
the calling key must hold `company.payment:approve`. The company's in-app
approval rules are never applied to API callers. A key without the
permission gets `403`.

**Preconditions (`422`).** The invoice must not be paid or partially paid
(`UNAPPROVE_PAID`) — once money has moved, the approval that authorized it
cannot be revoked, so
[remove the payments](/api-reference/financials/remove-payment) first. It
must also be neither voided (`INVOICE_VOIDED`) nor deleted
(`INVOICE_DELETED`). Unapproving a never-approved invoice is a DEFINED
no-op: still journaled, zero ledger rows, refreshed state returned.

**Concurrency + idempotency.** Requires `If-Match` (the invoice's current
`headJournalId`); the body carries the client-minted `actionId` — an
identical retry replays the original outcome.

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




## OpenAPI

````yaml /openapi/generated-external-api.yaml post /api/v1/companies/{companyId}/financials/invoices/{invoiceId}/unapprove
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/{invoiceId}/unapprove:
    post:
      tags:
        - Financials
      summary: Unapprove Invoice
      description: >
        Revokes the invoice's approval — the `invoice.unapproved` action: it
        clears

        `approved` / `approvedAt` and posts NOTHING to the books. The inverse of

        [approve](/api-reference/financials/approve-invoice).


        **Authority.** Granting and revoking an approval are the SAME authority:

        the calling key must hold `company.payment:approve`. The company's
        in-app

        approval rules are never applied to API callers. A key without the

        permission gets `403`.


        **Preconditions (`422`).** The invoice must not be paid or partially
        paid

        (`UNAPPROVE_PAID`) — once money has moved, the approval that authorized
        it

        cannot be revoked, so

        [remove the payments](/api-reference/financials/remove-payment) first.
        It

        must also be neither voided (`INVOICE_VOIDED`) nor deleted

        (`INVOICE_DELETED`). Unapproving a never-approved invoice is a DEFINED

        no-op: still journaled, zero ledger rows, refreshed state returned.


        **Concurrency + idempotency.** Requires `If-Match` (the invoice's
        current

        `headJournalId`); the body carries the client-minted `actionId` — an

        identical retry replays the original outcome.


        **Required permission:** `company.payment:approve`
      operationId: unapproveFinancialsInvoice
      parameters:
        - $ref: '#/components/parameters/companyId'
        - name: invoiceId
          in: path
          required: true
          schema:
            type: string
            format: uuid
          description: Invoice identifier
        - $ref: '#/components/parameters/ifMatch'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              additionalProperties: false
              required:
                - actionId
              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.
                    Stamped as the journal record's display attribution; the
                    acting principal stays the External API service user.
                    Ignored on idempotent replays
            examples:
              unapprove:
                summary: Revoke the approval
                value:
                  actionId: 2c3d4e5f-6071-4823-9934-a5b6c7d8e9fa
      responses:
        '200':
          description: >-
            The invoice with its approval revoked — refreshed read state
            (`approved: false`)
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/FinancialsV2InvoiceWriteResponse'
              examples:
                unapproved:
                  summary: Approval revoked
                  value:
                    journalIds:
                      - 2c3d4e5f-6071-4823-9934-a5b6c7d8e9fa
                    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: null
                      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
                      draftAmountPaidCents: null
                      paidDate: null
                      lastPaymentDate: null
                      approved: false
                      approvedAt: null
                      voidedAt: null
                      deletedAt: null
                      createdAt: '2026-06-01T10:30:00.000Z'
                      updatedAt: '2026-06-14T12:05:00.000Z'
                      headJournalId: 2c3d4e5f-6071-4823-9934-a5b6c7d8e9fa
                    payments: []
        '400':
          description: >-
            Bad Request — a malformed payload or a missing/malformed `If-Match`
            header (`IF_MATCH_REQUIRED` / `IF_MATCH_INVALID`)
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              examples:
                ifMatchInvalid:
                  summary: Malformed If-Match header
                  value:
                    error:
                      code: IF_MATCH_INVALID
                      message: >-
                        The If-Match header must be the invoice's headJournalId
                        (a uuid).
                      userMessages:
                        - >-
                          The If-Match header must be the invoice's
                          headJournalId (a uuid).
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          description: >-
            Not Found — no invoice with this id, or the company does not have
            this financials surface enabled (indistinguishable by design)
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              examples:
                invoiceNotFound:
                  summary: Invoice not found
                  value:
                    error:
                      code: NotFoundError
                      message: Invoice not found
                      userMessages:
                        - Invoice not found
        '409':
          $ref: '#/components/responses/FinancialsV2IfMatchConflict'
        '422':
          description: >-
            Unprocessable — a write precondition failed. Fails closed: no
            journal record, no ledger change, no read-state change.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/FinancialsV2PreconditionError'
              examples:
                unapprovePaid:
                  summary: The invoice has recorded payments
                  value:
                    error:
                      code: UNAPPROVE_PAID
                      message: >-
                        Invoice 550e8400-e29b-41d4-a716-446655440700 is paid; an
                        approval cannot be revoked once payments have been
                        recorded — remove them first
                      userMessages:
                        - >-
                          Invoice 550e8400-e29b-41d4-a716-446655440700 is paid;
                          an approval cannot be revoked once payments have been
                          recorded — remove them first
                invoiceVoided:
                  summary: The invoice is voided
                  value:
                    error:
                      code: INVOICE_VOIDED
                      message: >-
                        Invoice 550e8400-e29b-41d4-a716-446655440700 is voided;
                        'invoice.unapproved' cannot be applied to it
                      userMessages:
                        - >-
                          Invoice 550e8400-e29b-41d4-a716-446655440700 is
                          voided; 'invoice.unapproved' cannot be applied to it
        '500':
          $ref: '#/components/responses/InternalServerError'
components:
  parameters:
    companyId:
      name: companyId
      in: path
      required: true
      schema:
        type: string
        format: uuid
      description: Company identifier
    ifMatch:
      name: If-Match
      in: header
      required: true
      schema:
        type: string
        format: uuid
      description: >-
        The invoice's current `headJournalId` — the optimistic-concurrency
        watermark every single-invoice write after creation must send. Read it
        off any invoice read or write response and echo it verbatim (a bare
        uuid; an entity-tag dressing of it — `"uuid"` or `W/"uuid"` — is also
        accepted). Missing or malformed is a `400` (`IF_MATCH_REQUIRED` /
        `IF_MATCH_INVALID`); a stale value is a `409 IF_MATCH_CONFLICT` whose
        body carries the current invoice. An idempotent `actionId` replay
        short-circuits BEFORE the watermark is evaluated.
  schemas:
    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
    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
    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
    FinancialsV2IfMatchConflictError:
      type: object
      description: >-
        The conflict envelope of an `If-Match` invoice write.
        `IF_MATCH_CONFLICT`: the supplied watermark is stale —
        `error.currentInvoice` is the invoice's CURRENT row; re-read, reconcile,
        and retry with its `headJournalId`. `ACTION_ID_REUSED`: the `actionId`
        names a different recorded action (no `currentInvoice`).
      required:
        - error
      properties:
        error:
          type: object
          required:
            - code
            - message
          properties:
            code:
              type: string
              enum:
                - IF_MATCH_CONFLICT
                - ACTION_ID_REUSED
              description: Which conflict occurred
            message:
              type: string
              description: Human-readable error message
            userMessages:
              type: array
              description: Clean, verbatim-displayable messages
              items:
                type: string
            currentInvoice:
              allOf:
                - $ref: '#/components/schemas/FinancialsV2Invoice'
              description: >-
                Present exactly when `code` is `IF_MATCH_CONFLICT` — the
                invoice's current row; its `headJournalId` is the fresh
                `If-Match` value for the retry
    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
    FinancialsV2IfMatchConflict:
      description: >-
        Conflict — a stale `If-Match` watermark (`IF_MATCH_CONFLICT`: the body
        carries the invoice's CURRENT row; re-read, reconcile, retry with its
        `headJournalId`), or an `actionId` reused by a different action
        (`ACTION_ID_REUSED`: supply a fresh uuid — an identical retry replays
        instead).
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/FinancialsV2IfMatchConflictError'
          examples:
            ifMatchConflict:
              summary: Stale If-Match — the body carries the current invoice
              value:
                error:
                  code: IF_MATCH_CONFLICT
                  message: >-
                    If-Match 550e8400-e29b-41d4-a716-446655440901 does not match
                    the invoice's current head journal id
                  userMessages:
                    - >-
                      If-Match 550e8400-e29b-41d4-a716-446655440901 does not
                      match the invoice's current head journal id
                  currentInvoice:
                    id: 550e8400-e29b-41d4-a716-446655440700
                    invoiceNumber: INV-389538-455
                    categoryId: 550e8400-e29b-41d4-a716-446655440100
                    status: partially_paid
                    linkedEvent:
                      id: 550e8400-e29b-41d4-a716-446655440200
                      displayName: 'Claim #1042'
                    linkedPolicy: null
                    linkedPayee: null
                    incurredDate: '2026-06-01'
                    dueDate: null
                    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: 4000
                    balanceDueCents: 6000
                    paidDate: null
                    lastPaymentDate: '2026-06-10'
                    voidedAt: null
                    deletedAt: null
                    createdAt: '2026-06-01T10:30:00.000Z'
                    updatedAt: '2026-06-10T09:00:00.000Z'
                    headJournalId: 550e8400-e29b-41d4-a716-446655440900
            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)
    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.

````