# Product guide

## Product Guide <a href="#dexkj" id="dexkj"></a>

This guide provides a foundation on how to work with the [products API](/api-s/api-2.1/products.md). To get a foundation for how products are structured and their different features the [product structure user guide](https://support.younium.com/hc/en-us/articles/360038782551-Product-Structure) is a good place to start.

### Product type and object structure <a href="#hm9nb" id="hm9nb"></a>

The **product type** defines how many charge plans and charges a product can have. Every product must contain at least one charge plan, and every charge plan must contain at least one charge.

There are four product types:

* **Simple** – One charge plan with one charge.
* **MultipleCharges** – One charge plan with multiple charges.
* **MultipleChargePlans** – Multiple charge plans, each with one charge.
* **Full** – Multiple charge plans with multiple charges.

**Example: Simple product response**

```json
"product": {
    "productNumber": "P-000001",
    "chargePlans": [
        {
            "chargePlanNumber": "CP-000001",
            "charges": [
                {
                     "chargeNumber": "C-000001",
                     "priceDetails": [...]
                }
            ]
        }
    ]
}
```

**Example: Full Product Response**

```json
"product": {
    "productNumber": "P-000001",
    "chargePlans": [
        {
            "chargePlanNumber": "CP-000001",
            "charges": [
                {
                     "chargeNumber": "C-000001",
                     "priceDetails": [...]
                },
                {
                     "chargeNumber": "C-000002",
                     "priceDetails": [...]
                }
            ]
        },
        {
            "chargePlanNumber": "CP-000002",
            "charges": [
                {
                     "chargeNumber": "C-000003",
                     "priceDetails": [...]
                },
                {
                     "chargeNumber": "C-000004",
                     "priceDetails": [...]
                },
                {
                     "chargeNumber": "C-000005",
                     "priceDetails": [...]
                }
            ]
        },
    ]
}
```

### Charge Plans

A charge plan is primarily a **container** for charges. While it contains only general fields, it plays an important role by linking **order products** (products on an order) to their originating product and charges.

#### Charges <a href="#ufmqp" id="ufmqp"></a>

Charges are the most important part of the product and hold the most important information, which makes them more complex with a number of important fields.\
The fields on the charge object can be separated into different categories.

“General fields”, “charge configuration fields”, and “financial fields”

In the following JSON example, the fields are sorted by each category.

### Charges

Charges are the **core element** of a product. They contain the most critical information and are therefore more complex, with fields that can be organized into three categories:

1. **General fields**
2. **Charge configuration fields**
3. **Financial properties**

#### Example: Charge Object

```json
{ 
    //"General fields" 
    "name": "string", 
    "customFields": {
        "customFieldKey": "string"
    }, 
    "externalCRMId": "string", 
    "externalERPId": "string", 
     
    //charge configuration fields 
    "chargeType": "Recurring", 
    "model": "Quantity", 
    "unit": "units", 
    "pricePeriod": "Monthly, 
    "defaultQuantity": 0, 
    "usageRating": "Sum", 
    "measurementsRule": 0, 
    "PriceDetails": [ 
        { 
            "tier": 0, 
            "currency": "EUR", 
            "price": 10, 
            "customFields": {}, 
            "description": "string", 
            "isInfinite": false, 
            "priceBase": "Flat", 
            "toQuantity": 0 
        } 
    ], 
 
    //Financial properties 
    "billingPeriod": "Monthly", 
    "periodAlignment": "None", 
    "billingDay": "None", 
    "billingTiming" "InAdvance" 
    "specificBillingDay": 0, 
    "taxIncluded": false, 
    "revenueRecognition": "Recognized monthly over time", 
    "taxTemplate": "Sweden standard", 
    "deferredRevenueAccount": "2970", 
    "recognizedRevenueAccount": "3000" 
}
```

#### General fields <a href="#tpelm" id="tpelm"></a>

General identifiers for a charge and other detail fields. Read more about custom fields and external ids in the [developer resources section](/documentation/developer-resources/developer-resources.md)

#### Charge configuration fields <a href="#pgpep" id="pgpep"></a>

These fields define the **type** and **pricing model** of a charge and the **charge type** determines which pricing models are valid. The relevance of the other fields are dictated by the Type and model combination. The matrices below show the relationship between the fields and the type and model a charge has.

<table data-header-hidden data-full-width="true"><thead><tr><th width="167"></th><th width="87"></th><th width="99"></th><th width="92"></th><th width="98"></th><th width="103"></th><th width="96"></th><th width="88"></th><th width="92"></th><th></th><th></th><th></th><th></th><th></th><th></th><th></th></tr></thead><tbody><tr><td><code>chargeType</code></td><td>One-off</td><td></td><td></td><td></td><td>Usage</td><td></td><td></td><td></td><td>Measured</td><td></td><td></td><td>Recurring</td><td></td><td></td><td></td></tr><tr><td><code>model</code></td><td>Flat</td><td>Quantity</td><td>Volume</td><td>Tiered</td><td>Quantity</td><td>Volume</td><td>Tiered</td><td>Rated</td><td>Quantity</td><td>Volume</td><td>Tiered</td><td>Flat</td><td>Quantity</td><td>Volume</td><td>Tiered</td></tr><tr><td><code>PriceDetails</code></td><td><strong>x</strong></td><td><strong>x</strong></td><td><strong>x</strong></td><td><strong>x</strong></td><td><strong>x</strong></td><td><strong>x</strong></td><td><strong>x</strong></td><td></td><td><strong>x</strong></td><td><strong>x</strong></td><td><strong>x</strong></td><td><strong>x</strong></td><td><strong>x</strong></td><td><strong>x</strong></td><td><strong>x</strong></td></tr><tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr><tr><td><code>unit</code></td><td></td><td><strong>x</strong></td><td><strong>x</strong></td><td><strong>x</strong></td><td><strong>x</strong></td><td><strong>x</strong></td><td><strong>x</strong></td><td><strong>x</strong></td><td><strong>x</strong></td><td><strong>x</strong></td><td><strong>x</strong></td><td></td><td><strong>x</strong></td><td><strong>x</strong></td><td><strong>x</strong></td></tr><tr><td><code>defaultQuantity</code></td><td></td><td><strong>x</strong></td><td><strong>x</strong></td><td><strong>x</strong></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td><strong>x</strong></td><td><strong>x</strong></td><td><strong>x</strong></td></tr><tr><td><code>pricePeriod</code></td><td></td><td></td><td></td><td></td><td><strong>x</strong></td><td><strong>x</strong></td><td><strong>x</strong></td><td><strong>x</strong></td><td><strong>x</strong></td><td><strong>x</strong></td><td><strong>x</strong></td><td><strong>x</strong></td><td><strong>x</strong></td><td><strong>x</strong></td><td><strong>x</strong></td></tr><tr><td><code>usageRating</code></td><td></td><td></td><td></td><td></td><td><strong>x</strong></td><td><strong>x</strong></td><td><strong>x</strong></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr><tr><td><code>measurementRules</code></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td><strong>x</strong></td><td><strong>x</strong></td><td><strong>x</strong></td><td></td><td></td><td></td><td></td></tr></tbody></table>

Most values can be set even if they have no relevance for the type and model and will be ignored when the charge is used. If a value is required or invalid in a specific use case, this will be stated in the documentation or throw a validation error on the request.

#### Financial fields <a href="#id-9gvjv" id="id-9gvjv"></a>

These fields are connected to how the charge will be billed on an order and act as default values for the order product charge (the charge of an order) when it’s created.

#### Default charge values <a href="#rh9j4" id="rh9j4"></a>

Default values for charges can be set in the **Younium UI** under: `Settings > Products > Product settings`.

* If a field is not included or set to `null` in the request, it will fall back to the defined default (if available).
* Some fields (e.g., `revenueRecognition`, `taxTemplate`, `deferredRevenueAccount`, `recognizedRevenueAccount`) may remain null if no default exists.

In certain cases, this behavior is preferred, as these values can instead be set when a Subscription or Sales order is created.

#### Price details <a href="#u4cbn" id="u4cbn"></a>

Every charge (except rated usage charges) requires at least one **price detail**. Price details define the pricing rules and depend on the charge’s pricing model.

Key rules:

* The **tier index** starts at 0 and increments by 1.
* Each `toQuantity` must be greater than the previous tier’s `toQuantity`.
* The last tier may omit `toQuantity` if `isInfinite = true`.
* If no currency is set, the legal entity’s base currency is applied.
* For **flat** or **quantity** models, there is only one price detail per currency (tier = 0).
* For **volume** or **tiered** models, multiple tiers per `currency` are supported.

#### Product category <a href="#yefnc" id="yefnc"></a>

The **product category** helps organize products (e.g., for reporting). Categories are defined under:\
`Settings > Products > Product categories`.

## Creating a product <a href="#id-0vuiu" id="id-0vuiu"></a>

The POST `/products` endpoint is used for creating products.

Example request for a **simple subscription** of a monthly recurring flat fee:

```json
{
    "name": "SaaS",
    "productType": "Simple",
    "category": "Core service",
    "isFrameworkProduct": false,
    "chargePlans": [
        {
            "name": "SaaS charge plan",
            "charges": [
                {
                    "name": "SaaS monthly fee",
                    "model": "Flat",
                    "chargeType": "Recurring",
                    "pricePeriod": "Monthly",
                    "billingDay": "FromOrder",
                    "specificBillingDay": 0,
                    "billingPeriod": "Annual",
                    "periodAlignment": "AlignToOrder",
                    "billingTiming": "InAdvance",
                    "taxTemplate": "Sweden Standard",
                    "taxIncluded": false,
                    "deferredRevenueAccount": "24xx",
                    "recognizedRevenueAccount": "30xx",
                    "customFields": {
                        "customChargeField": "string"
                    },
                    "priceDetails": [
                        {
                            "currency": "SEK",
                            "price": 1099.00
                        },
                        {
                            "currency": "EUR",
                            "price": 99.00
                        },
                        {
                            "currency": "DKK",
                            "price": 749.00
                        },
                        {
                            "currency": "USD",
                            "price": 99.00
                        },
                        {
                            "currency": "NOK",
                            "price": 1099.00
                        }
                    ]
                }
            ]
        }
    ],
    "customFields": {
        "customProductField": "string"
    }
}
```

Remarks about the request:

* Note that the `tier` doesn’t have to be set on the `price details` in this case as there can be only one per currency. Tier will get the value 0 as default.

#### Creating a full product example <a href="#s0suk" id="s0suk"></a>

Say we are offering a SaaS in which there are 3 plans: starter, professional. In each plan, there is a recurring base fee for 99, 400 and including 5, 15, and 30 seats, respectively, and above those included seats, there’s a volume-based discounted price tier.

For example, for the starter plan

| 0-5    | 0 (included) |
| ------ | ------------ |
| 6-20   | 30 per seat  |
| 21-*∞* | 20 per seat  |

```json
{
    "name": "SaaS",
    "productType": "Full",
    "category": "Core service",
    "isFrameworkProduct": false,
    "chargePlans": [
        {
            "name": "Starter",
            "charges": [
                {
                    "name": "Starter base fee",
                    "model": "Flat",
                    "chargeType": "Recurring",
                    "priceDetails": [
                        {
                            "currency": "EUR",
                            "price": 99
                        },
                        {
                            "currency": "USD",
                            "price": 99
                        }
                    ]
                },
                {
                    "name": "Starter seats fee",
                    "model": "Tiered",
                    "chargeType": "Recurring",
                    "defaultQuantity": 5,
                    "unit": {
                        "key": "unit",
                        "value": "seats"
                    },
                    "priceDetails": [
                        {
                            "tier": 0,
                            "currency": "EUR",
                            "toQuantity": 5,
                            "priceBase": "perUnit",
                            "price": 0
                        },
                        {
                            "tier": 1,
                            "currency": "EUR",
                            "toQuantity": 20,
                            "priceBase": "perUnit",
                            "price": 30
                        },
                        {
                            "tier": 2,
                            "currency": "EUR",
                            "isInfinite": true,
                            "priceBase": "perUnit",
                            "price": 20
                        },
                        {
                            "tier": 0,
                            "currency": "USD",
                            "toQuantity": 5,
                            "priceBase": "perUnit",
                            "price": 0
                        },
                        {
                            "tier": 1,
                            "currency": "USD",
                            "toQuantity": 20,
                            "priceBase": "perUnit",
                            "price": 30
                        },
                        {
                            "tier": 2,
                            "currency": "USD",
                            "isInfinite": true,
                            "priceBase": "perUnit",
                            "price": 20
                        }
                    ]
                }
            ]
        },
        {
            "name": "Professional",
            "charges": [
                {
                    "name": "Professional base fee",
                    "model": "Flat",
                    "chargeType": "Recurring",
                    "priceDetails": [
                        {
                            "currency": "EUR",
                            "price": 400
                        },
                        {
                            "currency": "USD",
                            "price": 400
                        }
                    ]
                },
                {
                    "name": "Professional seats fee",
                    "model": "Tiered",
                    "chargeType": "Recurring",
                    "defaultQuantity": 15,
                    "unit": {
                        "key": "unit",
                        "value": "seats"
                    },
                    "priceDetails": [
                        {
                            "tier": 0,
                            "currency": "EUR",
                            "toQuantity": 5,
                            "priceBase": "perUnit",
                            "price": 0
                        },
                        {
                            "tier": 1,
                            "currency": "EUR",
                            "toQuantity": 20,
                            "priceBase": "perUnit",
                            "price": 30
                        },
                        {
                            "tier": 2,
                            "currency": "EUR",
                            "isInfinite": true,
                            "priceBase": "perUnit",
                            "price": 20
                        },
                        {
                            "tier": 0,
                            "currency": "USD",
                            "toQuantity": 5,
                            "priceBase": "perUnit",
                            "price": 0
                        },
                        {
                            "tier": 1,
                            "currency": "USD",
                            "toQuantity": 20,
                            "priceBase": "perUnit",
                            "price": 30
                        },
                        {
                            "tier": 2,
                            "currency": "USD",
                            "isInfinite": true,
                            "priceBase": "perUnit",
                            "price": 20
                        }
                    ]
                }
            ]
        }
    ]
}
```

## Patching a product <a href="#blujk" id="blujk"></a>

The `PATCH /products/{id}` endpoint updates existing products and can add, modify, or remove charge plans, charges, and price details.

#### Operation Field

Entities can include an `operation` field with values:

* **Create** – Ignores lookup key; all child entities inherit `Create`.
* **Remove** – Requires lookup key; child entities inherit `Remove`.
* **Change** (default) – Requires lookup key; affects only that entity.

Price details do not use lookup keys. They are identified by the combination of `tier` and `currencyCode`.

#### Rules and Limitations

* Removing entities may fail if they are already used in a subscription or sales order.
* Changing product type may require explicit removal of charges/charge plans.
* Changing the model may automatically alter or remove price details.
* New entities receive default values unless otherwise specified.
* Framework products currently support patching only at the product level (not charges or charge plans).

> ⚠️ **Caution:** Updates are **irreversible**. Deleted entities cannot be recovered.

#### Patching a full product endpoint <a href="#m9koe" id="m9koe"></a>

Taking the above example request of creating a full product and updating it with:

* Adding an enterprise charge plan
* Removing the middle tiers on the Starter tiered charge.
* Updating the price on the flat recurring fee on the Professional charge plan

```json
{
    "name": "SaaS-updated",
    "chargePlans": [
        {
            "chargePLan": "CP-000001",
            "name": "Starter-updated",
            "charges": [
                {
                    "charge": "C-000002",
                    "defaultQuantity": 10,
                    "priceDetails": [
                        {
                            "tier": 0,
                            "currency": "EUR",
                            "toQuantity": 10,
                            "price": 5
                        },
                        {
                            "operation": "Remove",
                            "tier": 1,
                            "currency": "EUR"
                        },
                        {
                            "tier": 0,
                            "currency": "USD",
                            "toQuantity": 10,
                            "price": 5
                        },
                        {
                            "operation": "Remove",
                            "tier": 1,
                            "currency": "USD"
                        }
                    ]
                }
            ]
        },
        {
            "chargePLan": "CP-000001",
            "name": "Professional-updated",
            "charges": [
                {
                    "charge": "C-000003",
                    "priceDetails": [
                        {
                            "tier": 0,
                            "currency": "EUR",
                            "price": 500
                        },
                        {
                            "tier": 0,
                            "currency": "USD",
                            "price": 500
                        }
                    ]
                },
                {
                    "charge": "C-000004",
                    "priceDetails": [
                        {
                            "tier": 1,
                            "currency": "EUR",
                            "price": 35
                        },
                        {
                            "tier": 2,
                            "currency": "EUR",
                            "price": 25
                        },
                        {
                            "tier": 1,
                            "currency": "USD",
                            "price": 35
                        },
                        {
                            "tier": 2,
                            "currency": "USD",
                            "price": 25
                        }
                    ]
                }
            ]
        },
        {
            "operation": "create",
            "name": "Enterprise",
            "charges": [
                {
                    "name": "Enterprise base fee",
                    "model": "Flat",
                    "chargeType": "Recurring",
                    "priceDetails": [
                        {
                            "currency": "EUR",
                            "price": 1000
                        },
                        {
                            "currency": "USD",
                            "price": 1000
                        }
                    ]
                },
                {
                    "name": "Enterprise pcs fee",
                    "model": "Tiered",
                    "chargeType": "Recurring",
                    "defaultQuantity": 30,
                    "unit": {
                        "key": "name",
                        "value": "pcs"
                    },
                    "priceDetails": [
                        {
                            "tier": 0,
                            "currency": "EUR",
                            "toQuantity": 5,
                            "priceBase": "perUnit",
                            "price": 0
                        },
                        {
                            "tier": 1,
                            "currency": "EUR",
                            "toQuantity": 20,
                            "priceBase": "perUnit",
                            "price": 30
                        },
                        {
                            "tier": 2,
                            "currency": "EUR",
                            "isInfinite": true,
                            "priceBase": "perUnit",
                            "price": 20
                        },
                        {
                            "tier": 0,
                            "currency": "USD",
                            "toQuantity": 5,
                            "priceBase": "perUnit",
                            "price": 0
                        },
                        {
                            "tier": 1,
                            "currency": "USD",
                            "toQuantity": 20,
                            "priceBase": "perUnit",
                            "price": 30
                        },
                        {
                            "tier": 2,
                            "currency": "USD",
                            "isInfinite": true,
                            "priceBase": "perUnit",
                            "price": 20
                        }
                    ]
                }
            ]
        }
    ]
}
```

## Deleting a product <a href="#ow6mr" id="ow6mr"></a>

Products or their child entities can be deleted using the relevant API endpoints.

* Entities in use on an order cannot be deleted.
* Price details should be removed by updating the charge via `PATCH`.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://developer.younium.com/documentation/product-guide.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
