catastrogps 1.1.0 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,11 +1,14 @@
1
1
  # catastrogps
2
2
 
3
- Official JavaScript and TypeScript client for the [Catastro GPS API](https://www.catastrogps.es/developers): cadastral parcels in **29 European countries plus the Basque Country and Navarre** (31 country and region codes) with one API key.
3
+ Official JavaScript and TypeScript client for the [Catastro GPS API](https://www.catastrogps.es/developers): cadastral parcels from **26 European cadastres plus the foral cadastres of the Basque Country and Navarre** with one API key.
4
4
 
5
5
  - Look up a parcel by its **official cadastral reference** or by **coordinates**, with the country detected for you.
6
- - Turn a **Spanish postal address in free text** into a cadastral reference.
6
+ - Turn a **postal address into parcels** in Spain and 26 more countries, ranked by confidence.
7
+ - Import **every unit of a Spanish building** (dwellings, shops, garages) with paging and free `304` refreshes.
7
8
  - Get the **parcel outline** (GeoJSON or a `[lat, lng]` ring), and **KML / GPX / DXF** exports.
8
- - **Solar** (PVGIS) and **agricultural** context for parcels in Spain, Portugal, France, Italy and Germany.
9
+ - **Relief, Natura 2000 and climate** (Copernicus DEM, EEA, ERA5-Land) and **ground motion** (Copernicus EGMS, mm/year) for any covered country.
10
+ - **Solar**, **agriculture**, **market**, **score**, **value history** and **comparison** for Spain, Portugal, France, Italy and Germany.
11
+ - Quota, prepaid balance and per-minute limit of every response, typed errors for every API code.
9
12
  - Zero runtime dependencies. Node.js 18+, Deno, Bun and edge runtimes with `fetch`. ESM and CommonJS, fully typed.
10
13
 
11
14
  **Free tier: 250 calls a month, forever. Failed lookups are not charged.** Get a key at [catastrogps.es/developers](https://www.catastrogps.es/developers).
@@ -29,72 +32,106 @@ console.log(parcel.municipio, parcel.superficieParcela, parcel.latitud, parcel.l
29
32
 
30
33
  `new CatastroGPS()` with no arguments reads `CATASTROGPS_API_KEY` from the environment.
31
34
 
35
+ ## Methods
36
+
37
+ | Method | Endpoint | Countries |
38
+ |--------|----------|-----------|
39
+ | `parcels.get(ref, { country })` | `GET /api/catastro/{ref}` | All references (see coverage) |
40
+ | `parcels.atPoint({ lat, lng, country })` | `GET /api/search/coordinates` | All, including HR, SE and UK (Scotland) |
41
+ | `searchAddressCandidates(q \| { q, street, number, municipality, postcode, country, limit })` | `GET /api/search/address/candidates` | Spain (with Basque Country and Navarre) and 26 more; not SE or HR |
42
+ | `parcels.findByAddress(text)` | `POST /api/search/address/parse` | Spain, central Catastro, live (prefer the candidates search) |
43
+ | `getUnits(ref14, { country, previous })`, `iterUnitPages` | `GET /api/catastro/{ref14}/units` | `ES`, `PV`, `NA` |
44
+ | `parcels.geometry(ref, { country })` | `GET /api/catastro/{ref}/polygon` | All but UK |
45
+ | `parcels.terrain(ref, { country, lat, lng })` | `GET /api/catastro/{ref}/terrain` | All; `lat`/`lng` required outside ES, PV, NA, PT, FR, IT, DE |
46
+ | `parcels.groundMotion(ref, { country, lat, lng })` | `GET /api/catastro/{ref}/ground-motion` | Same as terrain, inside EGMS coverage |
47
+ | `parcels.solar`, `parcels.agriculture`, `parcels.score` | `/solar`, `/agro`, `/score` | ES, PV, NA, PT, FR, IT, DE |
48
+ | `parcels.market(ref, { country })` | `/market` | Figures in FR, IT and DE (NRW); a note without figures elsewhere |
49
+ | `parcels.valueHistory(ref, { country })` | `/value-history` | ES, PV, NA, PT, FR, IT, DE, AT |
50
+ | `parcels.compare([{ reference, country }, ...])` | `POST /api/catastro/compare` | 2 or 3 parcels in ES, PT, FR, IT, DE |
51
+ | `export.file(ref, 'kml' \| 'gpx' \| 'dxf', { country })` | `GET /api/export/{format}` | Where a geometry exists |
52
+ | `resolve(text, { hint })` | `GET /api/resolve` | Free, no quota: which country and kind a text is |
53
+
32
54
  ## Examples
33
55
 
34
56
  ```ts
35
- const fromAddress = await client.parcels.findByAddress('Calle Mallorca 213, Barcelona');
36
- fromAddress.referenciaCatastral;
37
-
38
57
  const inWarsaw = await client.parcels.atPoint({ lat: 52.2297, lng: 21.0122 });
39
58
  inWarsaw.referenciaCatastral;
40
59
  inWarsaw.pais;
41
60
 
42
- const foral = await client.parcels.get('<Navarre reference>', { country: 'NA' });
61
+ const { candidatos } = await client.searchAddressCandidates({ q: 'Damrak 1, 1012 LG Amsterdam', country: 'NL' });
62
+ candidatos[0].refCatastral;
63
+ candidatos[0].confianza;
64
+
65
+ const terrain = await client.parcels.terrain('10194A00110004');
66
+ terrain.relief.slope?.class;
67
+ terrain.protected_areas.natura2000;
68
+ terrain.climate?.baseline;
43
69
 
44
- const outline = await client.parcels.geometry('9872023VH5797S', { country: 'ES' });
45
- outline.geojson;
70
+ const brussels = await client.parcels.terrain('21004C0123/00', { country: 'BE', lat: 50.848139, lng: 4.353613 });
46
71
 
47
- const solar = await client.parcels.solar('9872023VH5797S0001WX');
48
- solar.kwh_year;
72
+ const motion = await client.parcels.groundMotion('0745901TG4304N0002KH');
73
+ motion.status;
74
+ motion.ground_motion?.vertical.mean_mm_year;
75
+
76
+ const comparison = await client.parcels.compare([
77
+ { reference: '9872023VH5797S0001WX', country: 'ES' },
78
+ { reference: '750560000AB0001', country: 'FR' },
79
+ ]);
49
80
 
50
81
  const kml = await client.export.file('9872023VH5797S0001WX', 'kml');
51
82
 
52
83
  const guess = await client.resolve('05102200100005');
53
84
  guess.candidates;
54
-
55
- client.lastQuota;
56
85
  ```
57
86
 
58
- `client.lastQuota` is the monthly quota of your plan as of the last response: `{ plan, limit, remaining, resetsAt }`, read from the `X-Quota-Tier`, `X-Quota-Limit`, `X-Quota-Remaining` and `X-Quota-Reset` headers. The `X-RateLimit-*` headers are a different thing: a per-key burst limit per minute that depends on your plan (Free 10, Developer 60, Startup 120, Growth 300; a global per-IP guard also applies) that the client handles by retrying.
87
+ `terrain` and `groundMotion` carry a `source.attribution` string that must be shown next to the data. A ground motion answer with `status: 'no_data'` and `reason: 'no_reflectors'` means the satellite had nothing stable to measure (fields, forest, water): there is no figure, not a zero.
59
88
 
60
- Responses are the API's `data` object, with the field names the API uses (`refCatastral`, `municipio`, `superficieParcela`…). See the [API reference](https://www.catastrogps.es/developers).
89
+ Responses are the API's `data` object, with the field names the API uses (`refCatastral`, `municipio`, `superficieParcela`…). See the [API reference](https://www.catastrogps.es/developers) and the OpenAPI spec at `https://api.parcelgps.com/api/openapi.json`.
61
90
 
62
- ## Importar una comunidad de propietarios (Spain)
91
+ ## Import a building (comunidad de propietarios, Spain)
63
92
 
64
- Address → finca (14-character reference) → every unit, with use, area, participation coefficient, stair, floor and door.
93
+ Address, then finca (14-character reference), then every unit with use, area, participation coefficient, stair, floor and door.
65
94
 
66
95
  ```ts
67
96
  const { candidatos } = await client.searchAddressCandidates('Avenida José Rodríguez de la Borbolla Camoyán 10, Dos Hermanas');
68
97
  const finca = candidatos[0];
69
- finca.refCatastral;
70
- finca.confianza;
71
- finca.pais;
72
98
 
73
- const comunidad = await client.getUnits(finca.refCatastral);
99
+ const comunidad = await client.getUnits(finca.refCatastral, { country: finca.pais as 'ES' | 'PV' | 'NA' });
74
100
  comunidad.totalUnidadesFinca;
75
101
  for (const u of comunidad.unidades) {
76
102
  console.log(u.refCatastral, u.uso, u.superficie, u.participacion, u.escalera, u.planta, u.puerta);
77
103
  }
78
104
  comunidad.dataSource;
79
- comunidad.dataDate;
80
105
  comunidad.attribution;
81
106
 
82
107
  const refreshed = await client.getUnits(finca.refCatastral, { previous: comunidad });
83
108
  refreshed.changed;
84
109
  ```
85
110
 
86
- - `searchAddressCandidates` also takes `{ street, number, municipality, postcode, limit }`. Candidates come ranked by `confianza` (0.75 or more: number and municipality match). It costs 1 quota unit.
87
- - `getUnits` follows `nextCursor` for you (200 units per page) and costs one quota unit per 50 units, minimum one per page. `iterUnitPages(ref)` yields page by page.
88
- - Pass the previous result as `previous` to re-import: pages that did not change come back as `304 Not Modified`, cost nothing, and are reused; `changed` tells you if anything moved.
89
- - Fincas in the Basque Country or Navarra (`pais: 'PV' | 'NA'`) throw `CoverageError`: their foral cadastres are not served per finca.
90
- - A `ServiceUnavailableError` carries `retryAfterSeconds`; the client already waits for it (up to 60 s) before its retries.
111
+ - `getUnits` follows `nextCursor` for you (up to 200 units per page). `iterUnitPages(ref)` yields page by page.
112
+ - **Cost: one quota unit per unit served** in each page, minimum one per page; a page is cut to the quota you have left. Pass the previous result as `previous` to re-import: unchanged pages come back as `304 Not Modified`, cost nothing and are reused; `changed` tells you if anything moved.
113
+ - Basque Country and Navarre (`country: 'PV' | 'NA'`) are served from our copy of each foral cadastre: pass the foral reference of any unit or the finca key in `refCatastral`. The foral open data carry no participation coefficient.
114
+ - Organisations with a per-finca cap agreed by contract (Startup and Growth) pay at most that cap per finca and period: see `client.lastQuota.fincaCap` (`{ cap, used }`).
115
+
116
+ ## Quota, prepaid balance and limits
117
+
118
+ `client.lastQuota` is read from the headers of the last response; `conditionalRequest` also returns the `quota` of that exact response.
119
+
120
+ | Field | Header | Meaning |
121
+ |-------|--------|---------|
122
+ | `plan`, `limit`, `remaining`, `resetsAt` | `X-Quota-Tier`, `X-Quota-Limit`, `X-Quota-Remaining`, `X-Quota-Reset` | Monthly quota of your plan, after this response |
123
+ | `overage.balance`, `overage.unitPrice`, `overage.remainingUnits` | `X-Quota-Overage`, `X-Quota-Balance`, `X-Quota-Overage-Unit-Price`, `X-Quota-Overage-Remaining` | Prepaid pay-as-you-go balance in euros, used once the monthly quota is spent |
124
+ | `rateLimit.limit`, `rateLimit.remaining`, `rateLimit.resetSeconds` | `X-RateLimit-*` | Per-minute burst limit of your key (Free 10, Developer 60, Startup 120, Growth 300) |
125
+ | `fincaCap.cap`, `fincaCap.used` | `X-Quota-Finca-Cap`, `X-Quota-Finca-Cap-Used` | Only on `/units`, only with a contract cap |
126
+
127
+ When the monthly quota is spent and there is no prepaid balance left, the API answers `429 KEY_AUTH_004` (never `402`): the client throws `QuotaExceededError` with the `quota` of that response, and `prepaidBalanceEmpty` is true when your organisation has the prepaid overage on (top up at `https://parcelgps.com/app/developer`). Only 2xx responses spend quota; `300`, `304`, `4xx` and `5xx` are free, and so are 2xx answers without data.
91
128
 
92
129
  ## Errors
93
130
 
94
131
  Every error is a `CatastroGPSError` with `status`, `code` and `details`. Subclasses let you branch cleanly:
95
132
 
96
133
  ```ts
97
- import { AmbiguousReferenceError, CoverageError, NotFoundError, QuotaExceededError } from 'catastrogps';
134
+ import { AmbiguousReferenceError, CoverageError, NotFoundError, PlaceNameError, QuotaExceededError } from 'catastrogps';
98
135
 
99
136
  try {
100
137
  await client.parcels.get('05102200100005');
@@ -102,57 +139,79 @@ try {
102
139
  if (error instanceof AmbiguousReferenceError) {
103
140
  const [first] = error.candidates;
104
141
  await client.parcels.get('05102200100005', { country: first.country as 'DE' });
105
- } else if (error instanceof NotFoundError || error instanceof CoverageError) {
142
+ } else if (error instanceof PlaceNameError) {
143
+ console.log('A place name, not a reference', error.location);
144
+ } else if (error instanceof CoverageError) {
145
+ console.log(error.country, error.feature, error.supportedCountries);
146
+ } else if (error instanceof NotFoundError) {
106
147
  console.log(error.message);
107
148
  } else if (error instanceof QuotaExceededError) {
108
- console.log('Monthly quota used up');
149
+ console.log('Quota spent', error.quota?.resetsAt, error.prepaidBalanceEmpty);
109
150
  } else {
110
151
  throw error;
111
152
  }
112
153
  }
113
154
  ```
114
155
 
115
- Also available: `AuthenticationError`, `ValidationError`, `RateLimitError`, `ServiceUnavailableError`, `ServerError`, `TimeoutError`, `NetworkError`.
116
-
117
- Timeouts, network errors, 429 rate limits and 502/503/504 are retried up to `maxRetries` times (default 2) with exponential backoff. An exhausted monthly quota is never retried. Only 2xx responses spend quota; failed attempts and `304 Not Modified` are free.
156
+ | Class | API code / status |
157
+ |-------|-------------------|
158
+ | `AmbiguousReferenceError` | `300 CNV_AMBIGUOUS`: bare digits of several countries; `candidates` lists them |
159
+ | `CoverageError` | `422 CNV_COVERAGE`: country not covered, or an analysis outside its countries |
160
+ | `PlaceNameError` (a `ValidationError`) | `422 CNV_PLACE_NAME`: a place name, with the geocoded `location` when found |
161
+ | `ValidationError` | `400 VALIDATION_ERROR`, other `422` |
162
+ | `AuthenticationError` / `ForbiddenError` | `401 KEY_AUTH_001..003`, `403` |
163
+ | `NotFoundError` | `404 NOT_FOUND` |
164
+ | `QuotaExceededError` | `429 KEY_AUTH_004` |
165
+ | `RateLimitError` | `429 KEY_RATE_002`, `RATE_LIMIT_EXCEEDED`; `retryAfterSeconds` |
166
+ | `ServiceUnavailableError` | `503 SERVICE_UNAVAILABLE`; `retryAfterSeconds` |
167
+ | `ServerError`, `TimeoutError`, `NetworkError` | `5xx`, client timeout, network failure |
168
+
169
+ Timeouts, network errors, per-minute 429s and 502/503/504 are retried up to `maxRetries` times (default 2) with exponential backoff, waiting `Retry-After` when the API sends it (up to 60 s). An exhausted monthly quota is never retried.
118
170
 
119
171
  ## Options
120
172
 
121
173
  | Option | Default | |
122
174
  |--------|---------|---|
123
175
  | `apiKey` | `process.env.CATASTROGPS_API_KEY` | Required |
124
- | `baseUrl` | `https://api.catastrogps.es` | |
176
+ | `baseUrl` | `https://api.catastrogps.es` | `https://api.parcelgps.com` is the same API |
125
177
  | `timeoutMs` | `30000` | Official cadastres can be slow |
126
178
  | `maxRetries` | `2` | |
127
179
  | `fetch` | `globalThis.fetch` | Inject your own for tests or proxies |
128
180
 
129
181
  ## Coverage
130
182
 
131
- | Code | Country / region | Reference | Coordinates | Notes |
132
- |------|------------------|:---:|:---:|-------|
133
- | `ES` | Spain | ✅ | ✅ | Free-text address search |
134
- | `PV` · `NA` | Basque Country · Navarre | ✅ | ✅ | Foral cadastres |
135
- | `PT` | Portugal | Partial | ✅ | Digital cadastre is partial |
136
- | `FR` · `IT` | France · Italy | ✅ | ✅ | |
137
- | `DE` | Germany | Partial | Partial | All Länder except Bavaria |
138
- | `AT` `CH` `LI` `BE` `NL` `LU` | Austria, Switzerland, Liechtenstein, Belgium, Netherlands, Luxembourg | ✅ | ✅ | |
139
- | `PL` `CZ` `SK` `SI` `HR` `BG` `GR` `CY` | Poland, Czechia, Slovakia, Slovenia, Croatia, Bulgaria, Greece, Cyprus | ✅ | ✅ | |
140
- | `DK` `NO` `FI` `IS` `EE` `LV` `LT` `IE` | Denmark, Norway, Finland, Iceland, Estonia, Latvia, Lithuania, Ireland | ✅ | ✅ | |
141
- | `SE` | Sweden | ✅ | ✅ | Agricultural blocks, not property units |
142
- | `UK` | United Kingdom | — | Scotland | England, Wales and Northern Ireland not yet |
143
-
144
- Geometry is available wherever a reference works. Solar and agriculture: `ES`, `PV`, `NA`, `PT`, `FR`, `IT`, `DE`. Data comes live from each official source, so availability follows theirs.
183
+ Measured against production on 1 October 2026. 26 European cadastres plus the Basque Country and Navarre; Croatia, Sweden and the United Kingdom are partial sources, listed for honesty.
184
+
185
+ | Code | Country / region | Reference | Coordinates | Address | Notes |
186
+ |------|------------------|:---:|:---:|:---:|-------|
187
+ | `ES` | Spain | Yes | Yes | Yes | Units per building |
188
+ | `PV` · `NA` | Basque Country · Navarre | Yes | Yes | With `country: 'ES'` | Foral cadastres; units per building |
189
+ | `FR` · `IT` | France · Italy | Yes | Yes | Yes | |
190
+ | `DE` | Germany | Partial | Partial | Partial | 15 of 16 Länder: **no Bavaria** |
191
+ | `PT` | Portugal | Yes | Partial | Partial | The cadastre does not cover Lisbon, Porto or Coimbra |
192
+ | `AT` `NL` `BE` `PL` `CZ` `DK` `NO` `FI` `EE` | Austria, Netherlands, Belgium, Poland, Czechia, Denmark, Norway, Finland, Estonia | Yes | Yes | Yes | Belgium is slow (3-15 s) |
193
+ | `CH` | Switzerland | Yes | Partial | Yes | Not in cantons that publish no parcels (e.g. Vaud) |
194
+ | `LT` `SI` `SK` `BG` `LU` `LI` `IS` `CY` | Lithuania, Slovenia, Slovakia, Bulgaria, Luxembourg, Liechtenstein, Iceland, Cyprus | Yes | Yes | Yes | |
195
+ | `GR` · `LV` | Greece · Latvia | With the country set | Yes | Yes | |
196
+ | `IE` | Ireland | With `country: 'IE'` | Partial | Partial | Numeric SP_ID |
197
+ | `SE` | Sweden | Agricultural blocks | Agricultural blocks | No | Not property units |
198
+ | `HR` | Croatia | No | ARKOD only | No | Agricultural parcels of the Paying Agency, not the cadastre |
199
+ | `UK` | United Kingdom | No | Scotland | Scotland | |
200
+
201
+ Not covered: Hungary, Romania and the rest (`CoverageError`). Terrain and ground motion work wherever a parcel outline exists, with `lat`/`lng` outside the seven analysis countries. Data comes from each official source, so availability follows theirs.
145
202
 
146
203
  ## Pricing
147
204
 
148
- | Plan | Price | Calls / month |
149
- |------|-------|---------------|
150
- | Free | €0, forever | 100 |
151
- | Developer | €19 / month | 5,000 |
152
- | Startup | €49 / month | 15,000 |
153
- | Growth | €99 / month | 50,000 |
205
+ | Plan | Price | Calls / month | Prepaid overage per 1,000 |
206
+ |------|-------|---------------|---------------------------|
207
+ | Free | €0, forever | 250 | €10 |
208
+ | Developer | €19 / month | 5,000 | €5 |
209
+ | Startup | €49 / month | 15,000 | €4 |
210
+ | Growth | €99 / month | 50,000 | €2.50 |
211
+
212
+ Overage prices are net (VAT apart) and are charged from a prepaid balance you top up in the portal; with the balance at zero the API answers `429`, never debt.
154
213
 
155
- The same key works with the Python SDK (`pip install catastrogps`) and the MCP server for AI agents ([`catastro-gps-mcp`](https://www.npmjs.com/package/catastro-gps-mcp)).
214
+ The same key works with the Python SDK (`pip install catastrogps`), the Go SDK and the MCP server for AI agents ([`catastro-gps-mcp`](https://www.npmjs.com/package/catastro-gps-mcp)).
156
215
 
157
216
  ## License
158
217
 
package/dist/index.d.mts CHANGED
@@ -14,11 +14,33 @@ interface CatastroGPSOptions {
14
14
  interface CountryOption<C extends string = CountryCode> {
15
15
  country?: C;
16
16
  }
17
+ declare const ADDRESS_COUNTRY_CODES: readonly ["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"];
18
+ type AddressCountryCode = (typeof ADDRESS_COUNTRY_CODES)[number];
19
+ declare const UNITS_COUNTRY_CODES: readonly ["ES", "PV", "NA"];
20
+ type UnitsCountryCode = (typeof UNITS_COUNTRY_CODES)[number];
21
+ interface PrepaidOverage {
22
+ enabled: boolean;
23
+ balance?: number;
24
+ unitPrice?: number;
25
+ remainingUnits?: number;
26
+ }
27
+ interface BurstLimit {
28
+ limit?: number;
29
+ remaining?: number;
30
+ resetSeconds?: number;
31
+ }
32
+ interface FincaCap {
33
+ cap?: number;
34
+ used?: number;
35
+ }
17
36
  interface Quota {
18
37
  plan?: string;
19
38
  limit?: number;
20
39
  remaining?: number;
21
40
  resetsAt?: string;
41
+ overage?: PrepaidOverage;
42
+ rateLimit?: BurstLimit;
43
+ fincaCap?: FincaCap;
22
44
  }
23
45
  interface Parcel {
24
46
  refCatastral: string;
@@ -119,6 +141,7 @@ interface ResolveResult {
119
141
  }
120
142
  interface AddressCandidatesQuery {
121
143
  q?: string;
144
+ country?: AddressCountryCode;
122
145
  street?: string;
123
146
  number?: number;
124
147
  municipality?: string;
@@ -219,8 +242,130 @@ interface UnitsResult {
219
242
  pages: UnitsPage[];
220
243
  }
221
244
  interface GetUnitsOptions {
245
+ country?: UnitsCountryCode;
222
246
  previous?: UnitsResult;
223
247
  }
248
+ interface LocatedOptions extends CountryOption<Exclude<CountryCode, 'UK' | 'HR'>> {
249
+ lat?: number;
250
+ lng?: number;
251
+ }
252
+ interface DataSource {
253
+ name?: string;
254
+ provider?: string;
255
+ license?: string;
256
+ attribution?: string;
257
+ url?: string;
258
+ resolution?: string;
259
+ edition?: string;
260
+ }
261
+ type BlockStatus = 'ok' | 'no_data' | 'unavailable';
262
+ interface ProtectedSite {
263
+ code: string;
264
+ name: string;
265
+ type?: 'SPA' | 'SCI' | 'SPA_SCI' | string;
266
+ designation?: string;
267
+ country?: string;
268
+ overlap_pct?: number | null;
269
+ }
270
+ interface Terrain {
271
+ refcat: string;
272
+ country: string;
273
+ relief: {
274
+ status: BlockStatus;
275
+ elevation_m?: {
276
+ mean: number;
277
+ min: number;
278
+ max: number;
279
+ };
280
+ slope?: {
281
+ mean_pct: number;
282
+ mean_deg: number;
283
+ max_pct: number;
284
+ class: string;
285
+ max_class: string;
286
+ share_over_10_pct: number;
287
+ classes_pct: Record<string, number>;
288
+ };
289
+ aspect?: {
290
+ dominant: string;
291
+ dominant_share_pct: number;
292
+ mean_deg: number | null;
293
+ flat_share_pct: number;
294
+ sectors_pct: Record<string, number>;
295
+ };
296
+ sample?: {
297
+ method: string;
298
+ cells: number;
299
+ resolution_m: number;
300
+ };
301
+ source?: DataSource;
302
+ };
303
+ protected_areas: {
304
+ status: BlockStatus;
305
+ intersects?: boolean;
306
+ inside?: boolean;
307
+ max_overlap_pct?: number | null;
308
+ natura2000?: ProtectedSite[];
309
+ national?: ProtectedSite[];
310
+ method?: string;
311
+ sources?: DataSource[];
312
+ };
313
+ climate?: {
314
+ status: BlockStatus;
315
+ baseline?: Record<string, number>;
316
+ recent?: Record<string, number>;
317
+ [key: string]: unknown;
318
+ };
319
+ calculated_at?: string;
320
+ provenance?: string;
321
+ }
322
+ interface GroundMotion {
323
+ refcat: string;
324
+ country: string;
325
+ status: BlockStatus;
326
+ reason?: 'no_reflectors' | 'outside_coverage' | 'parcel_too_large' | string;
327
+ period?: {
328
+ from: string;
329
+ to: string;
330
+ label: string;
331
+ };
332
+ ground_motion?: {
333
+ class: string;
334
+ worst_class?: string;
335
+ vertical: {
336
+ mean_mm_year: number;
337
+ max_subsidence_mm_year?: number;
338
+ max_uplift_mm_year?: number;
339
+ std_mm_year?: number;
340
+ acceleration_mm_year2?: number;
341
+ rmse_mm?: number;
342
+ };
343
+ east_west?: {
344
+ mean_mm_year: number;
345
+ std_mm_year?: number;
346
+ };
347
+ yearly_displacement?: Array<{
348
+ year: number;
349
+ mm: number;
350
+ }>;
351
+ cells_with_data: number;
352
+ cells_considered: number;
353
+ coverage_pct: number;
354
+ basis?: 'parcel' | 'surroundings' | string;
355
+ cell_size_m?: number;
356
+ };
357
+ source?: DataSource;
358
+ calculated_at?: string;
359
+ provenance?: string;
360
+ }
361
+ type MarketData = Record<string, unknown>;
362
+ type ScoreData = Record<string, unknown>;
363
+ type ValueHistory = Record<string, unknown>;
364
+ type Comparison = Record<string, unknown>;
365
+ interface CompareItem {
366
+ reference: string;
367
+ country: EnrichmentCountryCode;
368
+ }
224
369
 
225
370
  declare class ExportResource {
226
371
  private readonly client;
@@ -249,6 +394,12 @@ declare class ParcelsResource {
249
394
  geometry(reference: string, options?: CountryOption<Exclude<CountryCode, 'UK'>>): Promise<ParcelGeometry>;
250
395
  solar(reference: string, options?: CountryOption<EnrichmentCountryCode>): Promise<SolarEstimate>;
251
396
  agriculture(reference: string, options?: CountryOption<EnrichmentCountryCode>): Promise<AgricultureData>;
397
+ terrain(reference: string, options?: LocatedOptions): Promise<Terrain>;
398
+ groundMotion(reference: string, options?: LocatedOptions): Promise<GroundMotion>;
399
+ market(reference: string, options?: CountryOption<EnrichmentCountryCode>): Promise<MarketData>;
400
+ score(reference: string, options?: CountryOption<EnrichmentCountryCode>): Promise<ScoreData>;
401
+ valueHistory(reference: string, options?: CountryOption<EnrichmentCountryCode | 'AT'>): Promise<ValueHistory>;
402
+ compare(parcels: CompareItem[]): Promise<Comparison>;
252
403
  }
253
404
 
254
405
  declare const DEFAULT_BASE_URL = "https://api.catastrogps.es";
@@ -265,6 +416,7 @@ interface ConditionalResponse<T> {
265
416
  data?: T;
266
417
  etag?: string;
267
418
  notModified: boolean;
419
+ quota?: Quota;
268
420
  }
269
421
  declare class CatastroGPS {
270
422
  readonly parcels: ParcelsResource;
@@ -291,8 +443,9 @@ declare class CatastroGPS {
291
443
  private retryDelayMs;
292
444
  private captureQuota;
293
445
  }
446
+ declare function readQuota(headers: Headers): Quota | undefined;
294
447
 
295
- declare const VERSION = "1.1.0";
448
+ declare const VERSION = "1.2.0";
296
449
 
297
450
  declare class CatastroGPSError extends Error {
298
451
  readonly status?: number;
@@ -318,8 +471,20 @@ declare class NotFoundError extends CatastroGPSError {
318
471
  declare class ValidationError extends CatastroGPSError {
319
472
  name: string;
320
473
  }
474
+ declare class PlaceNameError extends ValidationError {
475
+ name: string;
476
+ get location(): {
477
+ lat: number;
478
+ lng: number;
479
+ address?: string;
480
+ label?: string;
481
+ } | undefined;
482
+ }
321
483
  declare class CoverageError extends CatastroGPSError {
322
484
  name: string;
485
+ get country(): string | undefined;
486
+ get feature(): string | undefined;
487
+ get supportedCountries(): string[];
323
488
  }
324
489
  declare class AmbiguousReferenceError extends CatastroGPSError {
325
490
  name: string;
@@ -331,6 +496,8 @@ declare class AmbiguousReferenceError extends CatastroGPSError {
331
496
  }
332
497
  declare class QuotaExceededError extends CatastroGPSError {
333
498
  name: string;
499
+ quota?: Quota;
500
+ get prepaidBalanceEmpty(): boolean;
334
501
  }
335
502
  declare class RateLimitError extends CatastroGPSError {
336
503
  name: string;
@@ -350,4 +517,4 @@ declare class NetworkError extends CatastroGPSError {
350
517
  name: string;
351
518
  }
352
519
 
353
- export { type AddressCandidate, type AddressCandidatesQuery, type AddressCandidatesResult, type AddressMatch, type AgricultureData, AmbiguousReferenceError, AuthenticationError, COUNTRY_CODES, CatastroGPS, CatastroGPSError, type CatastroGPSOptions, type ConditionalResponse, type Construction, type CountryCode, type CountryOption, CoverageError, DEFAULT_BASE_URL, DEFAULT_MAX_RETRIES, DEFAULT_TIMEOUT_MS, ENRICHMENT_COUNTRY_CODES, type EnrichmentCountryCode, type ExportFormat, type FetchLike, ForbiddenError, type GetUnitsOptions, NetworkError, NotFoundError, type Parcel, type ParcelGeometry, type PointMatch, type PointQuery, type Quota, QuotaExceededError, RateLimitError, type ResolveCandidate, type ResolveResult, ServerError, ServiceUnavailableError, type SolarEstimate, TimeoutError, type Unit, type UnitsPage, type UnitsPageData, type UnitsResult, VERSION, ValidationError };
520
+ export { ADDRESS_COUNTRY_CODES, type AddressCandidate, type AddressCandidatesQuery, type AddressCandidatesResult, type AddressCountryCode, type AddressMatch, type AgricultureData, AmbiguousReferenceError, AuthenticationError, type BlockStatus, type BurstLimit, COUNTRY_CODES, CatastroGPS, CatastroGPSError, type CatastroGPSOptions, type CompareItem, type Comparison, type ConditionalResponse, type Construction, type CountryCode, type CountryOption, CoverageError, DEFAULT_BASE_URL, DEFAULT_MAX_RETRIES, DEFAULT_TIMEOUT_MS, type DataSource, ENRICHMENT_COUNTRY_CODES, type EnrichmentCountryCode, type ExportFormat, type FetchLike, type FincaCap, ForbiddenError, type GetUnitsOptions, type GroundMotion, type LocatedOptions, type MarketData, NetworkError, NotFoundError, type Parcel, type ParcelGeometry, PlaceNameError, type PointMatch, type PointQuery, type PrepaidOverage, type ProtectedSite, type Quota, QuotaExceededError, RateLimitError, type ResolveCandidate, type ResolveResult, type ScoreData, ServerError, ServiceUnavailableError, type SolarEstimate, type Terrain, TimeoutError, UNITS_COUNTRY_CODES, type Unit, type UnitsCountryCode, type UnitsPage, type UnitsPageData, type UnitsResult, VERSION, ValidationError, type ValueHistory, readQuota };