---
title: "Mark an estimate line performed. For an undispensed inventory line this runs the in-visit dispense (stamping `InventoryTransactionId` on the line; no Invoice involvement until convert). Gas items have no transaction."
method: POST
path: "/Estimates/{id}/items/{lineId}/perform"
tags: ["Estimates"]
---

# Mark an estimate line performed. For an undispensed inventory line this runs the in-visit dispense (stamping \`InventoryTransactionId\` on the line; no Invoice involvement until convert). Gas items have no transaction.

`POST /Estimates/{id}/items/{lineId}/perform`

## Request

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

## Path parameters

- `id` string, required
- `lineId` string, required

## Request body

- PerformEstimateItemRequest
  - `dispenseType` string, nullable: InHouse (administered now) or Prescription (take-home). Defaults to InHouse.
  - `disposition` string, nullable: Explicit dispense disposition (InHouse | TakeHomeLabelNow | TakeHomeLabelLater). When supplied it is persisted on the line and drives the convert gate (take-home requires the SIG filled; in-house never blocks). Falls back to a mapping from string? PerformEstimateItemRequest.DispenseType when omitted.
  - `overrideValidation` boolean
  - `overrideReason` string, nullable
  - `lotId` string, nullable: ITE-157: the confirmed lot/container for a plain inventory line (null = FEFO/auto).
  - `containerId` string, nullable
  - `containerPins` object, nullable: ITE-1361: per-lot container pins (lot id → container row id) for a blank-lot perform that the engine splits earliest-expiry-first across lots. See Dictionary&lt;string, string&gt;? DispenseItemDto.ContainerPins.
  - `witnessUserId` string, nullable: Real witness for a controlled-substance dispense — replaces the appointment self-witness when supplied.
  - `components` FulfillComponentDto[]: Charge (BillableItem) component override (design §2.3). When the performed line is a charge, these mirror FulfillBillableItemDto: each default component may be kept, substituted, skipped, or dispensed at a different `quantity`; ad-hoc components may be added. Empty for a plain inventory line or a charge dispensed at its catalog defaults.
    - `componentId` string, nullable: The BillableItemComponent this resolution applies to.
    - `inventoryItemId` string, nullable: Alternative match key when componentId is not supplied.
    - `skip` boolean: POS override (1c-3): omit this default component from the fulfillment — nothing is dispensed for it. Requires `ComponentOverrideReason`.
    - `substituteInventoryItemId` string, nullable: POS override (1c-3): dispense this inventory item in place of the default component's item (same quantity). Requires `ComponentOverrideReason`.
    - `quantity` union: Explicit quantity. Required for ad-hoc `AdditionalComponents`. For a catalog (default or substituted) component it is OPTIONAL and overrides the computed `QuantityMultiplier × line qty` — e.g. the patient used more or less than the bundle's default. Must be &gt; 0 (use bool FulfillComponentDto.Skip to remove a component). A quantity that differs from the default counts as an override and requires `ComponentOverrideReason`. A charge is fixed-price, so this only changes the stock consumed, never the bill.
      - number, double
      - string, double
    - `lotId` string, nullable: Explicit lot; empty/omitted ⇒ FEFO auto-allocation.
    - `locationId` string, nullable: Storage location to decrement; omitted ⇒ no per-location decrement.
    - `witnessUserId` string, nullable
    - `dispenseType` string, nullable: "InHouse" (default) or "Prescription". Legacy; prefer string? FulfillComponentDto.Disposition.
    - `disposition` string, nullable: Per-component dispense disposition: "InHouse" (administered now, no script), "TakeHomeLabelNow" (take-home, fill the Rx label now), or "TakeHomeLabelLater" (take-home, stock moves now, label filled afterward — blocks convert until filled). When omitted the charge's line-level default applies (back-compat). The engine derives DispenseType + DeferRxDetails from this, so the SIG fields below are required only for "TakeHomeLabelNow".
    - `dosage` string, nullable
    - `frequency` string, nullable
    - `duration` string, nullable
    - `instructions` string, nullable
    - `refillsAllowed` union
      - integer
      - string, int32
    - `collectorName` string, nullable
    - `collectorIdChecked` boolean, nullable
    - `overrideValidation` boolean
    - `overrideReason` string, nullable
    - `notes` string, nullable
    - `route` string, nullable: Vaccine administration route (e.g. "Subcutaneous"). Required when this component is a vaccine — the dispense stamps it onto the auto-created VaccinationRecord, mirroring the standalone vaccine-administration flow.
    - `site` string, nullable: Vaccine administration site (e.g. "Left foreleg"). Required for vaccine components.
  - `additionalComponents` FulfillComponentDto[]: Ad-hoc components dispensed alongside the charge's catalog defaults.
    - `componentId` string, nullable: The BillableItemComponent this resolution applies to.
    - `inventoryItemId` string, nullable: Alternative match key when componentId is not supplied.
    - `skip` boolean: POS override (1c-3): omit this default component from the fulfillment — nothing is dispensed for it. Requires `ComponentOverrideReason`.
    - `substituteInventoryItemId` string, nullable: POS override (1c-3): dispense this inventory item in place of the default component's item (same quantity). Requires `ComponentOverrideReason`.
    - `quantity` union: Explicit quantity. Required for ad-hoc `AdditionalComponents`. For a catalog (default or substituted) component it is OPTIONAL and overrides the computed `QuantityMultiplier × line qty` — e.g. the patient used more or less than the bundle's default. Must be &gt; 0 (use bool FulfillComponentDto.Skip to remove a component). A quantity that differs from the default counts as an override and requires `ComponentOverrideReason`. A charge is fixed-price, so this only changes the stock consumed, never the bill.
      - number, double
      - string, double
    - `lotId` string, nullable: Explicit lot; empty/omitted ⇒ FEFO auto-allocation.
    - `locationId` string, nullable: Storage location to decrement; omitted ⇒ no per-location decrement.
    - `witnessUserId` string, nullable
    - `dispenseType` string, nullable: "InHouse" (default) or "Prescription". Legacy; prefer string? FulfillComponentDto.Disposition.
    - `disposition` string, nullable: Per-component dispense disposition: "InHouse" (administered now, no script), "TakeHomeLabelNow" (take-home, fill the Rx label now), or "TakeHomeLabelLater" (take-home, stock moves now, label filled afterward — blocks convert until filled). When omitted the charge's line-level default applies (back-compat). The engine derives DispenseType + DeferRxDetails from this, so the SIG fields below are required only for "TakeHomeLabelNow".
    - `dosage` string, nullable
    - `frequency` string, nullable
    - `duration` string, nullable
    - `instructions` string, nullable
    - `refillsAllowed` union
      - integer
      - string, int32
    - `collectorName` string, nullable
    - `collectorIdChecked` boolean, nullable
    - `overrideValidation` boolean
    - `overrideReason` string, nullable
    - `notes` string, nullable
    - `route` string, nullable: Vaccine administration route (e.g. "Subcutaneous"). Required when this component is a vaccine — the dispense stamps it onto the auto-created VaccinationRecord, mirroring the standalone vaccine-administration flow.
    - `site` string, nullable: Vaccine administration site (e.g. "Left foreleg"). Required for vaccine components.
  - `componentOverrideReason` string, nullable: Required when the charge's dispensed component set deviates from the catalog default (skip / substitute / quantity change / addition).

## Response `200`

OK

- 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

## Changes

- **2026-10-28** `099cf36186e0`: 12 info
  - added the optional property `groupCodeId` to the response with the `200` status (media type: text/plain)
  - added the optional property `groupCodeId` to the response with the `200` status (media type: application/json)
  - added the optional property `groupCodeId` to the response with the `200` status (media type: text/json)
  - added the optional property `groupCodeName` to the response with the `200` status (media type: text/plain)
  - …8 more
- **2026-10-21** `85ee96c0bb96`: 6 info
  - added the new optional request property `oneOf[#/components/schemas/PerformEstimateItemRequest]/containerPins` (media type: application/json)
  - added the new optional request property `oneOf[#/components/schemas/PerformEstimateItemRequest]/containerPins` (media type: text/json)
  - added the new optional request property `oneOf[#/components/schemas/PerformEstimateItemRequest]/containerPins` (media type: application/*+json)
  - added the optional property `groupId` to the response with the `200` status (media type: text/plain)
  - …2 more
- …earlier changes not shown

[Operation history](https://skmtc.dev/clinicos/apis/pawthosx-business-api-v1/changes/Estimates/:id/items/:lineId/perform/post.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)
