---
title: "Link a pre-existing open estimate to an appointment. Honors the unique index on `treatment_plans.appointment_id` (one estimate per appointment): * No estimate on the appointment yet → set AppointmentId on the chosen one. * The appointment's auto-created estimate is empty → drop it and re-point the chosen estimate (preserves the chosen estimate's identity + consent history). * The appointment's estimate already has lines → merge the chosen estimate's lines into it and remove the chosen estimate. Its consent trail moves to the survivor first and an ConsentEventType.EstimateMerged event records the merge (ITE-1450). A removed estimate's consent events are always re-parented, never cascade-deleted. Returns the resulting estimate the Services tab should render."
method: POST
path: "/Estimates/{id}/link-appointment"
tags: ["Estimates"]
---

# Link a pre-existing open estimate to an appointment. Honors the unique index on \`treatment_plans.appointment_id\` (one estimate per appointment): \* No estimate on the appointment yet → set AppointmentId on the chosen one. \* The appointment's auto-created estimate is empty → drop it and re-point the chosen estimate (preserves the chosen estimate's identity + consent history). \* The appointment's estimate already has lines → merge the chosen estimate's lines into it and remove the chosen estimate. Its consent trail moves to the survivor first and an ConsentEventType.EstimateMerged event records the merge (ITE-1450). A removed estimate's consent events are always re-parented, never cascade-deleted. Returns the resulting estimate the Services tab should render.

`POST /Estimates/{id}/link-appointment`

## Request

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

## Path parameters

- `id` string, required

## Request body

- LinkAppointmentRequest: Link a pre-existing open estimate to an appointment (chronicle Services tab).
  - `appointmentId` 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`: 6 info
  - added the optional property `groups` to the response with the `200` status (media type: text/plain)
  - added the optional property `groups` to the response with the `200` status (media type: application/json)
  - added the optional property `groups` to the response with the `200` status (media type: text/json)
  - added the optional property `items/items/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/link-appointment/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)
