--- title: "Price Configuration" slug: "price-configuration" updated: 2026-07-09T05:09:39Z published: 2026-07-09T05:09:39Z canonical: "help.frisbii.com/price-configuration" --- > ## Documentation Index > Fetch the complete documentation index at: https://help.frisbii.com/llms.txt > Use this file to discover all available pages before exploring further. # Price Configuration Prices in Frisbii Media follow a three-level hierarchy: Offer → Contract → Price Issue → Price Segments An **Offer** contains one or more **Products**, each of which has **Steps** (billing phases). Each step references a **Price Issue** by ID. A **Price Issue** contains **Price Segments** — time-limited price entries, of which the most recently activated one is the current price. This indirection means you cannot simply read a price directly off an offer object — you need to resolve it through the price issues. The example below shows how. --- ## Step-by-step: get the current price for an offer ### 1. Get the offer ```php // @see https://api.frisbii-media.com/#tag/Offers/operation/searchProductOffers $response = json_decode($client->request('GET',    '/api/v3.0/products/offers?plenigoOfferId=O_KJHKJHIUZIUZ',    ['headers' => ['X-plenigo-token' => eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9]] )->getBody()->getContents(), true); $offer = $response['items'][0]; ``` ### 2. Get all price issues and resolve the active price per issue A price issue can have multiple segments with different `validFrom` dates. The active price is the segment with the most recent `validFrom` that is still in the past. ```php $now = new DateTime(); $activePriceIssues = []; // getList() is the reusable pagination helper — see Pagination: Iterating API Lists $priceIssues = getList('/products/priceIssues'); foreach ($priceIssues as $issue) {    $segments = [];    foreach ($issue['priceSegments'] as $segment) {        $validFrom = new \DateTime($segment['validFrom']);        if ($validFrom > $now) {            // Segment not yet active — skip            continue;        }        // Use Unix timestamp as key so we can sort chronologically        $segments[$validFrom->getTimestamp()] = $segment;    }    // Sort ascending; the last entry is the most recently activated segment    ksort($segments);    $activePriceIssues[$issue['priceIssueId']] = end($segments); } ``` ### 3. Collect the steps and calculate the price per step Products may appear in `products` or inside `productGroups`. Steps are shared across products — only the first product's steps need to be iterated for the structure, but prices must be summed across all products. ```php // Collect products from both possible locations in the offer $products = ($offer['products'] ?? []); if (!empty($offer['productGroups'][0]['products'])) {    $products = array_merge($products, $offer['productGroups'][0]['products']); } $steps = []; // Use the first product to get the step structure foreach ((reset($products)['steps'] ?? []) as $step) {    $step['price'] = 0.00;    $steps[$step['position']] = $step; // keyed by position for sorting } ksort($steps); // ensure steps are in order // Sum up prices across all products per step foreach ($products as $product) {    foreach ($product['steps'] as $step) {        $priceIssue = $activePriceIssues[$step['priceIssueId']] ?? null;        if (empty($priceIssue)) {            echo "Price issue not found: {$step['priceIssueId']}";            continue;        }        $steps[$step['position']]['price'] += $priceIssue['price'];    } } ``` ### 4. Output the results ```php foreach ($steps as $step) {    // If durationPeriod is 0, the runtime is unlimited    echo "{$step['position']}) "       . "runtime: {$step['durationPeriod']} {$step['durationTimespan']}, "       . "accounting period: {$step['accountingPeriod']} {$step['accountingTimespan']} "       . "— {$step['price']}\n"; } ``` **Example output:** ```plaintext 1) runtime: 0 MONTH, accounting period: 4 WEEK — 23.96 ``` Means: pay €23.96 every 4 weeks, unlimited runtime. ```plaintext 1) runtime: 12 MONTH, accounting period: 1 MONTH — 13.00 2) runtime: 0 MONTH, accounting period: 1 MONTH — 19.00 ``` Means: €13.00/month for the first 12 months, then €19.00/month indefinitely. --- ## Key concepts | Term | Description | | --- | --- | | **Step** | A billing phase of a subscription. An offer can have multiple steps with different durations and prices (e.g. intro price followed by regular price). | | **Position** | The order of steps. Position 1 is the first billing phase. | | **durationPeriod** | How long this step lasts. `0` means unlimited. | | **durationTimespan** | Unit of `durationPeriod`: `DAY`, `WEEK`, `MONTH`, `YEAR`. | | **accountingPeriod** | How often the customer is billed during this step. | | **accountingTimespan** | Unit of `accountingPeriod`. | | **Price Issue** | The container for price history. Multiple segments allow price changes over time without creating new products. | | **Price Segment** | A specific price with a `validFrom` date. The most recently activated segment is the current price. | --- ## API reference - [searchProductOffers](https://api.plenigo.com/#tag/Offers/operation/searchProductOffers) - [searchProductPriceIssues](https://api.plenigo.com/#tag/Price-Issues/operation/searchProductPriceIssues) ---