---
title: "Save how the estimate's lines are grouped and ordered (EstimateLineGroups) — the whole layout in one write, so a drag can never leave half an order behind. Creates, renames, reorders and deletes groups, and re-sequences every line's `DisplayOrder` to match EstimateLineLayout. Presentational only: no price, quantity or execution state changes, so it records no consent event and never trips the consent gate. Lines the request doesn't mention (e.g. added by someone else meanwhile) keep their relative order at the end of the ungrouped lines."
method: PUT
path: "/Estimates/{id}/layout"
tags: ["Estimates"]
---

# Save how the estimate's lines are grouped and ordered (EstimateLineGroups) — the whole layout in one write, so a drag can never leave half an order behind. Creates, renames, reorders and deletes groups, and re-sequences every line's \`DisplayOrder\` to match EstimateLineLayout. Presentational only: no price, quantity or execution state changes, so it records no consent event and never trips the consent gate. Lines the request doesn't mention (e.g. added by someone else meanwhile) keep their relative order at the end of the ungrouped lines.

`PUT /Estimates/{id}/layout`

## Request

- Base URL: `https://api.clinicos.vet/backend/business`
- URL: `https://api.clinicos.vet/backend/business/Estimates/{id}/layout`
- Auth: HTTP bearer
- TypeScript: <https://skmtc.dev/clinicos/apis/pawthosx-business-api-v1/docs/Estimates/:id/layout/put.ts> (a function with typed inputs; its response is checked against the schema)

## Path parameters

- `id` string, required

## Request body

- SaveEstimateLayoutRequest: `PUT /estimates/{id}/layout`: the whole grouping and order in one write. Groups are listed in display order, each with its line ids in order; List&lt;string&gt; SaveEstimateLayoutRequest.UngroupedLineIds follow the groups. A group with no `Id` is created; an existing group left out is deleted (its lines must then be listed elsewhere, or they fall to the end of the ungrouped lines).
  - `groups` EstimateLayoutGroupRequest[]
    - `id` string, nullable: Existing group id, or null to create a new group.
    - `title` string
    - `lineIds` string[]
  - `ungroupedLineIds` string[]

## Response `200`

OK

