{
    "schema_version": 3,
    "name": "BlaBlaPrice price index, Canada: October 2026",
    "country": "ca",
    "country_name": "Canada",
    "lang": "en",
    "month": "2026-10",
    "period": {
        "from": "2026-10-01",
        "to": "2026-10-31"
    },
    "currency": "CAD",
    "min_samples": 5,
    "min_model_samples": 3,
    "min_service_unit_samples": 3,
    "schema_changes": {
        "2": "H-023: model level added (fields level, model, brand, model_key, model_samples, model_shops, used, product_id; the models list of each category row; models_count, other_samples, models_note). The version 1 fields keep their names and meaning; a category row reads as before.",
        "3": "H-026: goods and services (fields kind, unit_code, variant, unit_samples, unit_shops; the units list of each category row with level \"unit\" rows; units_count, units_note, unit_label). Goods keep their models; a service has no models (models empty, models_note null) and is grouped by price unit instead, from 3 prices a unit, its category row being its most usual unit. The version 1 and 2 fields keep their names and meaning; ?level=category in the CSV gives the same category lines as before."
    },
    "updated_at": "2026-10-20T13:18:24Z",
    "generated_at": "2026-10-31T17:19:40Z",
    "refresh_hours": 6,
    "html": "https://blablaprice.com/ca/site/price-index/plumbing-work",
    "csv": "https://blablaprice.com/ca/site/price-index.csv?category=plumbing-work",
    "license": "https://creativecommons.org/licenses/by/4.0/",
    "creator": "BlaBlaPrice (EVERLOGIC LLC)",
    "months_available": [
        "2026-10"
    ],
    "fields": [
        "country",
        "lang",
        "month",
        "category_slug",
        "category_name",
        "p25",
        "median",
        "p75",
        "currency",
        "samples",
        "updated_at",
        "unit",
        "shops",
        "requests",
        "level",
        "model",
        "brand",
        "model_key",
        "model_samples",
        "model_shops",
        "used",
        "product_id",
        "kind",
        "unit_code",
        "variant",
        "unit_samples",
        "unit_shops"
    ],
    "field_docs": {
        "country": "country code of the site folder (ISO 3166-1 alpha-2, lower case; \"ua\" = Ukraine, \"us\" = the site root)",
        "lang": "language of category_name (ISO 639-1)",
        "month": "calendar month of the observations, YYYY-MM",
        "category_slug": "address of the category page on this country's site, relative to the country folder",
        "category_name": "category name in lang",
        "p25": "25th percentile of the observed prices (a quarter of the prices are lower), in currency, rounded to 2 significant digits",
        "median": "median (50th percentile) of the observed prices, in currency, rounded to 2 significant digits",
        "p75": "75th percentile of the observed prices (three quarters are lower), in currency, rounded to 2 significant digits",
        "currency": "ISO 4217 code; prices in other currencies are not converted, they are left out",
        "samples": "number of distinct prices behind the row (a goods category at least 5, a service unit at least 3)",
        "updated_at": "time of the newest price in the row, ISO 8601, UTC",
        "unit": "on a category row: price unit when sellers quote per unit (per hour, per m2), as the source wrote it, empty = a whole item or job; on a unit row (level \"unit\"): the unit code, the same as unit_code",
        "shops": "number of distinct sellers (web sites or BlaBlaPrice accounts) behind the row",
        "requests": "number of distinct buyer requests whose web search or offers gave the prices; a small number means the row rests on few searches",
        "level": "\"category\" for a row of all the category's prices, \"model\" for the prices of one model inside a goods category (schema_version 2), \"unit\" for the prices of one unit inside a service category (schema_version 3); in JSON the model rows are in the category row's \"models\" list and the unit rows in its \"units\" list, in CSV they follow their category row",
        "model": "model without the brand, as most shops write it, taken from the shop's product title: series and code, plus the memory or capacity when the title gives it (\"iPhone 14 Pro 256GB\", \"TDLRB 65242BS\"); empty on a category row",
        "brand": "brand named in the title, or the only brand that makes the product line in it (iPhone: Apple, Galaxy: Samsung, Redmi and Poco: Xiaomi); empty on a category row",
        "model_key": "stable key of the model: Latin letters, digits and hyphens, brand first, \"-used\" at the end for used or refurbished goods (\"apple-iphone-14-pro-256gb-used\"); empty on a category row",
        "model_samples": "number of distinct prices of the model (at least 3); equals samples on a model row, empty on a category row",
        "model_shops": "number of distinct sellers of the model; equals shops on a model row, empty on a category row",
        "used": "true when the shops' titles say used or refurbished (б/у, б/в, вживаний, refurbished, \"хороший стан\"); such goods are a model of their own; false = not said to be used; empty on a category row",
        "product_id": "ID of the matching product card of the BlaBlaPrice catalog when the brand and the model match one, else empty (cards are not created from shop titles)",
        "models": "JSON only: the category's model rows, more prices first; empty when no model has 3 prices",
        "models_count": "JSON only: number of models shown for the category",
        "other_samples": "JSON only: prices of the category not in a shown model (no clear model in the title, or fewer than 3 prices of that model); they are in the category row, not in a model",
        "models_note": "JSON only: why the category has no model rows yet, in lang; null when it has some",
        "name": "JSON model rows only: brand and model as the page shows them",
        "label": "JSON model and unit rows: the model with the used mark, or the service with its unit (\"Maths tutors: prices per hour\"), in lang",
        "kind": "\"goods\" or \"service\" (schema_version 3). Goods are grouped by model, services by price unit: a service has no models. Worked out once per country, not per page: the kind the request reader gave the category's requests (two thirds agreeing), else per-hour prices, else the category's name, else its section of the tree",
        "unit_code": "service rows: the unit of the price, a stable code: hour, lesson, visit, m2, m3, lm (running metre), kg, pack, t, l, or service = the source names no unit (a price for the whole service). Taken from the price's own unit or a unit the seller's title states outright (\"1 lesson\", \"per hour\"), never guessed; on a service category row the code of its first unit; empty for goods",
        "variant": "service rows: the variant every price of the unit names in its title: group, individual, online, or several joined with \"+\"; empty when the titles name none or differ (then see variants)",
        "unit_samples": "service rows: number of distinct prices of the unit (at least 3); on a category row those of its first unit; empty for goods",
        "unit_shops": "service rows: number of distinct sellers of the unit; empty for goods",
        "units": "JSON only: a service category's unit rows, more prices first, never mixed; empty for goods",
        "units_count": "JSON only: number of units shown for the category",
        "units_note": "JSON only: why a service category has no unit row yet, in lang; null otherwise",
        "unit_label": "JSON service rows only: the unit as the page says it, in lang (\"за годину\", \"per lesson\")",
        "variants": "JSON unit rows only: how many prices of the unit name each variant in their titles",
        "variant_label": "JSON unit rows only: the variant in lang"
    },
    "methodology": {
        "source": {
            "term": "Source",
            "text": "Prices on the sites of shops and sellers that the BlaBlaPrice web search found for buyers' requests in Canada, plus the prices in sellers' offers on BlaBlaPrice and in the price lists sellers uploaded. Test accounts are left out."
        },
        "period": {
            "term": "Period",
            "text": "One calendar month: October 2026. A price belongs to the month in which the search found it or the seller sent it. Earlier months are linked below when they have data."
        },
        "filter": {
            "term": "Selection",
            "text": "Only prices in CAD. Search results that do not match the request (a match score below 50 out of 100, or marked \"does not fit\") are dropped. The same price on the same page counts once. When a category has prices in different units, the most common unit is kept (for example per hour), so an hourly rate is not mixed with the price of a whole job."
        },
        "min": {
            "term": "Minimum",
            "text": "A category enters the table when it has at least 5 prices in the month. With fewer it is not shown, because a range drawn from a handful of prices is random. That is why the list of categories changes from month to month."
        },
        "kind": {
            "term": "Goods and services",
            "text": "Goods are grouped by model, because the model sets a product's price: two washing machines of different models cost different amounts even in one category. Services are grouped by unit of volume, because a service has no model and its price depends on how much work is done: an hour, a lesson, a square metre, a visit. The unit comes from the price itself or from the title on the provider's website (\"per hour\", \"1 lesson\"); when neither names one, it is a price for the whole service, and we do not guess a unit. Prices in different units are never mixed: a tutor's hour and a course of lessons, a call-out fee and the whole job differ several times over, so one median would describe none of them. A unit of a service needs 3 prices to enter the table. Whether a category is goods or a service is worked out once per country: from how BlaBlaPrice read the buyers' requests in it, from per-hour prices, from the category's name and from its section of the catalogue."
        },
        "model": {
            "term": "Models",
            "text": "The model is taken from the product title on the shop's site. The title has to name the brand (or a product line only one brand makes: iPhone and iPad for Apple, Galaxy for Samsung, Redmi and Poco for Xiaomi); the model is the name and code right after the brand. Colour, year, screen size, «Original», «New», emoji, region marks (UA, EU, Global) and units are dropped; memory (128GB, 8/256GB) and tyre size are kept, because the price depends on them. Used and refurbished items (used, refurbished, «good condition») are a model of their own. A model is shown once it has 3 prices or more: the median of one or two prices is chance, three already show where the price lies. When a model matches a card of the BlaBlaPrice catalog, the JSON gives its product_id; no cards are created from shop titles."
        },
        "others": {
            "term": "Other prices",
            "text": "A price goes to «other» when the title does not name one model clearly: no known brand («Washing machines, 5 kg»), no model code («Tigar Winter»), only a size («Xiaomi 32»), no memory while other shops give it for the same model («iPhone 14 Pro» next to «iPhone 14 Pro 256GB»), or the model has too few prices in the month so far (3 prices needed). Other prices are in the row of the whole category, not in the models. When a category has no such model, only its range is shown, marked «too few prices by model yet»."
        },
        "pct": {
            "term": "Percentiles",
            "text": "The 25th percentile (lower bound): a quarter of the prices found are lower. The median: half are lower, half are higher. The 75th percentile (upper bound): three quarters are lower. The middle half of the prices lies between the two bounds, so one very cheap or very expensive offer does not move the range. Values between neighbouring prices are interpolated linearly."
        },
        "round": {
            "term": "Rounding",
            "text": "Values are rounded to two significant digits (13,009 becomes 13,000), because this is a market range, not the price of a particular item."
        },
        "cur": {
            "term": "Currency",
            "text": "CAD. Prices in other currencies are neither converted nor counted."
        },
        "upd": {
            "term": "Updates",
            "text": "The table is recomputed every 6 hours. Newest price in it: 20 October 2026. Computed on 31 October 2026."
        },
        "limits": {
            "term": "Limits",
            "text": "These are not all the sellers of the country, only those the search found for requests on BlaBlaPrice, so the set of categories reflects what buyers looked for. Prices are as the seller's site showed them: delivery, installation, personal discounts and haggling are usually not included. One category mixes different models and job sizes. A row may rest on one or two requests (the requests field in the JSON and CSV). The index is not an offer from BlaBlaPrice: we do not sell goods or services ourselves."
        }
    },
    "count": 1,
    "models_count": 0,
    "units_count": 1,
    "kinds": {
        "goods": 0,
        "service": 1
    },
    "note": null,
    "rows": [
        {
            "country": "ca",
            "lang": "en",
            "month": "2026-10",
            "category_slug": "plumbing-work",
            "category_name": "Plumbing work",
            "p25": 170,
            "median": 180,
            "p75": 230,
            "currency": "CAD",
            "samples": 3,
            "updated_at": "2026-10-20T13:18:24Z",
            "unit": "",
            "shops": 3,
            "requests": 1,
            "level": "category",
            "model": null,
            "brand": null,
            "model_key": null,
            "model_samples": null,
            "model_shops": null,
            "used": null,
            "product_id": null,
            "kind": "service",
            "unit_code": "service",
            "variant": null,
            "unit_samples": 3,
            "unit_shops": 3,
            "category_id": 1658,
            "category_url": "https://blablaprice.com/ca/plumbing-work",
            "models": [],
            "models_count": 0,
            "unit_label": "per service",
            "units": [
                {
                    "country": "ca",
                    "lang": "en",
                    "month": "2026-10",
                    "category_slug": "plumbing-work",
                    "category_name": "Plumbing work",
                    "p25": 170,
                    "median": 180,
                    "p75": 230,
                    "currency": "CAD",
                    "samples": 3,
                    "updated_at": "2026-10-20T13:18:24Z",
                    "unit": "service",
                    "shops": 3,
                    "requests": 1,
                    "level": "unit",
                    "model": null,
                    "brand": null,
                    "model_key": null,
                    "model_samples": null,
                    "model_shops": null,
                    "used": null,
                    "product_id": null,
                    "kind": "service",
                    "unit_code": "service",
                    "variant": null,
                    "unit_samples": 3,
                    "unit_shops": 3,
                    "category_id": 1658,
                    "category_url": "https://blablaprice.com/ca/plumbing-work",
                    "unit_label": "per service",
                    "variants": {},
                    "variant_label": null,
                    "label": "Plumbing work: price per service"
                }
            ],
            "units_count": 1,
            "other_samples": 0,
            "models_note": null,
            "units_note": null
        }
    ],
    "category": "plumbing-work",
    "total_count": 1,
    "pagination": {
        "page": 1,
        "per_page": 50,
        "pages": 1,
        "total": 1,
        "of": "units",
        "prev": null,
        "next": null
    },
    "query_parameters": {
        "m": "YYYY-MM, an earlier month",
        "category": "category_slug: that category only, its models or units paged",
        "page": "page number from 1, 50 rows a page (categories, or the category's models or units)"
    }
}