> ## Documentation Index
> Fetch the complete documentation index at: https://docs2.zenskar.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Products

## Product schema

| Field               | Type   | Required | Description                                                        |
| ------------------- | ------ | -------- | ------------------------------------------------------------------ |
| `name`              | string | Yes      | Product name                                                       |
| `description`       | string | No       | Product description (whitespace-trimmed; blank becomes null)       |
| `sku`               | string | No       | Unique product identifier for business-facing lookups              |
| `type`              | enum   | Yes      | `point_in_time` or `period_of_time`                                |
| `subtype`           | enum   | Yes      | `quantity`, `credits`, or `feature` (must be compatible with type) |
| `unit`              | object | No       | Unit labels — `{ singular: "API call", plural: "API calls" }`      |
| `tax_category`      | string | No       | Zenskar tax code for tax resolution                                |
| `status`            | enum   | No       | `active` (default), `inactive`, or `archived`                      |
| `slug`              | string | No       | Optional reference to an external system                           |
| `custom_attributes` | object | No       | Arbitrary key-value metadata                                       |

## Type-subtype compatibility

| Product type     | Allowed subtypes      |
| ---------------- | --------------------- |
| `point_in_time`  | `quantity`, `credits` |
| `period_of_time` | `quantity`, `feature` |

## Product statuses

| Status     | Description                                                    |
| ---------- | -------------------------------------------------------------- |
| `active`   | Available for use in new contracts                             |
| `inactive` | Not available for new contracts; existing contracts unaffected |
| `archived` | End-of-life; can't be set on creation                          |

## API endpoints

| Method   | Path                        | Description                                   | Permissions                                    |
| -------- | --------------------------- | --------------------------------------------- | ---------------------------------------------- |
| `POST`   | `/v3/products`              | Create a new product                          | `can_read_product`, `can_create_product`       |
| `GET`    | `/v3/products`              | List products (paginated, filterable)         | `can_read_product`                             |
| `GET`    | `/v3/products/pricings`     | Search products with nested pricing presets   | `can_read_product`, `can_read_product_pricing` |
| `GET`    | `/v3/products/{product_id}` | Get a product by ID                           | `can_read_product`                             |
| `PATCH`  | `/v3/products/{product_id}` | Partially update a product                    | `can_read_product`, `can_update_product`       |
| `DELETE` | `/v3/products/{product_id}` | Soft-delete a product and its pricing presets | `can_read_product`, `can_delete_product`       |

## Business validation rules

Enforced by `validate_product_catalog` on create and update.

| # | Rule                            | Applies to      | Error code                          | Description                                                                                             |
| - | ------------------------------- | --------------- | ----------------------------------- | ------------------------------------------------------------------------------------------------------- |
| 1 | Status not archived on create   | Create          | `PRODUCT_CREATED_AS_ARCHIVED`       | New products can't be created with `archived` status; valid initial statuses are `active` or `inactive` |
| 2 | Type-subtype compatibility      | Create          | `PRODUCT_TYPE_SUBTYPE_INCOMPATIBLE` | Subtype must be allowed for the given type                                                              |
| 3 | Product name unique per org     | Create          | `PRODUCT_NAME_DUPLICATE`            | Currently disabled                                                                                      |
| 4 | SKU unique per org              | Create & update | `PRODUCT_SKU_DUPLICATE`             | On update, the product may keep its own existing SKU; skipped if SKU isn't provided                     |
| 5 | Slug unique per org             | Create & update | `PRODUCT_SLUG_DUPLICATE`            | On update, the product may keep its own existing slug; skipped if slug isn't provided                   |
| 6 | Type immutable with pricing     | Update          | `PRODUCT_TYPE_CHANGE_WITH_PRICING`  | Can't change type once pricing presets exist                                                            |
| 7 | Can't deactivate with contracts | Update          | `PRODUCT_DEACTIVATE_WITH_CONTRACTS` | Can't set status to `inactive` if the product is used in any active contract                            |

## Delete constraints

Separate from `validate_product_catalog`.

| Rule                        | Error                                                        | Description                                                 |
| --------------------------- | ------------------------------------------------------------ | ----------------------------------------------------------- |
| Can't delete with contracts | `Cannot delete product as it is being used in {n} contracts` | A product can't be deleted while referenced by any contract |

## Repercussions: product update

| Change                                 | Impact on contracts                                                                                | Impact on invoices                                                             |
| -------------------------------------- | -------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------ |
| Name / description / SKU / slug change | Metadata-only; contracts reference the product by ID and reflect the change on next read           | Future invoices show the updated name; finalized invoices unaffected           |
| Status to `inactive`                   | Blocked if any active contract references the product; finalized contracts continue to function    | No impact on existing invoices; product becomes unavailable for new line items |
| Status to `archived`                   | Product not available for any new usage                                                            | No impact on finalized invoices                                                |
| Type changed                           | Blocked if pricing presets exist; if none exist, only affects how future pricing can be configured | No impact — pricing must be recreated after a type change                      |
| Subtype changed                        | Only validated on create; changing on update may cause inconsistency with existing pricing         | Indirect — may cause pricing computation mismatches                            |
| Unit changed                           | Contracts see updated unit labels, unless a pricing preset overrides the unit                      | Future invoices reflect the new label; finalized invoices unaffected           |
| Custom attributes changed              | Informational only                                                                                 | No impact                                                                      |

## Repercussions: product deletion

| Impact          | Description                                                                                                           |
| --------------- | --------------------------------------------------------------------------------------------------------------------- |
| Contracts       | Deletion blocked if any contracts reference the product                                                               |
| Pricing presets | All pricing presets belonging to the product are soft-deleted with it                                                 |
| Invoices        | Finalized invoices retain historical data; soft-deleted product and pricing remain in the database for audit purposes |

## Not yet available

* Product groups and bundles.
* Editing pricing on an already-created product.
* *(Placeholder: any additional reference items not yet documented.)*
