{
  "openapi": "3.1.0",
  "info": {
    "title": "Catastro GPS API",
    "version": "2026-10-05",
    "summary": "Cadastral parcels of Spain and the rest of Europe as a JSON API: reference, coordinates, outline and area; address search across Europe; relief, protected areas and ground motion; fincas and dwellings in Spain.",
    "description": "Public API of Catastro GPS / Parcel GPS. Spanish data comes from our own copy of the Dirección General del Catastro (dataSource `clone`/`local_clone`) and, when the copy does not have a finca, from the Catastro live (`catastro`). Attribution to the Dirección General del Catastro is mandatory and is returned in `attribution` where it applies.\n\n## Pricing and quota\n\nPlan prices are per month, in euros, **VAT included**. The quota belongs to your organisation and is shared by all its API keys.\n\n| Plan | Price per month (VAT included) | Units per month | Requests per minute | Extra units, per 1,000 (prepaid balance, plus 21% VAT) |\n|---|---|---|---|---|\n| Free | 0 € | 250 | 10 | 10.00 € |\n| Developer | 19 € | 5,000 | 60 | 5.00 € |\n| Startup | 49 € | 15,000 | 120 | 4.00 € |\n| Growth | 99 € | 50,000 | 300 | 2.50 € |\n| Enterprise | from 300 € | by contract | 300, or more by contract | by contract |\n\n**What counts as a unit.** Only successful (2xx) answers with data cost units:\n\n| Call | Units |\n|---|---|\n| Parcel by reference, by coordinates, `/solar`, `/agro`, `/score`, `/market` | 1 per answer; 0 when the answer carries no data (`disponible: false` from `/market` or `/solar`, an empty `/agro`, a `/score` without data) |\n| `GET /api/search/address/candidates` | 1 when it returns candidates; none found is a 404 and free |\n| `GET /api/catastro/{refcat14}/units` | 1 per unit (dwelling) served in that page, minimum 1 |\n| `POST /api/catastro/compare` | 1 per parcel found (0 to 3); free if none is found |\n| Any other 2xx answer | 1 |\n| 304 Not Modified, 300, 4xx, 5xx | free |\n\n**Reset.** The quota resets at 00:00 UTC on day 1 of every calendar month (`X-Quota-Reset`). Unused units do not carry over to the next month.\n\n**When the quota runs out.** Requests keep working and each extra unit is charged to your organisation's prepaid balance at your plan's price above. Top-ups are made in the developer portal (https://parcelgps.com/app/developer): from 5 € to 1,000 € net per top-up, plus 21% VAT shown on the invoice. With the quota used up and no balance left (or overage paused in the portal), the API answers **429 `KEY_AUTH_004`** and nothing is charged; there is never a debt. Current overage prices: `GET /api/api-overage/pricing`.\n\n**Rate limit.** Per API key and minute, by plan (table above). Going over answers 429 `KEY_RATE_002` with `Retry-After`.\n\nError bodies always carry a stable machine code in `code` and an English text in `error`.\n\n## Coverage by country\n\nWhat each country answers today (measured against production on 1 October 2026; address search with five real addresses per country). Every country returns the reference, the GPS point (`latitud`, `longitud`), the outline (`poligono`) and the area (`superficieParcela`), by reference and by coordinates, unless the row says otherwise. `availableFields` in each response says which of the optional fields that response really carries.\n\n| Country | `country` | By reference | By coordinates | By address (`/search/address/candidates`) | Extra data |\n|---|---|---|---|---|---|\n| Spain, common territory | `ES` | yes | yes | yes (CartoCiudad) | address, use, class, built area, year, units/dwellings; `/units` |\n| Spain, Basque Country / Navarre | `PV` / `NA` | yes | yes | yes, with `country=ES` | address, use, built area, year; `/units` (foral copy, no participation coefficient) |\n| France | `FR` | yes | yes | yes (Base Adresse Nationale) | by reference also use, built area, year, dwellings and floors (BDNB) |\n| Italy | `IT` | yes | yes | yes (OpenStreetMap) | municipality, province |\n| Germany (15 of 16 Länder, **no Bavaria**) | `DE` | yes | yes | yes (OpenStreetMap), not in Bavaria | municipality, Land |\n| Austria | `AT` | yes | yes | yes (OpenStreetMap) | municipality, use |\n| Netherlands | `NL` | yes | yes | yes (PDOK Locatieserver) | municipality |\n| Belgium | `BE` | yes | yes (3-7 s, slow source) | yes (Digitaal Vlaanderen + OpenStreetMap), 5-15 s | — |\n| Poland | `PL` | yes | yes | yes (GUGiK) | municipality, voivodeship |\n| Switzerland | `CH` | yes | yes, except where the canton publishes no parcels (e.g. Vaud) | yes (swisstopo) | canton |\n| Czechia | `CZ` | yes | yes | yes (RÚIAN) | — |\n| Denmark | `DK` | yes | yes | yes (Dataforsyningen) | municipality |\n| Norway | `NO` | yes | yes | yes (OpenStreetMap) | municipality |\n| Finland | `FI` | yes | yes | yes (OpenStreetMap) | — |\n| Estonia | `EE` | yes | yes | yes (In-ADS) | municipality |\n| Latvia | `LV` | yes; bare digits need `?country=LV` | yes | yes (OpenStreetMap) | — |\n| Lithuania, Slovenia, Slovakia, Bulgaria | `LT`, `SI`, `SK`, `BG` | yes | yes | yes (OpenStreetMap; Cyrillic accepted in `BG`) | municipality in `SI` |\n| Luxembourg, Liechtenstein, Iceland | `LU`, `LI`, `IS` | yes | yes | yes (OpenStreetMap) | — |\n| Greece | `GR` | only with `?country=GR` | yes | yes (OpenStreetMap; Greek script) | — |\n| Cyprus | `CY` | yes | yes | yes (OpenStreetMap), low `confianza`: few house numbers mapped | — |\n| Portugal | `PT` | yes | partial: the cadastre does not cover Lisbon, Porto or Coimbra | partial, same limit; the DGT source is often down | municipality |\n| Ireland | `IE` | only with `?country=` (the numeric SP_ID) | partial | partial (OpenStreetMap) | county |\n| United Kingdom | `UK` | no | Scotland only | Scotland only (OpenStreetMap) | — |\n| Croatia | `HR` | no: there is no open cadastre | **ARKOD agricultural parcels only** (Croatian Paying Agency), not cadastral parcels, and not nationwide (Zagreb and Rijeka have none) | no (422) | — |\n| Sweden | `SE` | agricultural blocks | agricultural blocks | no (422): no parcels at urban addresses | land use |\n\nNot covered: Hungary, Romania and the rest. A reference from a country without coverage answers **422 `CNV_COVERAGE`**; bare digits that could belong to several countries answer **300 `CNV_AMBIGUOUS`** with the candidate countries — repeat the call with `?country=`. `/units` and dwellings are Spain only (common territory, Basque Country and Navarra).\n\nThe analysis endpoints (`/solar`, `/agro`, `/score`) cover `ES`, `PV`, `NA`, `PT`, `FR`, `IT` and `DE`; other countries answer 422 `CNV_COVERAGE`. Human-readable coverage and pricing: https://parcelgps.com/developers.",
    "contact": {
      "name": "Catastro GPS",
      "email": "soporte@catastrogps.es",
      "url": "https://parcelgps.com/developers"
    }
  },
  "servers": [
    {
      "url": "https://api.parcelgps.com",
      "description": "Production"
    }
  ],
  "security": [
    {
      "ApiKey": []
    }
  ],
  "tags": [
    {
      "name": "Fincas",
      "description": "Import a building (comunidad de propietarios): address to finca, then all of its units."
    },
    {
      "name": "Parcels",
      "description": "Look a parcel or a unit up by reference or by coordinates."
    },
    {
      "name": "Hazards",
      "description": "Natural hazards and terrain of a parcel measured from satellite data."
    }
  ],
  "paths": {
    "/api/search/address/candidates": {
      "get": {
        "tags": [
          "Fincas"
        ],
        "operationId": "searchAddressCandidates",
        "summary": "Address to parcel in Spain and 25 other European countries, with ranked candidates",
        "description": "Turns a postal address into cadastral parcels, ranked by `confianza` (0 to 1).\n\n- **Spain** (default, `country=ES`): geocodes against CartoCiudad (Instituto Geográfico Nacional) and returns the building entrances (portales) that match, each with its 14-character cadastral reference. Does not depend on the Catastro being up. Candidates in the Basque Country (`pais: PV`) and Navarra (`pais: NA`) carry the foral reference.\n- **Other countries** (`country=FR`, `IT`, `DE`, `AT`, `NL`, `BE`, `PL`, `CH`, `CZ`, `DK`, `NO`, `FI`, `EE`, `LV`, `LT`, `SI`, `SK`, `BG`, `GR`, `CY`, `LU`, `LI`, `IS`, `IE`, `UK`, `PT`): the address is geocoded with the official national address register where there is a free one (France: Base Adresse Nationale; Netherlands: PDOK Locatieserver; Switzerland: swisstopo; Poland: GUGiK; Czechia: RÚIAN; Estonia: In-ADS; Denmark: Dataforsyningen; Flanders: Digitaal Vlaanderen) and with OpenStreetMap (Photon, Nominatim as backup) elsewhere. The parcel under each address point comes from that country's official cadastre, the same source as `/search/coordinates`. In Italy streets and waters (`STRADA…`, `ACQUA…`) are never returned. Sweden and Croatia answer 422: their sources have no parcels at urban addresses.\n\nOutside Spain `confianza` combines the geocoder score with whether the house number, the municipality (or postcode) and the street match: 0.75 or more means the number and the municipality match; when the geocoder only knows the street, `coincideNumero` is false and the parcel is one on that street. Use the reference with `GET /api/catastro/{refcat}` for the outline and area.\n\nCosts 1 quota unit when it returns candidates; 404 (nothing found), 422 and 304 are free.",
        "parameters": [
          {
            "name": "country",
            "in": "query",
            "description": "Country of the address. `ES` (default) also returns Basque Country and Navarra entrances. A country without address search (`SE`, `HR`, or one that is not covered) answers 422 `CNV_COVERAGE` with `data.supportedCountries`.",
            "schema": {
              "type": "string",
              "enum": [
                "ES",
                "FR",
                "IT",
                "DE",
                "AT",
                "NL",
                "BE",
                "PL",
                "CH",
                "CZ",
                "DK",
                "NO",
                "FI",
                "EE",
                "LV",
                "LT",
                "SI",
                "SK",
                "BG",
                "GR",
                "CY",
                "LU",
                "LI",
                "IS",
                "IE",
                "UK",
                "PT"
              ],
              "default": "ES"
            },
            "examples": {
              "FR": {
                "value": "FR"
              },
              "NL": {
                "value": "NL"
              },
              "DE": {
                "value": "DE"
              }
            }
          },
          {
            "name": "q",
            "in": "query",
            "description": "Free-text address: street and number, then municipality (and optionally postcode). Required unless `street` is given. Examples: `Calle Gran Vía 31, Madrid`, `8 boulevard du Port, Amiens`, `Via Toledo 256, Napoli`, `Damrak 1, 1012 LG Amsterdam`, `Floriańska 15, 31-019 Kraków`, `Unter den Linden 77, 10117 Berlin`.",
            "schema": {
              "type": "string",
              "minLength": 3,
              "maxLength": 200
            },
            "example": "Avenida José Rodríguez de la Borbolla Camoyán 10, Dos Hermanas"
          },
          {
            "name": "street",
            "in": "query",
            "description": "Street with its type, when the address is structured.",
            "schema": {
              "type": "string"
            },
            "example": "Calle Gran Vía"
          },
          {
            "name": "number",
            "in": "query",
            "description": "House number. Overrides the number found in `q`.",
            "schema": {
              "type": "integer",
              "minimum": 1
            },
            "example": 31
          },
          {
            "name": "municipality",
            "in": "query",
            "description": "Municipality. Overrides the one found in `q`.",
            "schema": {
              "type": "string"
            },
            "example": "Madrid"
          },
          {
            "name": "postcode",
            "in": "query",
            "description": "Postcode in the country's own format: five digits in Spain, France, Italy, Germany, Finland, Estonia; four in Austria, Belgium, Switzerland, Denmark, Norway, Slovenia, Bulgaria, Cyprus, Liechtenstein, Luxembourg (`L-1660` accepted) and Latvia (`LV-1012` accepted); `1012 LG` in the Netherlands, `31-019` in Poland, `2510-191` in Portugal, `110 00` in Czechia, Slovakia and Greece, UK postcodes and Irish Eircodes. A postcode in another format answers 400.",
            "schema": {
              "type": "string"
            },
            "example": "28013"
          },
          {
            "name": "limit",
            "in": "query",
            "description": "Maximum candidates returned.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 10,
              "default": 5
            }
          },
          {
            "$ref": "#/components/parameters/IfNoneMatch"
          }
        ],
        "responses": {
          "200": {
            "description": "Candidates ordered by confidence (best first).",
            "headers": {
              "X-Quota-Limit": {
                "$ref": "#/components/headers/XQuotaLimit"
              },
              "X-Quota-Remaining": {
                "$ref": "#/components/headers/XQuotaRemaining"
              },
              "X-Quota-Reset": {
                "$ref": "#/components/headers/XQuotaReset"
              },
              "X-Quota-Tier": {
                "$ref": "#/components/headers/XQuotaTier"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AddressCandidatesResponse"
                }
              }
            }
          },
          "304": {
            "$ref": "#/components/responses/NotModified"
          },
          "400": {
            "$ref": "#/components/responses/ValidationError"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "422": {
            "description": "`country` is not one of ES, FR, IT (`CNV_COVERAGE`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/api/catastro/{refcat14}/units": {
      "get": {
        "tags": [
          "Fincas"
        ],
        "operationId": "getFincaUnits",
        "summary": "All units (dwellings, shops, garages, storage) of a finca",
        "description": "Returns every unit of a finca, up to 200 per page, ordered by reference. Follow `nextCursor` while `truncated` is true. **Common territory (`ES`)**: pass the 14-character finca reference. Served from our copy of the Catastro (`dataSource: clone`); when the copy lacks the finca, or has fewer dwellings than the building declares, it is read live from the Catastro (`dataSource: catastro`). A finca that is a single property (a hotel, a detached house) is returned as one unit with its 20-character reference, and its building elements go in `construcciones`. **Basque Country (`PV`) and Navarra (`NA`)**: pass the foral reference of any unit of the building (Bizkaia: Número Fijo, e.g. `N0714723L`; Araba: 20-character CODETI; Gipuzkoa: Referen+N.Fijo+D, 15 characters; Navarra: 20-character reference starting with 31) or the finca key returned in `refCatastral` (municipio-polígono-parcela, e.g. `020-3-657` in Bizkaia, `59-0002-183` in Araba, `201-04-2651` in Navarra; in Gipuzkoa municipio+Referen). Units come from our copy of each foral cadastre (`dataSource: clone`, `dataDate` = publication of the source, `attribution` = the Diputación Foral or the Gobierno de Navarra). The foral open data carry no participation coefficient, so `participacion` is absent; Navarra and Araba carry stair, floor and door, Bizkaia floor and door, Gipuzkoa floor and door. A foral parcel without units (rústica, solar) is returned as one whole-property unit. Foral references and municipio-polígono-parcela keys are detected without `country`: a reference the detected foral copy does not hold is looked up in the other one (Navarra or the Basque Country). Gipuzkoa finca keys need `country=PV`. Costs one quota unit per unit served in the page (minimum 1), and the page is cut to what the quota and the prepaid balance still cover; a 304 on refresh is free. A per-finca cap is a per-contract condition agreed with specific customers, not part of any plan: organisations that have one pay at most that cap per finca and quota period across all its pages; see the `X-Quota-Finca-Cap*` headers. Requires an organisation API key or a signed-in user.",
        "parameters": [
          {
            "name": "refcat14",
            "in": "path",
            "required": true,
            "description": "ES: 14-character finca reference (a 20-character one is cut to 14). PV and NA: the foral reference of any unit of the finca, or the finca key (`refCatastral` of a previous answer).",
            "schema": {
              "type": "string",
              "minLength": 6,
              "maxLength": 25
            },
            "example": "0745901TG4304N"
          },
          {
            "name": "cursor",
            "in": "query",
            "description": "`nextCursor` of the previous page: the last unit reference served (20 characters in ES and NA, the foral unit reference in PV).",
            "schema": {
              "type": "string",
              "pattern": "^[0-9A-Z]{6,24}$"
            }
          },
          {
            "name": "country",
            "in": "query",
            "description": "`ES` (default) for common territory, `PV` for Álava/Araba, Bizkaia and Gipuzkoa, `NA` for Navarra. Optional for foral references that are detected by their shape (all but Araba).",
            "schema": {
              "type": "string",
              "enum": [
                "ES",
                "PV",
                "NA"
              ]
            }
          },
          {
            "$ref": "#/components/parameters/IfNoneMatch"
          }
        ],
        "responses": {
          "200": {
            "description": "One page of units.",
            "headers": {
              "X-Quota-Limit": {
                "$ref": "#/components/headers/XQuotaLimit"
              },
              "X-Quota-Remaining": {
                "$ref": "#/components/headers/XQuotaRemaining"
              },
              "X-Quota-Reset": {
                "$ref": "#/components/headers/XQuotaReset"
              },
              "X-Quota-Tier": {
                "$ref": "#/components/headers/XQuotaTier"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "X-Quota-Finca-Cap": {
                "$ref": "#/components/headers/XQuotaFincaCap"
              },
              "X-Quota-Finca-Cap-Used": {
                "$ref": "#/components/headers/XQuotaFincaCapUsed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UnitsResponse"
                }
              }
            }
          },
          "304": {
            "$ref": "#/components/responses/NotModified"
          },
          "400": {
            "$ref": "#/components/responses/ValidationError"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "description": "Finca not found in our copy (ES: neither in the Catastro). PV/NA: the reference is neither a foral unit, a foral parcel nor a finca key. Free.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/api/catastro/{refcat}": {
      "get": {
        "tags": [
          "Parcels"
        ],
        "operationId": "getParcel",
        "summary": "Parcel or unit by cadastral reference",
        "description": "With a 20-character Spanish reference it returns that unit (dwelling), with the same per-unit fields as the units list: `uso`, `participacion` (number, %), `escalera`, `planta`, `puerta`. `superficieConstruida` here is `superficie` in the units list. The country is detected from the reference format unless `country` is given. Costs 1 quota unit.",
        "parameters": [
          {
            "name": "refcat",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "example": "0745901TG4304N0002KH"
          },
          {
            "name": "country",
            "in": "query",
            "description": "ISO code of the country: ES, PV, NA, FR, IT, DE, AT, PT, PL, NL, CH, BE, CZ, DK, FI, EE, SI, LT, LU, SK, BG, LI, IS, CY, GR, LV, IE, SE. Detected from the reference when omitted; required for GR, LV and IE. Coverage table in the description of this API and at https://parcelgps.com/developers.",
            "schema": {
              "type": "string",
              "minLength": 2,
              "maxLength": 2
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The parcel or unit.",
            "headers": {
              "X-Quota-Limit": {
                "$ref": "#/components/headers/XQuotaLimit"
              },
              "X-Quota-Remaining": {
                "$ref": "#/components/headers/XQuotaRemaining"
              },
              "X-Quota-Reset": {
                "$ref": "#/components/headers/XQuotaReset"
              },
              "X-Quota-Tier": {
                "$ref": "#/components/headers/XQuotaTier"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ParcelResponse"
                }
              }
            }
          },
          "300": {
            "description": "CNV_AMBIGUOUS: bare digits that could be a reference of several countries. `data.candidates` lists them; repeat with `?country=`. Free.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ValidationError"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "422": {
            "description": "CNV_COVERAGE: the reference belongs to a country without coverage (`data.country`). CNV_PLACE_NAME: the text is a place name, not a reference. Free.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/api/search/coordinates": {
      "get": {
        "tags": [
          "Parcels"
        ],
        "operationId": "searchByCoordinates",
        "summary": "Parcel at a point (WGS84)",
        "parameters": [
          {
            "name": "lat",
            "in": "query",
            "required": true,
            "schema": {
              "type": "number"
            },
            "example": 40.41998
          },
          {
            "name": "lng",
            "in": "query",
            "required": true,
            "schema": {
              "type": "number"
            },
            "example": -3.70377
          },
          {
            "name": "country",
            "in": "query",
            "description": "ISO code of the country: ES, PV, NA, FR, IT, DE, AT, PT, PL, NL, CH, BE, CZ, DK, FI, EE, SI, LT, LU, SK, BG, LI, IS, CY, GR, LV, IE, HR, UK, SE. Detected from the point when omitted.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The parcel at that point.",
            "headers": {
              "X-Quota-Limit": {
                "$ref": "#/components/headers/XQuotaLimit"
              },
              "X-Quota-Remaining": {
                "$ref": "#/components/headers/XQuotaRemaining"
              },
              "X-Quota-Reset": {
                "$ref": "#/components/headers/XQuotaReset"
              },
              "X-Quota-Tier": {
                "$ref": "#/components/headers/XQuotaTier"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CoordinatesResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ValidationError"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      },
      "post": {
        "tags": [
          "Parcels"
        ],
        "operationId": "searchByCoordinatesPost",
        "summary": "Parcel at a point (WGS84), JSON body",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "latitude",
                  "longitude"
                ],
                "properties": {
                  "latitude": {
                    "type": "number"
                  },
                  "longitude": {
                    "type": "number"
                  },
                  "country": {
                    "type": "string",
                    "description": "ISO code of the country: ES, PV, NA, FR, IT, DE, AT, PT, PL, NL, CH, BE, CZ, DK, FI, EE, SI, LT, LU, SK, BG, LI, IS, CY, GR, LV, IE, HR, UK, SE. Detected from the point when omitted."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The parcel at that point.",
            "headers": {
              "X-Quota-Limit": {
                "$ref": "#/components/headers/XQuotaLimit"
              },
              "X-Quota-Remaining": {
                "$ref": "#/components/headers/XQuotaRemaining"
              },
              "X-Quota-Reset": {
                "$ref": "#/components/headers/XQuotaReset"
              },
              "X-Quota-Tier": {
                "$ref": "#/components/headers/XQuotaTier"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CoordinatesResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ValidationError"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/api/search/address": {
      "post": {
        "tags": [
          "Parcels"
        ],
        "operationId": "searchByStructuredAddress",
        "summary": "Structured Spanish address to reference (Catastro callejero, live)",
        "description": "Asks the Catastro street index live, so it fails with 404 when the Catastro is saturated. Prefer `GET /api/search/address/candidates`.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "provincia",
                  "municipio",
                  "nombreVia",
                  "numero"
                ],
                "properties": {
                  "provincia": {
                    "type": "string"
                  },
                  "municipio": {
                    "type": "string"
                  },
                  "tipoVia": {
                    "type": "string",
                    "description": "Catastro street type code, e.g. CL, AV, PZ."
                  },
                  "nombreVia": {
                    "type": "string"
                  },
                  "numero": {
                    "type": "integer",
                    "minimum": 1
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The reference at that address.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LegacyAddressResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ValidationError"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/api/search/address/parse": {
      "post": {
        "tags": [
          "Parcels"
        ],
        "operationId": "searchByFreeAddress",
        "summary": "Free-text Spanish address to reference (Catastro callejero, live)",
        "description": "Parses the text and asks the Catastro street index live. Prefer `GET /api/search/address/candidates`, which does not depend on the Catastro and returns several candidates.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "direccion"
                ],
                "properties": {
                  "direccion": {
                    "type": "string",
                    "example": "Calle Gran Vía 31, Madrid"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The reference at that address.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LegacyAddressResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ValidationError"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/api/catastro/{refcat}/terrain": {
      "get": {
        "tags": [
          "Hazards"
        ],
        "operationId": "getTerrain",
        "summary": "Relief, protected areas and climate normals of a parcel",
        "description": "Three blocks for one parcel, each with its own `status` and `source` (licence and the attribution string that must be shown next to the data):\n\n- `relief`: elevation, slope and aspect over the parcel outline from Copernicus DEM GLO-30 (30 m).\n- `protected_areas`: Natura 2000 sites and nationally designated areas (EEA) that overlap the parcel, with the overlap share.\n- `climate`: ERA5-Land climate normals at the parcel point (mean temperature, precipitation, frost and hot days, recent change); `status: unavailable` while the grid cannot be read.\n\nIn `ES`, `PV`, `NA`, `PT`, `FR`, `IT` and `DE` the reference alone is enough. In every other covered country pass `lat` and `lng` (the `latitud` and `longitud` of `/api/catastro/{refcat}` or `/api/search/coordinates`) so the outline can be found. A reference with a slash goes URL-encoded (`%2F`). Costs 1 unit of the monthly quota.",
        "parameters": [
          {
            "name": "refcat",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "example": "10194A00110004"
          },
          {
            "name": "country",
            "in": "query",
            "description": "ISO code of the country: ES, PV, NA, FR, IT, DE, AT, PT, PL, NL, CH, BE, CZ, DK, FI, EE, SI, LT, LU, SK, BG, LI, IS, CY, GR, LV, IE, SE. Detected from the reference when omitted; required for GR, LV and IE. Coverage table in the description of this API and at https://parcelgps.com/developers.",
            "schema": {
              "type": "string",
              "minLength": 2,
              "maxLength": 2
            }
          },
          {
            "name": "lat",
            "in": "query",
            "description": "Latitude (WGS84) of the parcel point. Required outside ES, PV, NA, PT, FR, IT and DE.",
            "schema": {
              "type": "number"
            },
            "example": 50.848139
          },
          {
            "name": "lng",
            "in": "query",
            "description": "Longitude (WGS84) of the parcel point. Required outside ES, PV, NA, PT, FR, IT and DE.",
            "schema": {
              "type": "number"
            },
            "example": 4.353613
          }
        ],
        "responses": {
          "200": {
            "description": "Relief, protected areas and climate of the parcel. Real response measured in production on 30 September 2026 (climate block left out).",
            "headers": {
              "X-Quota-Limit": {
                "$ref": "#/components/headers/XQuotaLimit"
              },
              "X-Quota-Remaining": {
                "$ref": "#/components/headers/XQuotaRemaining"
              },
              "X-Quota-Reset": {
                "$ref": "#/components/headers/XQuotaReset"
              },
              "X-Quota-Tier": {
                "$ref": "#/components/headers/XQuotaTier"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TerrainResponse"
                },
                "example": {
                  "success": true,
                  "data": {
                    "refcat": "10194A00110004",
                    "country": "ES",
                    "relief": {
                      "status": "ok",
                      "elevation_m": {
                        "mean": 365.8,
                        "min": 212.3,
                        "max": 506.6
                      },
                      "slope": {
                        "mean_pct": 36.5,
                        "mean_deg": 20,
                        "max_pct": 71.6,
                        "class": "very_steep",
                        "max_class": "very_steep",
                        "share_over_10_pct": 98.4,
                        "classes_pct": {
                          "flat": 0.2,
                          "gentle": 1.4,
                          "moderate": 6.8,
                          "steep": 20,
                          "very_steep": 71.7
                        }
                      },
                      "aspect": {
                        "dominant": "N",
                        "dominant_share_pct": 75.3,
                        "mean_deg": 0,
                        "flat_share_pct": 0.2,
                        "sectors_pct": {
                          "N": 75.3,
                          "NE": 10.6,
                          "E": 0.6,
                          "SE": 0.1,
                          "S": 0,
                          "SW": 1,
                          "W": 1.4,
                          "NW": 10.8
                        }
                      },
                      "sample": {
                        "method": "parcel",
                        "cells": 1448,
                        "resolution_m": 31
                      },
                      "source": {
                        "name": "Copernicus DEM GLO-30",
                        "license": "Copernicus DEM licence (free, commercial use allowed)",
                        "attribution": "© DLR e.V. 2010-2014 and © Airbus Defence and Space GmbH 2014-2018 provided under COPERNICUS by the European Union and ESA; all rights reserved"
                      }
                    },
                    "protected_areas": {
                      "status": "ok",
                      "intersects": true,
                      "inside": true,
                      "max_overlap_pct": 100,
                      "natura2000": [
                        {
                          "code": "ES0000014",
                          "name": "Monfragüe y las Dehesas del Entorno",
                          "type": "SPA",
                          "country": "ES",
                          "overlap_pct": 100
                        },
                        {
                          "code": "ES4320077",
                          "name": "Monfragüe",
                          "type": "SCI",
                          "country": "ES",
                          "overlap_pct": 100
                        }
                      ],
                      "national": [
                        {
                          "code": "4820",
                          "name": "Monfragüe",
                          "designation": "National Park",
                          "country": "ES",
                          "overlap_pct": 100
                        }
                      ],
                      "method": "parcel",
                      "sources": [
                        {
                          "name": "Natura 2000",
                          "license": "CC BY 4.0",
                          "edition": "end 2024"
                        },
                        {
                          "name": "Nationally designated areas (CDDA)",
                          "license": "CC BY 4.0",
                          "edition": "2025"
                        }
                      ]
                    },
                    "calculated_at": "2026-09-30T19:45:02Z",
                    "provenance": "3"
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ValidationError"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "description": "NOT_FOUND: the parcel was not found, or `lat` and `lng` are missing in a country that needs them. Free.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "503": {
            "description": "TRN_040: terrain data is temporarily unavailable. Free.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/catastro/{refcat}/ground-motion": {
      "get": {
        "tags": [
          "Hazards"
        ],
        "operationId": "getGroundMotion",
        "summary": "Ground motion (subsidence or uplift, mm/year) of a parcel, 2020-2024",
        "description": "Satellite-measured vertical and east-west ground velocity over the parcel, its class, the fastest-sinking cell and the yearly displacement, for every country with a parcel outline inside EGMS coverage (EEA-39). Data: Copernicus Land Monitoring Service, European Ground Motion Service (free, commercial use allowed); the `source.attribution` string must be shown next to the data. Costs 1 unit of the monthly quota.",
        "parameters": [
          {
            "name": "refcat",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "example": "0745901TG4304N0002KH"
          },
          {
            "name": "country",
            "in": "query",
            "description": "ISO code of the country: ES, PV, NA, FR, IT, DE, AT, PT, PL, NL, CH, BE, CZ, DK, FI, EE, SI, LT, LU, SK, BG, LI, IS, CY, GR, LV, IE, SE. Detected from the reference when omitted; required for GR, LV and IE. Coverage table in the description of this API and at https://parcelgps.com/developers.",
            "schema": {
              "type": "string",
              "minLength": 2,
              "maxLength": 2
            }
          }
        ],
        "responses": {
          "300": {
            "description": "CNV_AMBIGUOUS: bare digits that could be a reference of several countries. `data.candidates` lists them; repeat with `?country=`. Free.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ValidationError"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "422": {
            "description": "CNV_COVERAGE: the reference belongs to a country without coverage (`data.country`). CNV_PLACE_NAME: the text is a place name, not a reference. Free.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          },
          "200": {
            "description": "Ground motion of the parcel, or `status: no_data` with the reason.",
            "headers": {
              "X-Quota-Limit": {
                "$ref": "#/components/headers/XQuotaLimit"
              },
              "X-Quota-Remaining": {
                "$ref": "#/components/headers/XQuotaRemaining"
              },
              "X-Quota-Reset": {
                "$ref": "#/components/headers/XQuotaReset"
              },
              "X-Quota-Tier": {
                "$ref": "#/components/headers/XQuotaTier"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GroundMotionResponse"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "ApiKey": {
        "type": "apiKey",
        "in": "header",
        "name": "X-API-Key",
        "description": "Create keys at https://www.catastrogps.es/app/developer"
      }
    },
    "parameters": {
      "IfNoneMatch": {
        "name": "If-None-Match",
        "in": "header",
        "description": "ETag of a previous response. When nothing changed the answer is 304 with no body and costs no quota.",
        "schema": {
          "type": "string"
        }
      }
    },
    "headers": {
      "XQuotaLimit": {
        "description": "Monthly quota of your plan.",
        "schema": {
          "type": "integer"
        }
      },
      "XQuotaRemaining": {
        "description": "Quota left this month, after this response.",
        "schema": {
          "type": "integer"
        }
      },
      "XQuotaReset": {
        "description": "When the monthly quota resets (ISO 8601, UTC).",
        "schema": {
          "type": "string",
          "format": "date-time"
        }
      },
      "XQuotaTier": {
        "description": "Plan of the organisation.",
        "schema": {
          "type": "string"
        }
      },
      "XRateLimitLimit": {
        "description": "Requests allowed per minute for your key.",
        "schema": {
          "type": "integer"
        }
      },
      "XRateLimitRemaining": {
        "description": "Requests left in the current minute.",
        "schema": {
          "type": "integer"
        }
      },
      "ETag": {
        "description": "Entity tag of the body. Send it back in If-None-Match.",
        "schema": {
          "type": "string"
        }
      },
      "CacheControl": {
        "description": "private, max-age in seconds (6 h for units, 24 h for address candidates).",
        "schema": {
          "type": "string"
        }
      },
      "RetryAfter": {
        "description": "Seconds to wait before retrying.",
        "schema": {
          "type": "integer"
        }
      },
      "XQuotaFincaCap": {
        "description": "Only on `/units` for organisations with a per-finca cap (a per-contract condition agreed with specific customers, not part of any plan): the most quota units one finca can cost in the current quota period, adding up all its pages.",
        "schema": {
          "type": "integer"
        }
      },
      "XQuotaFincaCapUsed": {
        "description": "Only on `/units` for organisations with a per-finca cap agreed by contract: quota units already charged for this finca in the current quota period, including this response. Once it reaches `X-Quota-Finca-Cap`, more pages or repeats of the same finca in the period cost nothing.",
        "schema": {
          "type": "integer"
        }
      }
    },
    "responses": {
      "NotModified": {
        "description": "Unchanged since the ETag you sent. No body, no quota spent."
      },
      "ValidationError": {
        "description": "Malformed parameters (code VALIDATION_ERROR).",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "Unauthorized": {
        "description": "Missing, malformed or unknown API key (KEY_AUTH_001, KEY_AUTH_002, KEY_AUTH_003, UNAUTHORIZED).",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "NotFound": {
        "description": "The reference or address does not exist (code NOT_FOUND). Never used for outages.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "TooManyRequests": {
        "description": "KEY_AUTH_004: monthly quota used up and no prepaid balance left to cover the request (see X-Quota-*); nothing is charged. The message says the plan, the price per 1,000 extra units, where to top up and when the quota resets. KEY_RATE_002 or RATE_LIMIT_EXCEEDED: per-minute limit, wait Retry-After seconds.",
        "headers": {
          "Retry-After": {
            "$ref": "#/components/headers/RetryAfter"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "ServiceUnavailable": {
        "description": "The official source of that country is down or saturated and our copy cannot answer (code SERVICE_UNAVAILABLE). Retry after Retry-After seconds. Free.",
        "headers": {
          "Retry-After": {
            "$ref": "#/components/headers/RetryAfter"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      }
    },
    "schemas": {
      "Error": {
        "type": "object",
        "required": [
          "success",
          "code",
          "error"
        ],
        "properties": {
          "success": {
            "type": "boolean",
            "const": false
          },
          "code": {
            "type": "string",
            "description": "Stable machine code.",
            "examples": [
              "NOT_FOUND",
              "SERVICE_UNAVAILABLE",
              "KEY_AUTH_004"
            ]
          },
          "error": {
            "type": "string",
            "description": "English text for humans. May change; route on `code`."
          }
        }
      },
      "AddressCandidatesResponse": {
        "type": "object",
        "required": [
          "success",
          "data"
        ],
        "properties": {
          "success": {
            "type": "boolean",
            "const": true
          },
          "data": {
            "type": "object",
            "required": [
              "consulta",
              "candidatos",
              "attribution"
            ],
            "properties": {
              "consulta": {
                "type": "object",
                "description": "How the address was read.",
                "properties": {
                  "texto": {
                    "type": "string"
                  },
                  "calle": {
                    "type": "string"
                  },
                  "numero": {
                    "type": "integer"
                  },
                  "municipio": {
                    "type": "string"
                  },
                  "codigoPostal": {
                    "type": "string"
                  }
                }
              },
              "candidatos": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/AddressCandidate"
                }
              },
              "attribution": {
                "type": "string"
              }
            }
          }
        }
      },
      "AddressCandidate": {
        "type": "object",
        "required": [
          "refCatastral",
          "pais",
          "direccion",
          "municipio",
          "provincia",
          "latitud",
          "longitud",
          "confianza",
          "coincideNumero",
          "coincideMunicipio",
          "enCopia"
        ],
        "properties": {
          "refCatastral": {
            "type": "string",
            "description": "Spain: 14-character finca reference in common territory, the foral reference in PV and NA. France: 14-character parcel IDU. Italy: particella reference (Belfiore code, sheet and number, e.g. `F839_019800.166`)."
          },
          "pais": {
            "type": "string",
            "enum": [
              "ES",
              "PV",
              "NA",
              "FR",
              "IT"
            ],
            "description": "ES: common territory, use the units endpoint. PV and NA: foral cadastre; list its units with GET /api/catastro/{refcat}/units?country=PV|NA. FR and IT: look the parcel up with GET /api/catastro/{refcat}?country=FR|IT."
          },
          "direccion": {
            "type": "string",
            "description": "Spain: address as the IGN writes it. France and Italy: the normalised address the geocoder matched."
          },
          "numero": {
            "type": "integer"
          },
          "codigoPostal": {
            "type": "string"
          },
          "municipio": {
            "type": "string"
          },
          "provincia": {
            "type": "string",
            "description": "Province (Spain), département (France) or province (Italy)."
          },
          "latitud": {
            "type": "number",
            "description": "Point of the address (entrance in Spain, address point in France and Italy)."
          },
          "longitud": {
            "type": "number"
          },
          "confianza": {
            "type": "number",
            "minimum": 0,
            "maximum": 1,
            "description": "0.75 or more: number and municipality match."
          },
          "coincideNumero": {
            "type": "boolean"
          },
          "coincideMunicipio": {
            "type": "boolean"
          },
          "enCopia": {
            "type": "boolean",
            "description": "The finca is in our copy of the Catastro (Spain only; always false in France and Italy)."
          },
          "direccionCatastro": {
            "type": "string",
            "description": "Address as the Catastro writes it (when enCopia)."
          },
          "uso": {
            "type": "string"
          },
          "viviendas": {
            "type": "integer",
            "description": "Dwellings the building declares (when enCopia)."
          },
          "anioConstruccion": {
            "type": "integer"
          }
        }
      },
      "UnitsResponse": {
        "type": "object",
        "required": [
          "success",
          "data"
        ],
        "properties": {
          "success": {
            "type": "boolean",
            "const": true
          },
          "data": {
            "$ref": "#/components/schemas/UnitsPage"
          },
          "searchesRemaining": {
            "type": "integer",
            "description": "Daily web searches left; -1 for API keys."
          }
        }
      },
      "UnitsPage": {
        "type": "object",
        "required": [
          "refCatastral",
          "totalUnidades",
          "totalUnidadesFinca",
          "unidades",
          "truncated",
          "dataSource",
          "dataDate",
          "attribution"
        ],
        "properties": {
          "refCatastral": {
            "type": "string",
            "description": "ES: the 14-character finca reference. PV/NA: the finca key (municipio-polígono-parcela; Gipuzkoa urban: municipio+Referen); pass it back to list the same finca."
          },
          "direccion": {
            "type": "string"
          },
          "codigoPostal": {
            "type": "string"
          },
          "municipio": {
            "type": "string"
          },
          "provincia": {
            "type": "string"
          },
          "usoGeneral": {
            "type": "string"
          },
          "superficieTotal": {
            "type": "integer",
            "description": "Sum of the unit areas in this page (m²)."
          },
          "anioConstruccion": {
            "type": "integer"
          },
          "participacion": {
            "type": "string",
            "description": "Finca-level coefficient as text; only meaningful for single-unit fincas. Use the per-unit number."
          },
          "totalUnidades": {
            "type": "integer",
            "description": "Units in this page."
          },
          "totalUnidadesFinca": {
            "type": "integer",
            "description": "Units in the whole finca."
          },
          "unidades": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Unit"
            }
          },
          "construcciones": {
            "type": "array",
            "description": "Building elements of a single-property finca.",
            "items": {
              "$ref": "#/components/schemas/Construction"
            }
          },
          "truncated": {
            "type": "boolean",
            "description": "More pages follow."
          },
          "nextCursor": {
            "type": "string",
            "description": "Pass as `cursor` to get the next page."
          },
          "dataSource": {
            "type": "string",
            "enum": [
              "clone",
              "catastro"
            ]
          },
          "dataDate": {
            "type": "string",
            "format": "date",
            "description": "Publication of the source the rows come from (clone; in PV/NA the date of the foral file) or the query date (catastro)."
          },
          "attribution": {
            "type": "string",
            "description": "Mandatory attribution: Dirección General del Catastro (ES), Diputación Foral de Álava / Bizkaia / Gipuzkoa (PV) or Gobierno de Navarra - Registro de la Riqueza Territorial (NA)."
          }
        }
      },
      "Unit": {
        "type": "object",
        "required": [
          "refCatastral",
          "escalera",
          "planta",
          "puerta",
          "uso",
          "superficie",
          "descripcion"
        ],
        "properties": {
          "refCatastral": {
            "type": "string",
            "description": "Unit reference: 20 characters in ES and NA; Número Fijo (Bizkaia), CODETI (Araba) or Referen+N.Fijo+D (Gipuzkoa) in PV."
          },
          "escalera": {
            "type": "string"
          },
          "planta": {
            "type": "string",
            "description": "Floor as the cadastre writes it (01, 00 = ground floor, -1, SM = semi-basement, AT, OD = whole building…)."
          },
          "puerta": {
            "type": "string"
          },
          "uso": {
            "type": "string",
            "examples": [
              "Residencial",
              "Almacén-Estacionamiento",
              "Comercial"
            ]
          },
          "superficie": {
            "type": "integer",
            "description": "Built area of the unit, m²."
          },
          "descripcion": {
            "type": "string"
          },
          "participacion": {
            "type": "number",
            "description": "Participation coefficient in %, full precision. Absent when the source does not have it (always absent in PV and NA)."
          },
          "anio": {
            "type": "integer"
          },
          "direccion": {
            "type": "string"
          }
        }
      },
      "Construction": {
        "type": "object",
        "properties": {
          "escalera": {
            "type": "string"
          },
          "planta": {
            "type": "string"
          },
          "puerta": {
            "type": "string"
          },
          "uso": {
            "type": "string"
          },
          "superficie": {
            "type": "integer"
          },
          "descripcion": {
            "type": "string"
          }
        }
      },
      "ParcelResponse": {
        "type": "object",
        "required": [
          "success",
          "data"
        ],
        "properties": {
          "success": {
            "type": "boolean",
            "const": true
          },
          "data": {
            "$ref": "#/components/schemas/Parcel"
          },
          "searchesRemaining": {
            "type": "integer"
          }
        }
      },
      "Parcel": {
        "type": "object",
        "required": [
          "refCatastral",
          "latitud",
          "longitud",
          "googleMapsUrl"
        ],
        "properties": {
          "dataSource": {
            "type": "string",
            "description": "`local_clone` when it came from our copy."
          },
          "refCatastral": {
            "type": "string"
          },
          "pais": {
            "type": "string"
          },
          "direccion": {
            "type": "string"
          },
          "codigoPostal": {
            "type": "string"
          },
          "municipio": {
            "type": "string"
          },
          "provincia": {
            "type": "string"
          },
          "latitud": {
            "type": "number"
          },
          "longitud": {
            "type": "number"
          },
          "googleMapsUrl": {
            "type": "string"
          },
          "uso": {
            "type": "string"
          },
          "clase": {
            "type": "string"
          },
          "superficieConstruida": {
            "type": "integer",
            "description": "Built area (m²). Same value as `superficie` in the units list."
          },
          "superficieParcela": {
            "type": "integer",
            "description": "Plot area (m²)."
          },
          "anioConstruccion": {
            "type": "integer"
          },
          "coefParticipacion": {
            "type": "string",
            "description": "Coefficient rounded to 2 decimals, as text. Kept for compatibility; use `participacion`."
          },
          "participacion": {
            "type": "number",
            "description": "Participation coefficient in %, full precision (20-character references)."
          },
          "escalera": {
            "type": "string"
          },
          "planta": {
            "type": "string"
          },
          "puerta": {
            "type": "string"
          },
          "viviendas": {
            "type": "integer"
          },
          "plantas": {
            "type": "integer"
          },
          "poligono": {
            "type": "array",
            "items": {
              "type": "array",
              "items": {
                "type": "number"
              },
              "minItems": 2,
              "maxItems": 2
            },
            "description": "Outline as [lat, lng] pairs."
          },
          "availableFields": {
            "type": "object",
            "additionalProperties": {
              "type": "boolean"
            }
          }
        }
      },
      "CoordinatesResponse": {
        "type": "object",
        "required": [
          "success",
          "data"
        ],
        "properties": {
          "success": {
            "type": "boolean",
            "const": true
          },
          "data": {
            "type": "object",
            "properties": {
              "referenciaCatastral": {
                "type": "string"
              },
              "refCat14": {
                "type": "string"
              },
              "direccion": {
                "type": "string"
              },
              "codigoPostal": {
                "type": "string"
              },
              "municipio": {
                "type": "string"
              },
              "tipoInmueble": {
                "type": "string"
              },
              "coordenadas": {
                "type": "object",
                "properties": {
                  "latitud": {
                    "type": "number"
                  },
                  "longitud": {
                    "type": "number"
                  }
                }
              },
              "googleMapsUrl": {
                "type": "string"
              },
              "pais": {
                "type": "string"
              }
            }
          },
          "searchesRemaining": {
            "type": "integer"
          }
        }
      },
      "LegacyAddressResponse": {
        "type": "object",
        "required": [
          "success",
          "data"
        ],
        "properties": {
          "success": {
            "type": "boolean",
            "const": true
          },
          "data": {
            "type": "object",
            "properties": {
              "referenciaCatastral": {
                "type": "string"
              },
              "refCat14": {
                "type": "string"
              },
              "direccion": {
                "type": "string"
              },
              "provincia": {
                "type": "string"
              },
              "municipio": {
                "type": "string"
              },
              "tipoVia": {
                "type": "string"
              },
              "nombreVia": {
                "type": "string"
              },
              "numero": {
                "type": "integer"
              },
              "planta": {
                "type": "string"
              },
              "puerta": {
                "type": "string"
              },
              "codigoPostal": {
                "type": "string"
              }
            }
          },
          "searchesRemaining": {
            "type": "integer"
          }
        }
      },
      "TerrainResponse": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean"
          },
          "data": {
            "$ref": "#/components/schemas/Terrain"
          }
        }
      },
      "Terrain": {
        "type": "object",
        "required": [
          "refcat",
          "country",
          "relief",
          "protected_areas",
          "climate",
          "calculated_at"
        ],
        "properties": {
          "refcat": {
            "type": "string"
          },
          "country": {
            "type": "string"
          },
          "relief": {
            "type": "object",
            "description": "Copernicus DEM GLO-30 cells inside the outline (`sample.method: parcel`); for a parcel smaller than a cell, the cell under its centroid or point.",
            "properties": {
              "status": {
                "type": "string",
                "enum": [
                  "ok",
                  "no_data",
                  "unavailable"
                ],
                "description": "`ok`: the block carries data. `no_data`: there is nothing to measure here (for example no elevation over open sea). `unavailable`: the source could not be read; retry later."
              },
              "elevation_m": {
                "type": "object",
                "properties": {
                  "mean": {
                    "type": "number"
                  },
                  "min": {
                    "type": "number"
                  },
                  "max": {
                    "type": "number"
                  }
                }
              },
              "slope": {
                "type": "object",
                "properties": {
                  "mean_pct": {
                    "type": "number"
                  },
                  "mean_deg": {
                    "type": "number"
                  },
                  "max_pct": {
                    "type": "number"
                  },
                  "class": {
                    "type": "string",
                    "enum": [
                      "flat",
                      "gentle",
                      "moderate",
                      "steep",
                      "very_steep"
                    ]
                  },
                  "max_class": {
                    "type": "string",
                    "enum": [
                      "flat",
                      "gentle",
                      "moderate",
                      "steep",
                      "very_steep"
                    ]
                  },
                  "share_over_10_pct": {
                    "type": "number",
                    "description": "Share of the parcel with a slope above 10 %."
                  },
                  "classes_pct": {
                    "type": "object",
                    "additionalProperties": {
                      "type": "number"
                    }
                  }
                }
              },
              "aspect": {
                "type": "object",
                "properties": {
                  "dominant": {
                    "type": "string",
                    "enum": [
                      "N",
                      "NE",
                      "E",
                      "SE",
                      "S",
                      "SW",
                      "W",
                      "NW",
                      "flat"
                    ]
                  },
                  "dominant_share_pct": {
                    "type": "number"
                  },
                  "mean_deg": {
                    "type": [
                      "number",
                      "null"
                    ]
                  },
                  "flat_share_pct": {
                    "type": "number"
                  },
                  "sectors_pct": {
                    "type": "object",
                    "additionalProperties": {
                      "type": "number"
                    }
                  }
                }
              },
              "sample": {
                "type": "object",
                "properties": {
                  "method": {
                    "type": "string",
                    "enum": [
                      "parcel",
                      "centroid",
                      "point"
                    ]
                  },
                  "cells": {
                    "type": "integer"
                  },
                  "resolution_m": {
                    "type": "number"
                  }
                }
              },
              "source": {
                "$ref": "#/components/schemas/TerrainDataSource"
              }
            }
          },
          "protected_areas": {
            "type": "object",
            "properties": {
              "status": {
                "type": "string",
                "enum": [
                  "ok",
                  "no_data",
                  "unavailable"
                ],
                "description": "`ok`: the block carries data. `no_data`: there is nothing to measure here (for example no elevation over open sea). `unavailable`: the source could not be read; retry later."
              },
              "intersects": {
                "type": "boolean",
                "description": "Some protected site touches the parcel."
              },
              "inside": {
                "type": "boolean",
                "description": "The parcel lies entirely inside a protected site."
              },
              "max_overlap_pct": {
                "type": [
                  "number",
                  "null"
                ]
              },
              "natura2000": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "code": {
                      "type": "string"
                    },
                    "name": {
                      "type": "string"
                    },
                    "type": {
                      "type": "string",
                      "enum": [
                        "SPA",
                        "SCI",
                        "SPA_SCI"
                      ],
                      "description": "Natura 2000 only: Birds Directive (SPA), Habitats Directive (SCI) or both."
                    },
                    "designation": {
                      "type": "string",
                      "description": "National areas only, for example National Park."
                    },
                    "country": {
                      "type": "string"
                    },
                    "overlap_pct": {
                      "type": [
                        "number",
                        "null"
                      ],
                      "description": "Share of the parcel inside the site; null when only the point was checked."
                    }
                  }
                }
              },
              "national": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "code": {
                      "type": "string"
                    },
                    "name": {
                      "type": "string"
                    },
                    "type": {
                      "type": "string",
                      "enum": [
                        "SPA",
                        "SCI",
                        "SPA_SCI"
                      ],
                      "description": "Natura 2000 only: Birds Directive (SPA), Habitats Directive (SCI) or both."
                    },
                    "designation": {
                      "type": "string",
                      "description": "National areas only, for example National Park."
                    },
                    "country": {
                      "type": "string"
                    },
                    "overlap_pct": {
                      "type": [
                        "number",
                        "null"
                      ],
                      "description": "Share of the parcel inside the site; null when only the point was checked."
                    }
                  }
                }
              },
              "method": {
                "type": "string",
                "enum": [
                  "parcel",
                  "point"
                ]
              },
              "sources": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/TerrainDataSource"
                }
              }
            }
          },
          "climate": {
            "type": "object",
            "description": "ERA5-Land monthly means over the 0.1° cell of the parcel point.",
            "properties": {
              "status": {
                "type": "string",
                "enum": [
                  "ok",
                  "no_data",
                  "unavailable"
                ],
                "description": "`ok`: the block carries data. `no_data`: there is nothing to measure here (for example no elevation over open sea). `unavailable`: the source could not be read; retry later."
              },
              "baseline": {
                "type": "object",
                "properties": {
                  "start_year": {
                    "type": "integer"
                  },
                  "end_year": {
                    "type": "integer"
                  },
                  "mean_temp_c": {
                    "type": "number"
                  },
                  "annual_precip_mm": {
                    "type": "number"
                  },
                  "frost_days_per_year": {
                    "type": "number"
                  },
                  "hot_days_per_year": {
                    "type": "number"
                  }
                }
              },
              "recent": {
                "type": "object",
                "properties": {
                  "start_year": {
                    "type": "integer"
                  },
                  "end_year": {
                    "type": "integer"
                  },
                  "mean_temp_c": {
                    "type": "number"
                  },
                  "annual_precip_mm": {
                    "type": "number"
                  },
                  "frost_days_per_year": {
                    "type": "number"
                  },
                  "hot_days_per_year": {
                    "type": "number"
                  }
                }
              },
              "change": {
                "type": "object",
                "properties": {
                  "mean_temp_c": {
                    "type": "number"
                  },
                  "annual_precip_mm": {
                    "type": "number"
                  },
                  "annual_precip_pct": {
                    "type": "number"
                  },
                  "frost_days_per_year": {
                    "type": "number"
                  },
                  "hot_days_per_year": {
                    "type": "number"
                  }
                }
              },
              "frost_threshold_c": {
                "type": "integer"
              },
              "hot_threshold_c": {
                "type": "integer"
              },
              "cell": {
                "type": "object",
                "properties": {
                  "lat": {
                    "type": "number"
                  },
                  "lng": {
                    "type": "number"
                  },
                  "resolution_deg": {
                    "type": "number"
                  }
                }
              },
              "source": {
                "$ref": "#/components/schemas/TerrainDataSource"
              }
            }
          },
          "calculated_at": {
            "type": "string",
            "format": "date-time"
          },
          "provenance": {
            "type": "string"
          }
        }
      },
      "TerrainDataSource": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string"
          },
          "provider": {
            "type": "string"
          },
          "license": {
            "type": "string"
          },
          "attribution": {
            "type": "string",
            "description": "Show it next to the data."
          },
          "url": {
            "type": "string"
          },
          "resolution": {
            "type": "string"
          },
          "edition": {
            "type": "string"
          }
        }
      },
      "GroundMotionResponse": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean"
          },
          "data": {
            "$ref": "#/components/schemas/GroundMotion"
          }
        }
      },
      "GroundMotion": {
        "type": "object",
        "description": "Ground motion of the parcel measured by satellite radar (Sentinel-1 InSAR), from the Copernicus European Ground Motion Service (EGMS) L3 Ortho product, 100 m grid, 2020-2024. Velocities are the mean over the 100 m cells whose centre falls inside the parcel outline; when no centre does (parcels under ~1 ha) or there is no outline, the 3 x 3 cells around the parcel point are used and `basis` says `surroundings`. Negative vertical velocity = the ground sinks. Fields with no measurement are left out instead of estimated.",
        "required": [
          "refcat",
          "country",
          "status",
          "period",
          "source",
          "calculated_at"
        ],
        "properties": {
          "refcat": {
            "type": "string"
          },
          "country": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "ok",
              "no_data",
              "unavailable"
            ],
            "description": "`no_data`: there is no measurement for this parcel (see `reason`). `unavailable`: our copy of the data could not be read; retry later."
          },
          "reason": {
            "type": "string",
            "enum": [
              "no_reflectors",
              "outside_coverage",
              "parcel_too_large"
            ],
            "description": "Only with `no_data`. `no_reflectors`: the satellite found no stable reflectors here (fields, forest, water, snow); typical outside towns. `outside_coverage`: the location is outside EGMS coverage (EEA-39). `parcel_too_large`: the outline spans more than 2,500 km2."
          },
          "period": {
            "type": "object",
            "properties": {
              "from": {
                "type": "string",
                "example": "2020-01"
              },
              "to": {
                "type": "string",
                "example": "2024-12"
              },
              "label": {
                "type": "string",
                "example": "2020-2024"
              }
            }
          },
          "ground_motion": {
            "type": "object",
            "properties": {
              "class": {
                "type": "string",
                "enum": [
                  "severe_subsidence",
                  "notable_subsidence",
                  "slow_subsidence",
                  "stable",
                  "slow_uplift",
                  "notable_uplift"
                ],
                "description": "From the mean vertical velocity v (mm/year): v <= -10 severe_subsidence; -10 < v <= -5 notable_subsidence; -5 < v <= -2 slow_subsidence; -2 < v < 2 stable; 2 <= v < 5 slow_uplift; v >= 5 notable_uplift."
              },
              "worst_class": {
                "type": "string",
                "description": "Same scale applied to the fastest-sinking cell."
              },
              "vertical": {
                "type": "object",
                "properties": {
                  "mean_mm_year": {
                    "type": "number"
                  },
                  "max_subsidence_mm_year": {
                    "type": "number"
                  },
                  "max_uplift_mm_year": {
                    "type": "number"
                  },
                  "std_mm_year": {
                    "type": "number"
                  },
                  "acceleration_mm_year2": {
                    "type": "number"
                  },
                  "rmse_mm": {
                    "type": "number"
                  }
                }
              },
              "east_west": {
                "type": "object",
                "description": "Positive = moving east.",
                "properties": {
                  "mean_mm_year": {
                    "type": "number"
                  },
                  "std_mm_year": {
                    "type": "number"
                  }
                }
              },
              "yearly_displacement": {
                "type": "array",
                "description": "Mean vertical displacement of each year relative to January 2020, in mm.",
                "items": {
                  "type": "object",
                  "properties": {
                    "year": {
                      "type": "integer"
                    },
                    "mm": {
                      "type": "number"
                    }
                  }
                }
              },
              "cells_with_data": {
                "type": "integer"
              },
              "cells_considered": {
                "type": "integer"
              },
              "coverage_pct": {
                "type": "number"
              },
              "basis": {
                "type": "string",
                "enum": [
                  "parcel",
                  "surroundings"
                ]
              },
              "cell_size_m": {
                "type": "integer",
                "example": 100
              }
            }
          },
          "source": {
            "type": "object",
            "description": "Name, provider, licence and the attribution that must be shown with the data.",
            "properties": {
              "name": {
                "type": "string"
              },
              "provider": {
                "type": "string"
              },
              "license": {
                "type": "string"
              },
              "attribution": {
                "type": "string"
              },
              "url": {
                "type": "string"
              },
              "resolution": {
                "type": "string"
              },
              "edition": {
                "type": "string"
              }
            }
          },
          "calculated_at": {
            "type": "string",
            "format": "date-time"
          },
          "provenance": {
            "type": "string"
          }
        }
      }
    }
  }
}
