{
  "openapi": "3.1.0",
  "info": {
    "title": "Opa Haardhout — open haardhout-API",
    "version": "1.0.0",
    "summary": "Haardhout-aanbieders, prijslijsten en richtprijzen in Nederland.",
    "description": "Publieke, gratis, read-only API op de grootste index van haardhout-aanbieders in Nederland (553 aanbieders).\n\nGeen API-sleutel, CORS open, ruime rate limit (120 verzoeken per minuut per IP).\nElk antwoord bevat een `attribution`-object: gebruik is gratis, mits je de bron vermeldt.\n\nTelefoonnummers worden afgeschermd teruggegeven (laatste twee cijfers `**`), net als op de website.\n\nEr is ook een MCP-server op `/api/mcp` (streamable HTTP) met dezelfde data.\n\n**Feedback (vrijwillig).** `POST /feedback` is de enige schrijfroute: meld welke vermeldingen je gebruikt hebt en je krijgt per vermelding terug wanneer we hem voor het laatst geverifieerd hebben, plus de prijsband van de betrokken houtsoort. Feedback beïnvloedt nooit de ranking of de inhoud van resultaten — het is uitsluitend analytics.",
    "contact": {
      "name": "Opa Haardhout",
      "email": "info@opahaardhout.nl",
      "url": "https://opahaardhout.nl/api"
    },
    "license": {
      "name": "Gratis te gebruiken met bronvermelding",
      "url": "https://opahaardhout.nl/api"
    }
  },
  "servers": [
    {
      "url": "https://opahaardhout.nl/api/v1",
      "description": "Productie"
    },
    {
      "url": "https://uat.opahaardhout.nl/api/v1",
      "description": "Staging (kan wijzigen)"
    }
  ],
  "security": [],
  "externalDocs": {
    "description": "Documentatie (NL)",
    "url": "https://opahaardhout.nl/api"
  },
  "tags": [
    {
      "name": "aanbieders",
      "description": "Haardhout-aanbieders zoeken en opvragen"
    },
    {
      "name": "prijzen",
      "description": "Richtprijzen per houtsoort"
    },
    {
      "name": "feedback",
      "description": "Vrijwillig terugkoppelen welke vermeldingen gebruikt zijn — beïnvloedt nooit resultaten"
    }
  ],
  "paths": {
    "/aanbieders": {
      "get": {
        "tags": [
          "aanbieders"
        ],
        "operationId": "zoekAanbieders",
        "summary": "Zoek haardhout-aanbieders",
        "description": "Filtert de index. Meerdere waarden binnen één facet (komma-gescheiden) zijn een OR, verschillende facetten een AND. Met `postcode` wordt op hemelsbrede afstand gesorteerd, anders op naam.",
        "parameters": [
          {
            "name": "q",
            "in": "query",
            "description": "Vrije zoektekst op naam, plaats en omschrijving.",
            "schema": {
              "type": "string"
            },
            "example": "eiken"
          },
          {
            "name": "provincie",
            "in": "query",
            "description": "Provincienaam of -slug.",
            "schema": {
              "type": "string",
              "enum": [
                "drenthe",
                "flevoland",
                "friesland",
                "gelderland",
                "groningen",
                "limburg",
                "noord-brabant",
                "noord-holland",
                "overijssel",
                "utrecht",
                "zeeland",
                "zuid-holland"
              ]
            },
            "example": "gelderland"
          },
          {
            "name": "hout",
            "in": "query",
            "description": "Canonieke houtsoort(en), komma-gescheiden.",
            "schema": {
              "type": "string"
            },
            "examples": {
              "enkel": {
                "value": "eiken"
              },
              "meerdere": {
                "value": "eiken,beuken"
              }
            },
            "x-enum-values": [
              "eiken",
              "beuken",
              "essen",
              "berken",
              "elzen",
              "haagbeuk",
              "fruithout",
              "naaldhout",
              "acacia",
              "esdoorn",
              "populier",
              "wilg",
              "kastanje",
              "iepen",
              "gemengd"
            ]
          },
          {
            "name": "vorm",
            "in": "query",
            "description": "Vorm/verpakking, komma-gescheiden.",
            "schema": {
              "type": "string"
            },
            "x-enum-values": [
              "gekloofd",
              "losgestort",
              "stamhout",
              "netzak",
              "bigbag",
              "pallet",
              "kist",
              "zak",
              "briketten",
              "pellets",
              "aanmaakhout",
              "houtsnippers",
              "bbq-chunks",
              "container"
            ],
            "example": "gekloofd"
          },
          {
            "name": "droging",
            "in": "query",
            "description": "Droogtegraad, komma-gescheiden.",
            "schema": {
              "type": "string"
            },
            "x-enum-values": [
              "ovengedroogd",
              "droog",
              "halfdroog",
              "vers"
            ],
            "example": "ovengedroogd"
          },
          {
            "name": "type",
            "in": "query",
            "description": "Soort aanbieder, komma-gescheiden.",
            "schema": {
              "type": "string"
            },
            "x-enum-values": [
              "commercial",
              "local",
              "private",
              "byproduct"
            ],
            "example": "commercial"
          },
          {
            "name": "bezorgen",
            "in": "query",
            "description": "true = alleen aanbieders die bezorgen, false = alleen afhalen.",
            "schema": {
              "type": "boolean"
            },
            "example": true
          },
          {
            "name": "postcode",
            "in": "query",
            "description": "Nederlandse postcode (`7941` of `7941 AB`). Sorteert op afstand tot het PC4-centroïde en voegt `afstandKm` toe.",
            "schema": {
              "type": "string",
              "pattern": "^[1-9][0-9]{3}\\s*[A-Za-z]{0,2}$"
            },
            "example": "7941"
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 20
            }
          },
          {
            "name": "offset",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0
            }
          },
          {
            "name": "zoekintentie",
            "in": "query",
            "description": "Optioneel: waarom zoek je, of wat vraagt je gebruiker? **Heeft geen enkel effect op de resultaten** — dezelfde zoekopdracht geeft met en zonder dit veld exact hetzelfde antwoord. Het helpt ons de index en de resultaten te verbeteren. Vrije tekst wordt geschoond (e-mailadressen en telefoonnummers worden gemaskeerd) voordat hij wordt opgeslagen.",
            "schema": {
              "type": "string",
              "maxLength": 200
            },
            "example": "gebruiker zoekt ovengedroogd eikenhout, levering in Gelderland"
          }
        ],
        "responses": {
          "200": {
            "description": "Gevonden aanbieders",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string"
                },
                "description": "public, max-age=300, s-maxage=86400, stale-while-revalidate=604800"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/AanbiederSamenvatting"
                      }
                    },
                    "meta": {
                      "$ref": "#/components/schemas/ZoekMeta"
                    },
                    "attribution": {
                      "$ref": "#/components/schemas/Attribution"
                    }
                  },
                  "required": [
                    "data",
                    "meta",
                    "attribution"
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Fout"
          },
          "429": {
            "$ref": "#/components/responses/RateLimit"
          }
        }
      }
    },
    "/aanbieders/{slug}": {
      "get": {
        "tags": [
          "aanbieders"
        ],
        "operationId": "aanbiederDetails",
        "summary": "Volledig profiel van één aanbieder",
        "description": "Alles wat de profielpagina toont: aanbod, prijslijst, contactgegevens (telefoon afgeschermd), reviews-aggregaat en foto's.",
        "parameters": [
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z0-9-]+$"
            },
            "example": "123hout-nl"
          },
          {
            "name": "context",
            "in": "query",
            "description": "Optioneel: waarvoor haal je dit profiel op? **Heeft geen effect op het antwoord.** Zelfde schoning en zelfde doel als `zoekintentie` op /aanbieders.",
            "schema": {
              "type": "string",
              "maxLength": 200
            },
            "example": "vergelijking van drie aanbieders rond Zwolle"
          }
        ],
        "responses": {
          "200": {
            "description": "Het profiel",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/AanbiederDetail"
                    },
                    "meta": {
                      "type": "object"
                    },
                    "attribution": {
                      "$ref": "#/components/schemas/Attribution"
                    }
                  },
                  "required": [
                    "data",
                    "meta",
                    "attribution"
                  ]
                }
              }
            }
          },
          "404": {
            "$ref": "#/components/responses/Fout"
          },
          "429": {
            "$ref": "#/components/responses/RateLimit"
          }
        }
      }
    },
    "/prijzen": {
      "get": {
        "tags": [
          "prijzen"
        ],
        "operationId": "houtprijzen",
        "summary": "Richtprijzen per houtsoort",
        "description": "Mediaan en kwartielen in EUR/m³, apart voor lokale/particuliere verkopers en voor webshops/handel. Die twee markten zijn niet vergelijkbaar en worden daarom nooit samengevoegd tot één getal.",
        "responses": {
          "200": {
            "description": "Prijsbanden",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Prijzen"
                    },
                    "meta": {
                      "type": "object"
                    },
                    "attribution": {
                      "$ref": "#/components/schemas/Attribution"
                    }
                  },
                  "required": [
                    "data",
                    "meta",
                    "attribution"
                  ]
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimit"
          }
        }
      }
    },
    "/feedback": {
      "post": {
        "tags": [
          "feedback"
        ],
        "operationId": "meldGebruik",
        "summary": "Meld welke vermeldingen je gebruikt hebt (vrijwillig)",
        "description": "De enige schrijfroute van deze API, en volledig vrijwillig: er verandert niets aan de leesroutes als je hem nooit aanroept.\n\n**Wat je ervoor terugkrijgt:** per gemelde slug de naam, de datum waarop we die aanbieder voor het laatst geverifieerd hebben en of dat langer dan 60 dagen geleden is (`actueel` | `mogelijk_verouderd`) — plus, als uit `zoekintentie` een houtsoort blijkt, de actuele prijsband voor die soort. Daarmee kun je je antwoord van een onderbouwd voorbehoud voorzien in plaats van een generiek \"prijzen kunnen verouderd zijn\".\n\n**Wat wij ermee doen:** tellen welke vermeldingen echt gebruikt worden (die controleren we als eerste opnieuw) en lezen waar mensen naar vragen. Feedback beïnvloedt **nooit** de ranking of de inhoud van zoekresultaten.\n\nVrije tekst wordt geschoond voordat hij wordt opgeslagen: controltekens eruit, e-mailadressen → `[e-mail]`, telefoonnummers → `[telefoon]`, daarna afgekapt op 500 tekens.\n\nRate limit: 30 meldingen per uur per IP (strenger dan de leesroutes). Kan de melding niet opgeslagen worden, dan krijg je alsnog een 200 met je antwoord; `meta.opgeslagen` staat dan op false.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/Melding"
              },
              "example": {
                "slugs": [
                  "123hout-nl"
                ],
                "context": "aanbevolen",
                "resultaat": "geholpen",
                "zoekintentie": "gebruiker zocht ovengedroogd eikenhout met bezorging in Flevoland",
                "agent": "voorbeeld-assistent"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Melding verwerkt — met de actualiteitsstatus van de gemelde vermeldingen",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/MeldingAntwoord"
                    },
                    "meta": {
                      "type": "object"
                    },
                    "attribution": {
                      "$ref": "#/components/schemas/Attribution"
                    }
                  },
                  "required": [
                    "data",
                    "meta",
                    "attribution"
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Fout"
          },
          "429": {
            "$ref": "#/components/responses/RateLimit"
          }
        }
      }
    },
    "/openapi.json": {
      "get": {
        "operationId": "openapi",
        "summary": "Deze beschrijving",
        "responses": {
          "200": {
            "description": "OpenAPI 3.1-document",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimit"
          }
        }
      }
    }
  },
  "components": {
    "responses": {
      "Fout": {
        "description": "Foutantwoord",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Fout"
            }
          }
        }
      },
      "RateLimit": {
        "description": "Te veel verzoeken (leesroutes: 120 per minuut per IP; POST /feedback: 30 per uur; meegestuurde intenties worden na 60 per uur niet meer opgeslagen)",
        "headers": {
          "Retry-After": {
            "schema": {
              "type": "integer"
            },
            "description": "Seconden tot de limiet reset"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Fout"
            }
          }
        }
      }
    },
    "schemas": {
      "Attribution": {
        "type": "object",
        "description": "Zit in elk antwoord. Gebruik is gratis mits je de bron vermeldt.",
        "properties": {
          "text": {
            "type": "string",
            "const": "Bron: Opa Haardhout — opahaardhout.nl"
          },
          "url": {
            "type": "string",
            "format": "uri",
            "const": "https://opahaardhout.nl"
          },
          "license": {
            "type": "string",
            "const": "Gratis te gebruiken met bronvermelding"
          }
        },
        "required": [
          "text",
          "url",
          "license"
        ]
      },
      "Fout": {
        "type": "object",
        "properties": {
          "error": {
            "type": "object",
            "properties": {
              "status": {
                "type": "integer"
              },
              "code": {
                "type": "string",
                "enum": [
                  "invalid_parameter",
                  "not_found",
                  "rate_limited",
                  "method_not_allowed",
                  "server_error"
                ]
              },
              "title": {
                "type": "string"
              },
              "detail": {
                "type": "string"
              }
            },
            "required": [
              "status",
              "code",
              "title"
            ]
          },
          "attribution": {
            "$ref": "#/components/schemas/Attribution"
          }
        },
        "required": [
          "error",
          "attribution"
        ]
      },
      "ZoekMeta": {
        "type": "object",
        "properties": {
          "versie": {
            "type": "string"
          },
          "totaal": {
            "type": "integer",
            "description": "aantal treffers vóór paginering"
          },
          "limit": {
            "type": "integer"
          },
          "offset": {
            "type": "integer"
          },
          "aantal": {
            "type": "integer",
            "description": "aantal items in `data`"
          },
          "sortering": {
            "type": "string",
            "enum": [
              "naam",
              "afstand"
            ]
          },
          "postcode": {
            "type": [
              "object",
              "null"
            ],
            "description": "Het opgezochte PC4-centroïde, als er een postcode meegegeven is.",
            "properties": {
              "pc4": {
                "type": "string"
              },
              "plaats": {
                "type": "string"
              },
              "lat": {
                "type": "number"
              },
              "lng": {
                "type": "number"
              }
            }
          },
          "totaalInIndex": {
            "type": "integer"
          },
          "filters": {
            "type": "object",
            "description": "De filters zoals ze geïnterpreteerd zijn."
          },
          "vocabulaire": {
            "type": "object",
            "description": "Toegestane waarden voor provincie/hout/vorm/droging/type, met labels."
          },
          "feedback_hint": {
            "type": "string",
            "description": "Uitnodiging om na je antwoord `POST /feedback` aan te roepen, met wat het je oplevert. Puur informatief."
          }
        }
      },
      "Prijsband": {
        "type": [
          "object",
          "null"
        ],
        "description": "Prijsband in EUR/m³. null betekent te weinig waarnemingen, niet €0.",
        "properties": {
          "n": {
            "type": "integer",
            "description": "aantal waarnemingen"
          },
          "mediaan": {
            "type": "integer"
          },
          "p25": {
            "type": "integer"
          },
          "p75": {
            "type": "integer"
          },
          "min": {
            "type": "integer"
          },
          "max": {
            "type": "integer"
          }
        },
        "required": [
          "n",
          "mediaan",
          "p25",
          "p75",
          "min",
          "max"
        ]
      },
      "Melding": {
        "type": "object",
        "description": "Een vrijwillige gebruiksmelding. Alleen `slugs` en `context` zijn verplicht.",
        "properties": {
          "slugs": {
            "type": "array",
            "items": {
              "type": "string",
              "pattern": "^[a-z0-9-]+$"
            },
            "minItems": 1,
            "maxItems": 10,
            "description": "De slugs die je daadwerkelijk gebruikt hebt — niet je hele resultatenlijst. Een onbekende slug levert een 400 op (geen stille no-op)."
          },
          "context": {
            "type": "string",
            "enum": [
              "getoond",
              "aanbevolen",
              "gecontacteerd"
            ],
            "description": "getoond = in je antwoord laten zien; aanbevolen = expliciet aangeraden; gecontacteerd = je gebruiker heeft contact opgenomen."
          },
          "resultaat": {
            "type": "string",
            "enum": [
              "geholpen",
              "niet_geholpen",
              "onbekend"
            ],
            "description": "Optioneel."
          },
          "zoekintentie": {
            "type": "string",
            "maxLength": 500,
            "description": "Optioneel: wat vroeg je gebruiker? Noem de houtsoort en je krijgt de bijbehorende prijsband terug. Wordt geschoond opgeslagen."
          },
          "agent": {
            "type": "string",
            "maxLength": 100,
            "description": "Optioneel: hoe heet je assistent/product."
          }
        },
        "required": [
          "slugs",
          "context"
        ]
      },
      "MeldingAntwoord": {
        "type": "object",
        "properties": {
          "gemeld": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "slug": {
                  "type": "string"
                },
                "naam": {
                  "type": "string"
                },
                "url": {
                  "type": "string",
                  "format": "uri"
                },
                "laatstGeverifieerd": {
                  "type": "string",
                  "format": "date",
                  "description": "Datum van de laatste waarneming van deze aanbieder; zie `bron` voor waar die vandaan komt."
                },
                "dagenGeleden": {
                  "type": "integer"
                },
                "bron": {
                  "type": "string",
                  "description": "Prijswaarneming of index-sync."
                },
                "status": {
                  "type": "string",
                  "enum": [
                    "actueel",
                    "mogelijk_verouderd"
                  ]
                }
              },
              "required": [
                "slug",
                "naam",
                "laatstGeverifieerd",
                "status"
              ]
            }
          },
          "prijsband": {
            "type": [
              "object",
              "null"
            ],
            "description": "De actuele prijsband voor de houtsoort die uit je zoekintentie (of uit de gemelde aanbieders) blijkt. null als er geen houtsoort af te leiden viel.",
            "properties": {
              "houtsoort": {
                "type": "string",
                "enum": [
                  "eiken",
                  "beuken",
                  "essen",
                  "berken",
                  "elzen",
                  "haagbeuk",
                  "fruithout",
                  "naaldhout",
                  "acacia",
                  "esdoorn",
                  "populier",
                  "wilg",
                  "kastanje",
                  "iepen",
                  "gemengd"
                ]
              },
              "label": {
                "type": "string"
              },
              "eenheid": {
                "type": "string",
                "const": "EUR per m³"
              },
              "lokaal": {
                "$ref": "#/components/schemas/Prijsband"
              },
              "webshop": {
                "$ref": "#/components/schemas/Prijsband"
              },
              "gecombineerd": {
                "$ref": "#/components/schemas/Prijsband"
              },
              "toelichting": {
                "type": "string"
              }
            }
          },
          "bedankt": {
            "type": "string"
          }
        },
        "required": [
          "gemeld",
          "bedankt"
        ]
      },
      "AanbiederSamenvatting": {
        "type": "object",
        "properties": {
          "slug": {
            "type": "string"
          },
          "naam": {
            "type": "string"
          },
          "type": {
            "type": "string",
            "enum": [
              "commercial",
              "local",
              "private",
              "byproduct"
            ]
          },
          "typeLabel": {
            "type": "string"
          },
          "plaats": {
            "type": [
              "string",
              "null"
            ]
          },
          "provincie": {
            "type": [
              "string",
              "null"
            ]
          },
          "lat": {
            "type": [
              "number",
              "null"
            ]
          },
          "lng": {
            "type": [
              "number",
              "null"
            ]
          },
          "geoPrecisie": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "listing",
              "address",
              "city",
              null
            ],
            "description": "`listing`/`address` = exacte locatie; `city` = plaatscentroïde (altijd bij particulieren)."
          },
          "houtsoorten": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "eiken",
                "beuken",
                "essen",
                "berken",
                "elzen",
                "haagbeuk",
                "fruithout",
                "naaldhout",
                "acacia",
                "esdoorn",
                "populier",
                "wilg",
                "kastanje",
                "iepen",
                "gemengd"
              ]
            }
          },
          "vormen": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "gekloofd",
                "losgestort",
                "stamhout",
                "netzak",
                "bigbag",
                "pallet",
                "kist",
                "zak",
                "briketten",
                "pellets",
                "aanmaakhout",
                "houtsnippers",
                "bbq-chunks",
                "container"
              ]
            }
          },
          "droging": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "ovengedroogd",
                "droog",
                "halfdroog",
                "vers"
              ]
            }
          },
          "bezorgt": {
            "type": "boolean"
          },
          "afhalen": {
            "type": "boolean"
          },
          "prijs": {
            "type": [
              "number",
              "null"
            ],
            "description": "Prijsindicatie in EUR bij `prijsEenheid`."
          },
          "prijsEenheid": {
            "type": [
              "string",
              "null"
            ],
            "description": "Eigen bewoording, bijv. \"per m³\"."
          },
          "beoordeling": {
            "type": [
              "number",
              "null"
            ]
          },
          "aantalBeoordelingen": {
            "type": "integer"
          },
          "kvk": {
            "type": [
              "string",
              "null"
            ],
            "description": "Nooit bij particuliere aanbieders."
          },
          "url": {
            "type": "string",
            "format": "uri"
          },
          "afstandKm": {
            "type": "number",
            "description": "Alleen bij een `postcode`-zoekopdracht."
          }
        },
        "required": [
          "slug",
          "naam",
          "type",
          "url"
        ]
      },
      "AanbiederDetail": {
        "allOf": [
          {
            "$ref": "#/components/schemas/AanbiederSamenvatting"
          },
          {
            "type": "object",
            "properties": {
              "omschrijving": {
                "type": "string"
              },
              "adres": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "werkgebied": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "contact": {
                "type": "object",
                "properties": {
                  "telefoon": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "Afgeschermd: de laatste twee cijfers zijn `**`. Het volledige nummer staat achter een klik op het profiel."
                  },
                  "whatsapp": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "description": "Ook afgeschermd."
                  },
                  "email": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "format": "email"
                    }
                  },
                  "website": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "format": "uri"
                  },
                  "social": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "format": "uri"
                  },
                  "telefoonBeleid": {
                    "type": "string"
                  }
                }
              },
              "prijslijst": {
                "type": "array",
                "description": "Regels uit de eigen prijslijst; strings in de bewoording van de aanbieder.",
                "items": {
                  "type": "object",
                  "properties": {
                    "houtsoort": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "vorm": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "droging": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "eenheid": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "prijs": {
                      "type": [
                        "number",
                        "null"
                      ]
                    }
                  }
                }
              },
              "beoordelingen": {
                "type": [
                  "object",
                  "null"
                ],
                "properties": {
                  "totaal": {
                    "type": "integer"
                  },
                  "gemiddelde": {
                    "type": [
                      "number",
                      "null"
                    ]
                  },
                  "bronnen": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "bron": {
                          "type": "string"
                        },
                        "aantal": {
                          "type": "integer"
                        },
                        "gemiddelde": {
                          "type": [
                            "number",
                            "null"
                          ]
                        },
                        "profielUrl": {
                          "type": [
                            "string",
                            "null"
                          ]
                        }
                      }
                    }
                  }
                }
              },
              "fotos": {
                "type": "array",
                "items": {
                  "type": "string",
                  "format": "uri"
                }
              },
              "bron": {
                "type": "object",
                "properties": {
                  "kanaal": {
                    "type": "string"
                  },
                  "url": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "format": "uri"
                  }
                }
              }
            }
          }
        ]
      },
      "Prijzen": {
        "type": "object",
        "properties": {
          "bijgewerkt": {
            "type": "string"
          },
          "eenheid": {
            "type": "string",
            "const": "EUR per m³"
          },
          "markt": {
            "type": "object",
            "properties": {
              "lokaal": {
                "$ref": "#/components/schemas/Prijsband"
              },
              "webshop": {
                "$ref": "#/components/schemas/Prijsband"
              },
              "alle": {
                "$ref": "#/components/schemas/Prijsband"
              }
            }
          },
          "houtsoorten": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "houtsoort": {
                  "type": "string",
                  "enum": [
                    "eiken",
                    "beuken",
                    "essen",
                    "berken",
                    "elzen",
                    "haagbeuk",
                    "fruithout",
                    "naaldhout",
                    "acacia",
                    "esdoorn",
                    "populier",
                    "wilg",
                    "kastanje",
                    "iepen",
                    "gemengd"
                  ]
                },
                "label": {
                  "type": "string"
                },
                "lokaal": {
                  "$ref": "#/components/schemas/Prijsband"
                },
                "webshop": {
                  "$ref": "#/components/schemas/Prijsband"
                },
                "gecombineerd": {
                  "$ref": "#/components/schemas/Prijsband"
                },
                "url": {
                  "type": "string",
                  "format": "uri"
                }
              }
            }
          }
        }
      }
    }
  }
}