- EstimateDto
  - `id` string
  - `estimateNumber` string
  - `clientId` string, nullable
  - `clientName` string, nullable
  - `patientId` string, nullable
  - `patientName` string, nullable
  - `appointmentId` string, nullable
  - `status` string
  - `selectedTier` string, nullable
  - `invoiceId` string, nullable
  - `notes` string, nullable
  - `createdById` string, nullable
  - `createdByName` string, nullable
  - `createdAt` string, date-time
  - `updatedAt` string, date-time
  - `items` EstimateLineItemDto[]
    - `id` string
    - `serviceCatalogItemId` string, nullable
    - `retailItemId` string, nullable
    - `inventoryItemId` string, nullable
    - `billableItemId` string, nullable: Source BillableItem ("Charge") id when this line is a charge.
    - `code` string
    - `description` string
    - `unitPrice` union
      - number, double
      - string, double
    - `qtyMode` string
    - `qtyLow` union
      - number, double
      - string, double
    - `qtyMed` union
      - number, double
      - string, double
    - `qtyHigh` union
      - number, double
      - string, double
    - `quantity` union: Billed units. Equals the amount dispensed on a per-unit line; on a flat-rate line it is 1 (0 when nothing is given) and decimal? EstimateLineItemDto.DispensedQuantity is the amount.
      - number, double
      - string, double
    - `isFlatRate` boolean: Flat-rate inventory line: bills one administration at UnitPrice whatever amount is given.
    - `dispensedQuantity` union: Amount given (or planned) on a flat-rate line; null on per-unit lines.
      - number, double
      - string, double
    - `isTaxable` boolean
    - `vatCategory` string, nullable: The source item's VAT category ("standard" | "reduced" | "zero" | "exempt"; null is standard). Prices the line in VAT mode, at the rate convert bills it at (ITE-1539).
    - `note` string, nullable
    - `displayOrder` union
      - integer
      - string, int32
    - `groupId` string, nullable: The EstimateLineGroupDto this line sits under; null when ungrouped.
    - `createdByAi` boolean: True when the line came from an accepted AI treatment suggestion (ITE-871).
    - `groupCodeId` string, nullable: The kit this line was expanded from; null for a line added on its own.
    - `groupCodeName` string, nullable: The kit's name when it was added.
    - `kitInstanceId` string, nullable: Shared by every line one add of a kit produced.
    - `serviceType` string: "Procedure" | "Inventory" | "Retail" — derived from the source FK.
    - `inventoryItemCategory` string, nullable: InventoryItemCategory ("Vaccine", "Medication", …) for an inventory-backed line; routes the perform flow (e.g. vaccine administration).
    - `executionStatus` string: Pending | Performed | Declined.
    - `disposition` string, nullable: Persisted dispense disposition: InHouse | TakeHomeLabelNow | TakeHomeLabelLater (null for non-dispensing lines).
    - `requiresSig` boolean: True when this performed take-home line still needs its SIG / medication details filled (blocks convert). Drives the per-line "Fill instructions" affordance. In-house lines are never required.
    - `markedForBilling` boolean
    - `dispenseFee` union: Flat per-dispense fee on the line (once per unique inventory item on the estimate).
      - number, double
      - string, double
    - `unitCost` union: Snapshotted lot cost for a dispensed inventory line.
      - number, double
      - string, double
    - `inventoryTransactionId` string, nullable: Set once an inventory line is dispensed in-visit. The void reversal anchors on this.
    - `performedById` string, nullable
    - `performedByName` string, nullable
    - `performedAt` string, date-time, nullable
    - `declinedReason` string, nullable
    - `declinedAt` string, date-time, nullable
    - `isControlledSubstance` boolean: True for a controlled-substance inventory line (gates the void-reason requirement).
    - `lineTotal` union: Computed line total: (UnitPrice × Quantity) + DispenseFee.
      - number, double
      - string, double
    - `discount` union: Manual flat dollar discount entered by staff (0 when none, or when a code is applied).
      - number, double
      - string, double
    - `discountSetById` string, nullable
    - `discountSetByName` string, nullable
    - `discountSetAt` string, date-time, nullable
    - `appliedDiscount` EstimateAppliedDiscountDto: A discount code applied to an estimate (order-level when string? EstimateAppliedDiscountDto.EstimateLineItemId is null).
      - `id` string
      - `estimateLineItemId` string, nullable
      - `discountPolicyId` string
      - `discountCode` string
      - `discountName` string
      - `discountType` string: "Percentage" | "Fixed".
      - `discountValue` union
        - number, double
        - string, double
      - `maxDiscountAmount` union
        - number, double
        - string, double
      - `appliedById` string
      - `appliedByName` string, nullable
      - `appliedAt` string, date-time
    - `discountAmount` union: Staff discount (code or manual) at the working decimal EstimateLineItemDto.Quantity. Excludes price rules.
      - number, double
      - string, double
    - `originalUnitPrice` union: The catalog price before staff overrode decimal EstimateLineItemDto.UnitPrice; null = not overridden.
      - number, double
      - string, double
    - `priceOverriddenById` string, nullable
    - `priceOverriddenByName` string, nullable
    - `priceOverriddenAt` string, date-time, nullable
  - `orderDiscount` EstimateAppliedDiscountDto: A discount code applied to an estimate (order-level when string? EstimateAppliedDiscountDto.EstimateLineItemId is null).
    - `id` string
    - `estimateLineItemId` string, nullable
    - `discountPolicyId` string
    - `discountCode` string
    - `discountName` string
    - `discountType` string: "Percentage" | "Fixed".
    - `discountValue` union
      - number, double
      - string, double
    - `maxDiscountAmount` union
      - number, double
      - string, double
    - `appliedById` string
    - `appliedByName` string, nullable
    - `appliedAt` string, date-time
  - `orderDiscountAmount` union: Order-code discount at the working quantities (non-declined lines). Excludes price rules.
    - number, double
    - string, double
  - `groups` EstimateLineGroupDto[]: Titled line sections in display order (EstimateLineGroups). List&lt;EstimateLineItemDto&gt; EstimateDto.Items is already in layout order: each group's lines in group order, then the ungrouped lines.
    - `id` string
    - `title` string
    - `displayOrder` union
      - integer
      - string, int32
    - `origin` string: "Manual" | "Kit" | "Auto". Server-owned; layout saves never write it.
    - `isPinned` boolean: True once staff renamed or moved the group. Server-owned.

## Changes

- **2026-10-28** `099cf36186e0`: 18 info
  - added the optional property `groups/items/isPinned` to the response with the `200` status (media type: text/plain)
  - added the optional property `groups/items/isPinned` to the response with the `200` status (media type: application/json)
  - added the optional property `groups/items/isPinned` to the response with the `200` status (media type: text/json)
  - added the optional property `groups/items/origin` to the response with the `200` status (media type: text/plain)
  - …14 more
- **2026-10-21** `85ee96c0bb96`: 1 info
  - endpoint added

[Operation history](https://skmtc.dev/clinicos/apis/pawthosx-business-api-v1/changes/Estimates/:id/layout/put.md)

---

[API](https://skmtc.dev/clinicos/apis/pawthosx-business-api-v1.md) - [All operations](https://skmtc.dev/clinicos/apis/pawthosx-business-api-v1/llms.txt) - [OpenAPI document](https://skmtc.dev/clinicos/apis/pawthosx-business-api-v1/revisions/099cf36186e0?raw)
