---
title: "Update a Sale"
method: PUT
path: "/api/v1/sales/{id}"
tags: ["Sales"]
---

# Update a Sale

`PUT /api/v1/sales/{id}`

Permissions needed: any of (CREATE_CHECKUPS, EDIT_CHECKUPS, CREATE_EDIT_COUNTER_SALE, SELL_SERVICES)

**Discontinued product validation (422)**
The following rules apply when a product is discontinued (soft-deleted):
- A new `sold_products` entry whose `product_id` refers to a discontinued product is rejected.
- For an existing treatment whose product is discontinued, `quantity`, `unit_id`, and `purchase_order_items`
  (both the set of IDs and their quantities) must not differ from the stored values.

- For an existing `sold_services[].products` item whose product is discontinued, `quantity`, `unit_id`, and
  `purchase_order_items` (both the set of IDs and their quantities) must not differ from the stored values.

- An existing sold item whose product is discontinued (or whose product no longer exists) may still be
  removed by omitting it from the payload; no stock adjustment is made for it on removal.

## Parameters

- `#/paths/~1api~1v1~1sales/delete/parameters/0` — unresolved $ref

## Request body

- object
  - `remove_irrelevant_tasks` boolean
  - `discount` number, float, nullable
  - `discount_percentage` number, float, nullable
  - `discount_type` 'fixed' | 'percentage', nullable
  - `discount_reason` object, nullable
    - `reason` string, nullable
    - `is_private` 'public' | 'private'
  - `predefined_discounts` integer[]
  - `sold_products` object[]
    - `id` integer — ID of an existing treatment. Omit or set to null for new treatments.
    - `product_id` integer — Product to sell. Cannot refer to a discontinued (soft-deleted) product when creating a new treatment.
    - `vet_id` number, float
    - `unit_id` 'unit' | 'subunit' — Cannot be changed for an existing treatment whose product is discontinued.
    - `unit` string
    - `quantity` number, float — Cannot be changed for an existing treatment whose product is discontinued.
    - `sale_price` number, float
    - `sale_price_with_vat` number, float
    - `vat` number, float — Deprecated for lines referencing a catalog item — use `tax_rate_ids`. Still required on write-in lines (no `product_id` / `service_package_id`).
    - `tax_rate_ids` integer[] — Tax rate ids to apply. Takes precedence over `vat` when present. Send at most the clinic's `max_tax_rates` (1 today).
    - `price` number, float
    - `sub_price` number, float
    - `product_name` string
    - `label` string
    - `recommendations` string
    - `is_checkout_bought` boolean
    - `fixed_fee` number, float
    - `include_fixed_fee` boolean
    - `discount_reason` object, nullable
      - `reason` string, nullable
      - `is_private` 'public' | 'private'
    - `discount` number, float
    - `discount_percentage` number, float
    - `discount_type` 'fixed' | 'percentage'
    - `price_threshold_type` 'minimum' | 'maximum'
    - `purchase_order_items` object[] — For an existing treatment whose product is discontinued, the set of batch IDs and their quantities must exactly match the stored values. Any addition, removal, or quantity change results in a 422.
      - `id` integer — ID of the purchase order item (batch).
      - `quantity` number, float
  - `sold_services` object[]
    - `id` integer
    - `service_package_id` integer
    - `quantity` number, float
    - `price` number, float
    - `unit_price` number, float
    - `vat` number, float — Deprecated for lines referencing a catalog item — use `tax_rate_ids`. Still required on write-in lines (no `product_id` / `service_package_id`).
    - `tax_rate_ids` integer[] — Tax rate ids to apply. Takes precedence over `vat` when present. Send at most the clinic's `max_tax_rates` (1 today).
    - `vet_id` number, float
    - `name` string
    - `original_price` number, float
    - `is_checkout_bought` boolean
    - `discount` number, float
    - `discount_percentage` number, float
    - `discount_type` 'fixed' | 'percentage'
    - `discount_reason` object, nullable
      - `reason` string, nullable
      - `is_private` 'public' | 'private'
    - `aaha_code` string
    - `products` object[]
      - `id` integer
      - `product_id` integer
      - `units` unknown[]
        - unknown
      - `formula` number, float
      - `unit_price_with_vat` number, float
      - `subunit_price_with_vat` number, float
      - `unit_id` 'unit' | 'subunit' — Cannot be changed for an existing service product whose product is discontinued.
      - `quantity` number, float — Cannot be changed for an existing service product whose product is discontinued.
      - `label` string
      - `recommendations` string
      - `name` string
      - `displayed` boolean
      - `purchase_order_items` object[] — For an existing service product whose product is discontinued, the set of batch IDs and their quantities must exactly match the stored values. Any addition, removal, or quantity change results in a 422.
        - `id` integer — ID of the purchase order item (batch).
        - `quantity` number, float

## Response `200`

- object
  - `data` Data — unresolved $ref

## Other responses

- `400` — unresolved $ref
- `401` — unresolved $ref
- `403` — unresolved $ref
- `422` — unresolved $ref
- `429` — unresolved $ref

---

[API](https://skmtc.net/digitail/apis/digitail-api.md) · [All operations](https://skmtc.net/digitail/apis/digitail-api/llms.txt) · [OpenAPI document](https://skmtc-service-staging.skmtc.workers.dev/v1/apis/digitail/digitail-api/revisions/bd9694db5fce/schema)
