{
  "openapi": "3.1.0",
  "info": {
    "title": "landfeed — Polish land parcel API",
    "version": "v1-draft-2026-10-13",
    "summary": "Any Polish parcel from whatever a human typed, a sourced record and a verdict, in one call.",
    "description": "Contract for week 1 (docs/landfeed/README.md, step 1; deltas from the Cenogram teardown,\ncontext/research/cenogram-teardown-2026-10-12.md sections 8 and 9). The service serves this\nfile at GET /v1/openapi.json; paths, methods, parameters and the envelope must match.\n\nInvariants every endpoint keeps:\n- One call answers. Every read endpoint accepts exactly one of `q` (free text as typed),\n  `id` (EGiB id_dzialki, slash or dash form) or `point` (WGS84 \"lat,lng\", or `lat` and `lng`),\n  resolves internally, and on an ambiguous input returns HTTP 200, status `ambiguous` and\n  `candidates`, never an error and never a silent pick.\n- Every layer answer carries `source`, `as_of`, a plain-language `note` and four-state\n  `coverage` (covered | covered_no_data | not_covered | not_computed). Unknown is\n  `not_covered` with value null.\n- Cost is declared per operation (`x-request-cost`, requests) and reported per response in\n  `billing {cost, charged, refunded, rule}` and the X-Request-Cost / X-Credits-Charged /\n  X-Credits-Refunded headers. Invalid input is 400 and free. 4xx, 5xx and not_covered are\n  refunded. Informative negatives (covered_no_data) and candidate lists are charged.\n- GET by id returns an ETag; If-None-Match that matches returns 304, free.\n- Authenticated responses are `Cache-Control: private, max-age=0, must-revalidate`; never\n  `public`.\n- Planning is one request: layer `planning` (plan ogólny, MPZP, WZ, gmina status), and it is\n  part of `check`. Plan status is draft | adopted | in_force | none with effective_from.\n- Never served: KW numbers, owner or holder data, investor names, address-level transaction\n  prices.\n- Plan data: Rejestr Urbanistyczny first; Dzialkopedia's POG sweep as attributed fallback\n  (`source.fallback: true`).\nBody of every response: contracts/envelope.json (Envelope). Auth: static key header in dev.\n"
  },
  "servers": [
    {
      "url": "http://localhost:8410",
      "description": "blackbull dev"
    }
  ],
  "security": [
    {
      "ApiKey": []
    }
  ],
  "paths": {
    "/v1/resolve": {
      "get": {
        "operationId": "resolve",
        "summary": "Turn what a human typed (or an id, or a point) into parcel candidates.",
        "description": "Always returns `candidates` (possibly one) and `corpus_coverage`. status `ok` when exactly\none candidate is confident (>= 0.85 and at least 0.15 above the next); `ambiguous`\notherwise, with `needs_obreb` true when the number exists in several obręby of the gmina.\nLocality and gmina names match fuzzily (diacritics, one or two typos: \"Lesnowola\" finds\nLesznowola) with confidence lowered and the assumption stated in `query.resolved.note`\nand `match_reason`. Ids are accepted in slash or dash form. A candidate in a partition\nwe have not loaded comes back with `held: false` and corpus_coverage says so.\n",
        "x-request-cost": 1,
        "parameters": [
          {
            "$ref": "#/components/parameters/q"
          },
          {
            "$ref": "#/components/parameters/id"
          },
          {
            "$ref": "#/components/parameters/point"
          },
          {
            "$ref": "#/components/parameters/lat"
          },
          {
            "$ref": "#/components/parameters/lng"
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 20,
              "default": 5
            }
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/ResolveOk"
          },
          "400": {
            "$ref": "#/components/responses/InvalidInput"
          },
          "401": {
            "$ref": "#/components/responses/Failure"
          },
          "404": {
            "$ref": "#/components/responses/Failure"
          }
        }
      }
    },
    "/v1/parcel": {
      "get": {
        "operationId": "parcel",
        "summary": "The full sourced record of one parcel.",
        "x-request-cost": 1,
        "parameters": [
          {
            "$ref": "#/components/parameters/q"
          },
          {
            "$ref": "#/components/parameters/id"
          },
          {
            "$ref": "#/components/parameters/point"
          },
          {
            "$ref": "#/components/parameters/lat"
          },
          {
            "$ref": "#/components/parameters/lng"
          },
          {
            "$ref": "#/components/parameters/layers"
          },
          {
            "$ref": "#/components/parameters/geometry"
          },
          {
            "$ref": "#/components/parameters/IfNoneMatch"
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/ParcelOk"
          },
          "304": {
            "$ref": "#/components/responses/NotModified"
          },
          "400": {
            "$ref": "#/components/responses/InvalidInput"
          },
          "401": {
            "$ref": "#/components/responses/Failure"
          },
          "404": {
            "$ref": "#/components/responses/Failure"
          }
        }
      }
    },
    "/v1/parcel/batch": {
      "post": {
        "operationId": "parcel_batch",
        "summary": "Up to 1,000 parcels in one request; each item is q | id | point.",
        "x-request-cost": 1,
        "x-request-cost-per": "item",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "items"
                ],
                "additionalProperties": false,
                "properties": {
                  "items": {
                    "type": "array",
                    "minItems": 1,
                    "maxItems": 1000,
                    "items": {
                      "$ref": "./envelope.json#/$defs/QueryInput"
                    }
                  },
                  "layers": {
                    "type": "array",
                    "items": {
                      "$ref": "./envelope.json#/$defs/LayerKey"
                    }
                  },
                  "geometry": {
                    "type": "string",
                    "enum": [
                      "none",
                      "centroid",
                      "full"
                    ],
                    "default": "centroid"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "result is an array of per-item envelopes (each with its own status and candidates).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "./envelope.json"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/InvalidInput"
          },
          "401": {
            "$ref": "#/components/responses/Failure"
          }
        }
      }
    },
    "/v1/search": {
      "get": {
        "operationId": "search",
        "summary": "Parcels by address or text (q), around a parcel (id) or point, or in a bbox.",
        "description": "q: address via PRG (\"Marcinowice 221\", \"Warszawa, Puławska 1\") or parcel text; returns the\nparcels at that address. id or point: parcels within radius_m of it (0 = that parcel and its\nneighbours sharing a boundary). bbox: parcels intersecting it (max 4 km²). Polygon search\nis POST /v1/search with a GeoJSON polygon (max 4 km²).\n",
        "x-request-cost": 1,
        "parameters": [
          {
            "$ref": "#/components/parameters/q"
          },
          {
            "$ref": "#/components/parameters/id"
          },
          {
            "$ref": "#/components/parameters/point"
          },
          {
            "$ref": "#/components/parameters/lat"
          },
          {
            "$ref": "#/components/parameters/lng"
          },
          {
            "name": "bbox",
            "in": "query",
            "description": "min_lon,min_lat,max_lon,max_lat (WGS84). Replaces q|id|point.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "radius_m",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "maximum": 2000,
              "default": 0
            }
          },
          {
            "$ref": "#/components/parameters/limit"
          },
          {
            "$ref": "#/components/parameters/cursor"
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/SearchOk"
          },
          "400": {
            "$ref": "#/components/responses/InvalidInput"
          },
          "401": {
            "$ref": "#/components/responses/Failure"
          },
          "404": {
            "$ref": "#/components/responses/Failure"
          }
        }
      },
      "post": {
        "operationId": "search_polygon",
        "summary": "Parcels intersecting a GeoJSON polygon (max 4 km²).",
        "x-request-cost": 1,
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "polygon"
                ],
                "properties": {
                  "polygon": {
                    "type": "object",
                    "description": "GeoJSON Polygon or MultiPolygon",
                    "WGS84": null
                  },
                  "limit": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 1000,
                    "default": 100
                  },
                  "cursor": {
                    "type": [
                      "string",
                      "null"
                    ]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/SearchOk"
          },
          "400": {
            "$ref": "#/components/responses/InvalidInput"
          },
          "401": {
            "$ref": "#/components/responses/Failure"
          }
        }
      }
    },
    "/v1/layer/{layer}": {
      "get": {
        "operationId": "layer",
        "summary": "One layer's answer for one parcel.",
        "x-request-cost": 1,
        "parameters": [
          {
            "name": "layer",
            "in": "path",
            "required": true,
            "schema": {
              "$ref": "./envelope.json#/$defs/LayerKey"
            }
          },
          {
            "$ref": "#/components/parameters/IfNoneMatch"
          },
          {
            "$ref": "#/components/parameters/q"
          },
          {
            "$ref": "#/components/parameters/id"
          },
          {
            "$ref": "#/components/parameters/point"
          },
          {
            "$ref": "#/components/parameters/lat"
          },
          {
            "$ref": "#/components/parameters/lng"
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/LayerOk"
          },
          "304": {
            "$ref": "#/components/responses/NotModified"
          },
          "400": {
            "$ref": "#/components/responses/InvalidInput"
          },
          "401": {
            "$ref": "#/components/responses/Failure"
          },
          "404": {
            "$ref": "#/components/responses/Failure"
          }
        }
      }
    },
    "/v1/check": {
      "get": {
        "operationId": "check",
        "summary": "Can you build here? A deterministic verdict with named checks, sources, and the record embedded.",
        "description": "Not legal advice: booleans with sources, the same way a flood flag is. A check whose input\nthe state does not publish machine-readably is `unknown`, never guessed. The full parcel\nrecord is embedded in result.record so one call answers follow-ups. Planning is part of\nthe check: pog_zone (with plan status and effective_from), wz_possible, mpzp_status.\n",
        "x-request-cost": 1,
        "parameters": [
          {
            "$ref": "#/components/parameters/IfNoneMatch"
          },
          {
            "$ref": "#/components/parameters/q"
          },
          {
            "$ref": "#/components/parameters/id"
          },
          {
            "$ref": "#/components/parameters/point"
          },
          {
            "$ref": "#/components/parameters/lat"
          },
          {
            "$ref": "#/components/parameters/lng"
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/CheckOk"
          },
          "304": {
            "$ref": "#/components/responses/NotModified"
          },
          "400": {
            "$ref": "#/components/responses/InvalidInput"
          },
          "401": {
            "$ref": "#/components/responses/Failure"
          },
          "404": {
            "$ref": "#/components/responses/Failure"
          }
        }
      }
    },
    "/v1/events": {
      "get": {
        "operationId": "events",
        "summary": "What changed for a parcel (or around a point, or in the gmina q names), newest first.",
        "x-request-cost": 1,
        "parameters": [
          {
            "$ref": "#/components/parameters/q"
          },
          {
            "$ref": "#/components/parameters/id"
          },
          {
            "$ref": "#/components/parameters/point"
          },
          {
            "$ref": "#/components/parameters/lat"
          },
          {
            "$ref": "#/components/parameters/lng"
          },
          {
            "name": "since",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "name": "types",
            "in": "query",
            "description": "Comma-separated event names (parcel_events.event).",
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/limit"
          },
          {
            "$ref": "#/components/parameters/cursor"
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/EventsOk"
          },
          "400": {
            "$ref": "#/components/responses/InvalidInput"
          },
          "401": {
            "$ref": "#/components/responses/Failure"
          },
          "404": {
            "$ref": "#/components/responses/Failure"
          }
        }
      }
    },
    "/v1/sources": {
      "get": {
        "operationId": "sources",
        "summary": "Every source the API serves, with licence, attribution, as_of, freshness and coverage.",
        "description": "No input lists all sources. With q | id | point: the sources that answer for that parcel,\neach with the coverage state it has there. Free, so an agent can always check freshness.\n",
        "x-request-cost": 0,
        "parameters": [
          {
            "$ref": "#/components/parameters/q"
          },
          {
            "$ref": "#/components/parameters/id"
          },
          {
            "$ref": "#/components/parameters/point"
          },
          {
            "$ref": "#/components/parameters/lat"
          },
          {
            "$ref": "#/components/parameters/lng"
          },
          {
            "name": "layer",
            "in": "query",
            "schema": {
              "$ref": "./envelope.json#/$defs/LayerKey"
            }
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/SourcesOk"
          },
          "400": {
            "$ref": "#/components/responses/InvalidInput"
          },
          "401": {
            "$ref": "#/components/responses/Failure"
          }
        }
      }
    },
    "/v1/gminy/{teryt}/planning": {
      "get": {
        "operationId": "gmina_planning",
        "summary": "A gmina's planning status - plan ogólny, MPZP coverage, the WZ regime today.",
        "x-request-cost": 1,
        "parameters": [
          {
            "name": "teryt",
            "in": "path",
            "required": true,
            "description": "7-char TERYT gmina code (e.g. 1465011). For a name, a parcel or a point use /v1/gminy/planning.",
            "schema": {
              "type": "string",
              "pattern": "^[0-9]{7}$"
            }
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/PlanningOk"
          },
          "401": {
            "$ref": "#/components/responses/Failure"
          },
          "404": {
            "$ref": "#/components/responses/Failure"
          }
        }
      }
    },
    "/v1/gminy/planning": {
      "get": {
        "operationId": "gmina_planning_lookup",
        "summary": "Same as /v1/gminy/{teryt}/planning, the gmina resolved from q (a gmina name or any parcel text), id or point.",
        "x-request-cost": 1,
        "parameters": [
          {
            "$ref": "#/components/parameters/q"
          },
          {
            "$ref": "#/components/parameters/id"
          },
          {
            "$ref": "#/components/parameters/point"
          },
          {
            "$ref": "#/components/parameters/lat"
          },
          {
            "$ref": "#/components/parameters/lng"
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/PlanningOk"
          },
          "400": {
            "$ref": "#/components/responses/InvalidInput"
          },
          "401": {
            "$ref": "#/components/responses/Failure"
          },
          "404": {
            "$ref": "#/components/responses/Failure"
          }
        }
      }
    },
    "/v1/openapi.json": {
      "get": {
        "operationId": "openapi",
        "summary": "This spec, as served.",
        "x-request-cost": 0,
        "security": [],
        "responses": {
          "200": {
            "description": "OpenAPI 3.1 document",
            "content": {
              "application/json": {}
            }
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "ApiKey": {
        "type": "apiKey",
        "in": "header",
        "name": "X-Api-Key",
        "description": "Static dev key (env GEOFEED_API_KEY). OAuth and per-key quotas arrive at release."
      }
    },
    "parameters": {
      "q": {
        "name": "q",
        "in": "query",
        "description": "Free text as a human typed it (parcel, address, gmina). Exactly one of q, id, point.",
        "schema": {
          "type": "string",
          "minLength": 1,
          "maxLength": 300
        }
      },
      "id": {
        "name": "id",
        "in": "query",
        "description": "EGiB id_dzialki, e.g. 146501_1.0101.12/3. Exactly one of q, id, point.",
        "schema": {
          "$ref": "./envelope.json#/$defs/ParcelId"
        }
      },
      "point": {
        "name": "point",
        "in": "query",
        "description": "WGS84 \"lat,lng\", e.g. 52.2297,21.0122. Exactly one of q, id, point (or lat and lng).",
        "schema": {
          "type": "string"
        }
      },
      "lat": {
        "name": "lat",
        "in": "query",
        "description": "WGS84 latitude; with lng, the same as point.",
        "schema": {
          "type": "number",
          "minimum": 49,
          "maximum": 55
        }
      },
      "lng": {
        "name": "lng",
        "in": "query",
        "description": "WGS84 longitude; with lat, the same as point.",
        "schema": {
          "type": "number",
          "minimum": 14,
          "maximum": 24.5
        }
      },
      "IfNoneMatch": {
        "name": "If-None-Match",
        "in": "header",
        "description": "ETag from an earlier GET by id. A match returns 304, free.",
        "schema": {
          "type": "string"
        }
      },
      "layers": {
        "name": "layers",
        "in": "query",
        "description": "Comma-separated LayerKey list; default all v1 layers.",
        "schema": {
          "type": "string"
        }
      },
      "geometry": {
        "name": "geometry",
        "in": "query",
        "schema": {
          "type": "string",
          "enum": [
            "none",
            "centroid",
            "full"
          ],
          "default": "centroid"
        }
      },
      "limit": {
        "name": "limit",
        "in": "query",
        "schema": {
          "type": "integer",
          "minimum": 1,
          "maximum": 1000,
          "default": 100
        }
      },
      "cursor": {
        "name": "cursor",
        "in": "query",
        "schema": {
          "type": "string"
        }
      }
    },
    "headers": {
      "CacheControl": {
        "description": "Always 'private, max-age=0, must-revalidate' on authenticated responses; never public.",
        "schema": {
          "type": "string"
        }
      },
      "ETag": {
        "description": "On GET by id (parcel, check, layer). Strong validator from the record hash and layer versions. Send it back as If-None-Match.",
        "schema": {
          "type": "string"
        }
      },
      "XRequestCost": {
        "description": "The operation's x-request-cost.",
        "schema": {
          "type": "integer"
        }
      },
      "XCreditsCharged": {
        "description": "Same as billing.charged.",
        "schema": {
          "type": "integer"
        }
      },
      "XCreditsRefunded": {
        "description": "Same as billing.refunded.",
        "schema": {
          "type": "integer"
        }
      }
    },
    "responses": {
      "NotModified": {
        "description": "If-None-Match matched the current ETag. No body. Free (billing rule free_not_modified).",
        "headers": {
          "ETag": {
            "$ref": "#/components/headers/ETag"
          },
          "Cache-Control": {
            "$ref": "#/components/headers/CacheControl"
          }
        }
      },
      "InvalidInput": {
        "description": "400 and free. Envelope with status error, error.code invalid_input, error.hint, error.example_id, billing {charged 0, rule free_invalid_input}.",
        "headers": {
          "Cache-Control": {
            "$ref": "#/components/headers/CacheControl"
          },
          "X-Request-Cost": {
            "$ref": "#/components/headers/XRequestCost"
          },
          "X-Credits-Charged": {
            "$ref": "#/components/headers/XCreditsCharged"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "./envelope.json"
            }
          }
        }
      },
      "Failure": {
        "description": "Envelope with status not_found or error, result null, error set (hint, docs, example_id where the input was a parcel; signup_url on 401). Refunded, or free on 401.",
        "headers": {
          "Cache-Control": {
            "$ref": "#/components/headers/CacheControl"
          },
          "ETag": {
            "$ref": "#/components/headers/ETag"
          },
          "X-Request-Cost": {
            "$ref": "#/components/headers/XRequestCost"
          },
          "X-Credits-Charged": {
            "$ref": "#/components/headers/XCreditsCharged"
          },
          "X-Credits-Refunded": {
            "$ref": "#/components/headers/XCreditsRefunded"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "./envelope.json"
            }
          }
        }
      },
      "ResolveOk": {
        "description": "Envelope; result is the top candidate or null; candidates always present.",
        "headers": {
          "Cache-Control": {
            "$ref": "#/components/headers/CacheControl"
          },
          "ETag": {
            "$ref": "#/components/headers/ETag"
          },
          "X-Request-Cost": {
            "$ref": "#/components/headers/XRequestCost"
          },
          "X-Credits-Charged": {
            "$ref": "#/components/headers/XCreditsCharged"
          },
          "X-Credits-Refunded": {
            "$ref": "#/components/headers/XCreditsRefunded"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "allOf": [
                {
                  "$ref": "./envelope.json"
                },
                {
                  "properties": {
                    "result": {
                      "oneOf": [
                        {
                          "type": "null"
                        },
                        {
                          "$ref": "./envelope.json#/$defs/Candidate"
                        }
                      ]
                    }
                  }
                }
              ]
            }
          }
        }
      },
      "ParcelOk": {
        "description": "Envelope; result is a ParcelRecord (null when ambiguous or not_covered).",
        "headers": {
          "Cache-Control": {
            "$ref": "#/components/headers/CacheControl"
          },
          "ETag": {
            "$ref": "#/components/headers/ETag"
          },
          "X-Request-Cost": {
            "$ref": "#/components/headers/XRequestCost"
          },
          "X-Credits-Charged": {
            "$ref": "#/components/headers/XCreditsCharged"
          },
          "X-Credits-Refunded": {
            "$ref": "#/components/headers/XCreditsRefunded"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "allOf": [
                {
                  "$ref": "./envelope.json"
                },
                {
                  "properties": {
                    "result": {
                      "oneOf": [
                        {
                          "type": "null"
                        },
                        {
                          "$ref": "#/components/schemas/ParcelRecord"
                        }
                      ]
                    }
                  }
                }
              ]
            }
          }
        }
      },
      "LayerOk": {
        "description": "Envelope; result is one LayerAnswer plus the parcel id.",
        "headers": {
          "Cache-Control": {
            "$ref": "#/components/headers/CacheControl"
          },
          "ETag": {
            "$ref": "#/components/headers/ETag"
          },
          "X-Request-Cost": {
            "$ref": "#/components/headers/XRequestCost"
          },
          "X-Credits-Charged": {
            "$ref": "#/components/headers/XCreditsCharged"
          },
          "X-Credits-Refunded": {
            "$ref": "#/components/headers/XCreditsRefunded"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "allOf": [
                {
                  "$ref": "./envelope.json"
                },
                {
                  "properties": {
                    "result": {
                      "oneOf": [
                        {
                          "type": "null"
                        },
                        {
                          "type": "object",
                          "required": [
                            "id",
                            "answer"
                          ],
                          "properties": {
                            "id": {
                              "type": "string"
                            },
                            "answer": {
                              "$ref": "./envelope.json#/$defs/LayerAnswer"
                            }
                          }
                        }
                      ]
                    }
                  }
                }
              ]
            }
          }
        }
      },
      "CheckOk": {
        "description": "Envelope; result is a CheckResult with the record embedded.",
        "headers": {
          "Cache-Control": {
            "$ref": "#/components/headers/CacheControl"
          },
          "ETag": {
            "$ref": "#/components/headers/ETag"
          },
          "X-Request-Cost": {
            "$ref": "#/components/headers/XRequestCost"
          },
          "X-Credits-Charged": {
            "$ref": "#/components/headers/XCreditsCharged"
          },
          "X-Credits-Refunded": {
            "$ref": "#/components/headers/XCreditsRefunded"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "allOf": [
                {
                  "$ref": "./envelope.json"
                },
                {
                  "properties": {
                    "result": {
                      "oneOf": [
                        {
                          "type": "null"
                        },
                        {
                          "$ref": "#/components/schemas/CheckResult"
                        }
                      ]
                    }
                  }
                }
              ]
            }
          }
        }
      },
      "SearchOk": {
        "description": "Envelope; result is an array of ParcelSummary; page set.",
        "headers": {
          "Cache-Control": {
            "$ref": "#/components/headers/CacheControl"
          },
          "ETag": {
            "$ref": "#/components/headers/ETag"
          },
          "X-Request-Cost": {
            "$ref": "#/components/headers/XRequestCost"
          },
          "X-Credits-Charged": {
            "$ref": "#/components/headers/XCreditsCharged"
          },
          "X-Credits-Refunded": {
            "$ref": "#/components/headers/XCreditsRefunded"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "allOf": [
                {
                  "$ref": "./envelope.json"
                },
                {
                  "properties": {
                    "result": {
                      "oneOf": [
                        {
                          "type": "null"
                        },
                        {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/ParcelSummary"
                          }
                        }
                      ]
                    }
                  }
                }
              ]
            }
          }
        }
      },
      "EventsOk": {
        "description": "Envelope; result is an array of Event; page set.",
        "headers": {
          "Cache-Control": {
            "$ref": "#/components/headers/CacheControl"
          },
          "ETag": {
            "$ref": "#/components/headers/ETag"
          },
          "X-Request-Cost": {
            "$ref": "#/components/headers/XRequestCost"
          },
          "X-Credits-Charged": {
            "$ref": "#/components/headers/XCreditsCharged"
          },
          "X-Credits-Refunded": {
            "$ref": "#/components/headers/XCreditsRefunded"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "allOf": [
                {
                  "$ref": "./envelope.json"
                },
                {
                  "properties": {
                    "result": {
                      "oneOf": [
                        {
                          "type": "null"
                        },
                        {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/Event"
                          }
                        }
                      ]
                    }
                  }
                }
              ]
            }
          }
        }
      },
      "SourcesOk": {
        "description": "Envelope; result is an array of Source.",
        "headers": {
          "Cache-Control": {
            "$ref": "#/components/headers/CacheControl"
          },
          "ETag": {
            "$ref": "#/components/headers/ETag"
          },
          "X-Request-Cost": {
            "$ref": "#/components/headers/XRequestCost"
          },
          "X-Credits-Charged": {
            "$ref": "#/components/headers/XCreditsCharged"
          },
          "X-Credits-Refunded": {
            "$ref": "#/components/headers/XCreditsRefunded"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "allOf": [
                {
                  "$ref": "./envelope.json"
                },
                {
                  "properties": {
                    "result": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Source"
                      }
                    }
                  }
                }
              ]
            }
          }
        }
      },
      "PlanningOk": {
        "description": "Envelope; result is GminaPlanning.",
        "headers": {
          "Cache-Control": {
            "$ref": "#/components/headers/CacheControl"
          },
          "ETag": {
            "$ref": "#/components/headers/ETag"
          },
          "X-Request-Cost": {
            "$ref": "#/components/headers/XRequestCost"
          },
          "X-Credits-Charged": {
            "$ref": "#/components/headers/XCreditsCharged"
          },
          "X-Credits-Refunded": {
            "$ref": "#/components/headers/XCreditsRefunded"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "allOf": [
                {
                  "$ref": "./envelope.json"
                },
                {
                  "properties": {
                    "result": {
                      "oneOf": [
                        {
                          "type": "null"
                        },
                        {
                          "$ref": "#/components/schemas/GminaPlanning"
                        }
                      ]
                    }
                  }
                }
              ]
            }
          }
        }
      }
    },
    "schemas": {
      "ParcelSummary": {
        "type": "object",
        "required": [
          "id",
          "gmina_teryt",
          "gmina_name",
          "obreb_name",
          "number",
          "centroid"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "voivodeship": {
            "type": "string"
          },
          "gmina_teryt": {
            "type": "string"
          },
          "gmina_name": {
            "type": "string"
          },
          "powiat_name": {
            "type": "string"
          },
          "obreb_id": {
            "type": "string"
          },
          "obreb_name": {
            "type": [
              "string",
              "null"
            ]
          },
          "number": {
            "type": "string"
          },
          "area_official_m2": {
            "type": [
              "number",
              "null"
            ]
          },
          "centroid": {
            "$ref": "./envelope.json#/$defs/LonLat"
          },
          "distance_m": {
            "type": [
              "number",
              "null"
            ]
          },
          "address": {
            "type": [
              "string",
              "null"
            ],
            "description": "PRG address when the search was by address"
          }
        }
      },
      "ParcelRecord": {
        "type": "object",
        "required": [
          "id",
          "admin",
          "area",
          "layers",
          "record_hash"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "admin": {
            "type": "object",
            "required": [
              "voivodeship",
              "gmina_teryt",
              "gmina_name",
              "obreb_id",
              "number"
            ],
            "properties": {
              "voivodeship": {
                "type": "string"
              },
              "voivodeship_name": {
                "type": "string"
              },
              "powiat_name": {
                "type": "string"
              },
              "gmina_teryt": {
                "type": "string"
              },
              "gmina_name": {
                "type": "string"
              },
              "gmina_type": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "obreb_id": {
                "type": "string"
              },
              "obreb_name": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "number": {
                "type": "string"
              }
            }
          },
          "area": {
            "type": "object",
            "required": [
              "official_m2",
              "geometry_m2",
              "source"
            ],
            "properties": {
              "official_m2": {
                "type": [
                  "number",
                  "null"
                ],
                "description": "EGiB declared area in m² (never hectares)"
              },
              "geometry_m2": {
                "type": "number"
              },
              "source": {
                "$ref": "./envelope.json#/$defs/SourceRef"
              }
            }
          },
          "centroid": {
            "$ref": "./envelope.json#/$defs/LonLat"
          },
          "geometry": {
            "type": [
              "object",
              "null"
            ],
            "description": "GeoJSON MultiPolygon WGS84 when geometry=full"
          },
          "layers": {
            "type": "object",
            "description": "One LayerAnswer per requested layer; value schemas below by layer key.",
            "additionalProperties": {
              "$ref": "./envelope.json#/$defs/LayerAnswer"
            }
          },
          "record_hash": {
            "type": [
              "string",
              "null"
            ]
          },
          "record_as_of": {
            "type": [
              "string",
              "null"
            ],
            "format": "date"
          }
        }
      },
      "PlanningValue": {
        "description": "One-request planning answer for a parcel: the plan ogólny, MPZP and WZ answers (each a full LayerAnswer with its own coverage, source and note) and the gmina planning status. Never says \"no plan\" without naming which plan and which source.",
        "type": "object",
        "required": [
          "pog",
          "mpzp",
          "wz",
          "gmina"
        ],
        "properties": {
          "pog": {
            "$ref": "./envelope.json#/$defs/LayerAnswer"
          },
          "mpzp": {
            "$ref": "./envelope.json#/$defs/LayerAnswer"
          },
          "wz": {
            "$ref": "./envelope.json#/$defs/LayerAnswer"
          },
          "gmina": {
            "$ref": "#/components/schemas/GminaPlanning"
          }
        }
      },
      "PogValue": {
        "description": "Plan ogólny. Drafts are shown and labelled. covered_no_data = the source covers the gmina and records no plan ogólny for it: {status: none, zone_symbol: null, zones: []}.",
        "type": "object",
        "required": [
          "status",
          "zone_symbol",
          "zones",
          "effective_from"
        ],
        "properties": {
          "status": {
            "$ref": "./envelope.json#/$defs/PlanStatus"
          },
          "effective_from": {
            "type": [
              "string",
              "null"
            ],
            "format": "date",
            "description": "Date the plan takes or took effect; null for draft and none."
          },
          "zone_symbol": {
            "type": [
              "string",
              "null"
            ],
            "description": "Dominant zone (largest share), e.g. SW, SJ, SN, SR, SI, SH, SU, SK, SC, SG, SO, SP"
          },
          "zone_name": {
            "type": [
              "string",
              "null"
            ]
          },
          "zones": {
            "type": "array",
            "items": {
              "type": "object",
              "required": [
                "symbol",
                "share_pct"
              ],
              "properties": {
                "symbol": {
                  "type": "string"
                },
                "name": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "share_pct": {
                  "type": "number"
                },
                "parameters": {
                  "type": "object",
                  "properties": {
                    "max_height_m": {
                      "type": [
                        "number",
                        "null"
                      ]
                    },
                    "max_coverage_pct": {
                      "type": [
                        "number",
                        "null"
                      ]
                    },
                    "min_biologically_active_pct": {
                      "type": [
                        "number",
                        "null"
                      ]
                    },
                    "max_intensity": {
                      "type": [
                        "number",
                        "null"
                      ]
                    },
                    "min_new_plot_area_m2": {
                      "type": [
                        "number",
                        "null"
                      ]
                    }
                  }
                }
              }
            }
          },
          "in_ouz": {
            "type": [
              "boolean",
              "null"
            ],
            "description": "inside an obszar uzupełnienia zabudowy"
          },
          "plan_id": {
            "type": [
              "string",
              "null"
            ]
          },
          "adopted_on": {
            "type": [
              "string",
              "null"
            ],
            "format": "date"
          },
          "resolution_url": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "WzValue": {
        "description": "Derived (ours): can a WZ decision be issued for this parcel today. basis cites the statute.",
        "type": "object",
        "required": [
          "possible"
        ],
        "properties": {
          "possible": {
            "type": [
              "boolean",
              "null"
            ]
          },
          "reason": {
            "type": "string"
          }
        }
      },
      "MpzpValue": {
        "description": "covered_no_data = the source covers the gmina and no MPZP covers the parcel: {status: none, symbol: null, plans: [], effective_from: null}. A plan in preparation is status draft.",
        "type": "object",
        "required": [
          "status",
          "symbol",
          "plans",
          "effective_from"
        ],
        "properties": {
          "status": {
            "$ref": "./envelope.json#/$defs/PlanStatus"
          },
          "effective_from": {
            "type": [
              "string",
              "null"
            ],
            "format": "date"
          },
          "symbol": {
            "type": [
              "string",
              "null"
            ],
            "description": "KIMPZP symbol where published; null with note otherwise"
          },
          "share_pct": {
            "type": [
              "number",
              "null"
            ]
          },
          "plans": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "plan_id": {
                  "type": "string"
                },
                "name": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "adopted_on": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "format": "date"
                },
                "resolution_url": {
                  "type": [
                    "string",
                    "null"
                  ]
                }
              }
            }
          }
        }
      },
      "FloodValue": {
        "description": "covered_no_data = mapped area, parcel outside all zones: {q10: false, q100: false, q500: false}.",
        "type": "object",
        "required": [
          "q10",
          "q100",
          "q500"
        ],
        "properties": {
          "q10": {
            "type": "boolean"
          },
          "q100": {
            "type": "boolean"
          },
          "q500": {
            "type": "boolean"
          },
          "q100_share_pct": {
            "type": [
              "number",
              "null"
            ]
          },
          "map_edition": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "LandslideValue": {
        "type": "object",
        "required": [
          "present"
        ],
        "properties": {
          "present": {
            "type": "boolean"
          },
          "kinds": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "landslide",
                "threatened_area"
              ]
            }
          },
          "count": {
            "type": "integer"
          }
        }
      },
      "ProtectedValue": {
        "type": "object",
        "required": [
          "inside_any",
          "forms"
        ],
        "properties": {
          "inside_any": {
            "type": "boolean"
          },
          "forms": {
            "type": "array",
            "items": {
              "type": "object",
              "required": [
                "type",
                "name"
              ],
              "properties": {
                "type": {
                  "type": "string",
                  "description": "park_narodowy, rezerwat, park_krajobrazowy, obszar_chronionego_krajobrazu, natura2000_oso, natura2000_soo, uzytek_ekologiczny, zespol_przyrodniczo_krajobrazowy, stanowisko_dokumentacyjne, pomnik_przyrody"
                },
                "code": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "name": {
                  "type": "string"
                }
              }
            }
          }
        }
      },
      "BuildingsValue": {
        "type": "object",
        "required": [
          "count"
        ],
        "properties": {
          "count": {
            "type": "integer"
          },
          "footprint_m2_total": {
            "type": [
              "number",
              "null"
            ]
          }
        }
      },
      "RoadAccessValue": {
        "type": "object",
        "required": [
          "verdict"
        ],
        "properties": {
          "verdict": {
            "type": "string",
            "enum": [
              "pass",
              "fail",
              "unknown"
            ]
          },
          "via": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "adjacent_public_road_parcel",
              "bdot_road_within_30m",
              null
            ]
          },
          "nearest_public_road_m": {
            "type": [
              "number",
              "null"
            ]
          }
        }
      },
      "PermitsValue": {
        "description": "GUNB RWDZ within 500 m, request-time. Investor names are never served.",
        "type": "object",
        "required": [
          "count_500m"
        ],
        "properties": {
          "count_500m": {
            "type": "integer"
          },
          "recent": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "kind": {
                  "type": "string"
                },
                "decision_date": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "format": "date"
                },
                "object_category": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "distance_m": {
                  "type": "number"
                }
              }
            }
          }
        }
      },
      "PricesValue": {
        "description": "Aggregated RCN comparables. Below 5 transactions the aggregate is withheld and coverage is covered_no_data.",
        "type": "object",
        "required": [
          "comparables_count"
        ],
        "properties": {
          "comparables_count": {
            "type": "integer"
          },
          "median_pln_m2": {
            "type": [
              "number",
              "null"
            ]
          },
          "p25_pln_m2": {
            "type": [
              "number",
              "null"
            ]
          },
          "p75_pln_m2": {
            "type": [
              "number",
              "null"
            ]
          },
          "window_months": {
            "type": "integer"
          },
          "radius_m": {
            "type": "integer"
          }
        }
      },
      "SoilValue": {
        "type": "object",
        "required": [
          "classes"
        ],
        "properties": {
          "classes": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "symbol": {
                  "type": "string"
                },
                "share_pct": {
                  "type": "number"
                }
              }
            }
          }
        }
      },
      "AddressValue": {
        "type": "object",
        "required": [
          "addresses"
        ],
        "properties": {
          "addresses": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "locality": {
                  "type": "string"
                },
                "street": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "house_number": {
                  "type": "string"
                },
                "postcode": {
                  "type": [
                    "string",
                    "null"
                  ]
                }
              }
            }
          }
        }
      },
      "CheckResult": {
        "type": "object",
        "required": [
          "verdict",
          "checks",
          "record",
          "disclaimer"
        ],
        "properties": {
          "verdict": {
            "type": "string",
            "enum": [
              "pass",
              "conditional",
              "fail",
              "unknown"
            ],
            "description": "Rule owned by the ported free check (geofeed/resolve). pass: every check pass. fail: a blocking check fails (no WZ path and no MPZP allowing building). conditional: buildable subject to a named condition (road access, flood, protected form). unknown: a blocking check is unknown."
          },
          "checks": {
            "type": "array",
            "items": {
              "type": "object",
              "required": [
                "id",
                "layer",
                "result",
                "source"
              ],
              "properties": {
                "id": {
                  "type": "string",
                  "enum": [
                    "pog_zone",
                    "wz_possible",
                    "mpzp_status",
                    "mpzp_params",
                    "flood_q100",
                    "landslide",
                    "protected",
                    "road_access"
                  ]
                },
                "layer": {
                  "$ref": "./envelope.json#/$defs/LayerKey"
                },
                "result": {
                  "type": "string",
                  "enum": [
                    "pass",
                    "fail",
                    "warn",
                    "unknown"
                  ]
                },
                "value": {},
                "detail": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "basis": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "source": {
                  "$ref": "./envelope.json#/$defs/SourceRef"
                }
              }
            }
          },
          "record": {
            "$ref": "#/components/schemas/ParcelRecord"
          },
          "disclaimer": {
            "type": "string"
          }
        }
      },
      "Event": {
        "type": "object",
        "required": [
          "id",
          "event",
          "detected_at"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "event": {
            "type": "string"
          },
          "layer": {
            "type": [
              "string",
              "null"
            ]
          },
          "before": {},
          "after": {},
          "as_of": {
            "type": [
              "string",
              "null"
            ],
            "format": "date"
          },
          "detected_at": {
            "type": "string",
            "format": "date-time"
          },
          "source": {
            "$ref": "./envelope.json#/$defs/SourceRef"
          }
        }
      },
      "Source": {
        "type": "object",
        "required": [
          "id",
          "title",
          "publisher",
          "licence",
          "attribution",
          "as_of",
          "freshness"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "title": {
            "type": "string"
          },
          "category": {
            "type": "string"
          },
          "layers": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "publisher": {
            "type": "string"
          },
          "url": {
            "type": [
              "string",
              "null"
            ]
          },
          "licence": {
            "type": "string"
          },
          "licence_url": {
            "type": [
              "string",
              "null"
            ]
          },
          "attribution": {
            "type": "string"
          },
          "band": {
            "type": "string"
          },
          "refresh_target": {
            "type": "string"
          },
          "as_of": {
            "type": [
              "string",
              "null"
            ],
            "format": "date"
          },
          "last_success_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "freshness": {
            "type": "string",
            "enum": [
              "fresh",
              "stale",
              "unknown"
            ]
          },
          "coverage_pct": {
            "type": [
              "number",
              "null"
            ]
          },
          "coverage_unit": {
            "type": [
              "string",
              "null"
            ]
          },
          "coverage_here": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "$ref": "./envelope.json#/$defs/Coverage"
              }
            ],
            "description": "Set only when q|id|point was given"
          }
        }
      },
      "GminaPlanning": {
        "type": "object",
        "required": [
          "gmina_teryt",
          "gmina_name",
          "pog_status",
          "as_of",
          "sources"
        ],
        "properties": {
          "gmina_teryt": {
            "type": "string"
          },
          "gmina_name": {
            "type": "string"
          },
          "pog_status": {
            "type": "string",
            "enum": [
              "draft",
              "adopted",
              "in_force",
              "none",
              "unknown"
            ]
          },
          "pog_adopted_on": {
            "type": [
              "string",
              "null"
            ],
            "format": "date"
          },
          "pog_effective_from": {
            "type": [
              "string",
              "null"
            ],
            "format": "date"
          },
          "pog_resolution_url": {
            "type": [
              "string",
              "null"
            ]
          },
          "mpzp_count": {
            "type": [
              "integer",
              "null"
            ]
          },
          "mpzp_coverage_pct": {
            "type": [
              "number",
              "null"
            ]
          },
          "studium_expired": {
            "type": [
              "boolean",
              "null"
            ]
          },
          "wz_regime": {
            "type": [
              "string",
              "null"
            ]
          },
          "as_of": {
            "type": "string",
            "format": "date"
          },
          "sources": {
            "type": "array",
            "items": {
              "$ref": "./envelope.json#/$defs/SourceRef"
            }
          }
        }
      }
    }
  }
}
