> For the complete documentation index, see [llms.txt](https://protectedseas.gitbook.io/navigator-api-docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://protectedseas.gitbook.io/navigator-api-docs/change-log.md).

# Change Log

A record of changes to the Navigator API V2. Newest entries first.

Tags: **Added**, **Changed**, **Deprecated**, **Removed**, **Fixed**.

***

#### **2026-09-03 — Removed**

* The `site_id` key in **Search** responses (all modes, including `sites_updated`).\
  It was an exact duplicate of `ps_id`, and was the only place in the API still\
  returning it — **Site Details** and **Boundary** have always returned `ps_id`\
  alone. Deprecated 2026-07-23 and announced to partners for removal in September.\
  Code reading `site_id` from Search responses should read `ps_id` instead.
  * Requests are unaffected. Both the `ps_id` and `sid` query parameters continue\
    to work exactly as before — only the response key was removed.

#### **2026-08-26 — Fixed**

* **Search**: unrecognised `lfp` values are now rejected with `400`. Previously only numeric values were validated — a numeric code outside `0`–`5` returned `400`, but an unrecognised keyword such as `lfp=medium` was silently ignored and the query ran with no `lfp` filter, returning `200` and a full unfiltered result set with nothing to indicate the filter had been dropped. Accepted values are unchanged: numeric codes `0`–`5`, single or comma-separated, or the keywords `high`, `mid`, `low`. A value mixing the two forms, such as `lfp=4,high`, is now also rejected. Access logs show no client sending a non-conforming value, so no integration should be affected.

#### **2026-08-20 — Changed**

* **Scalar values are now returned with their natural JSON types across all endpoints.** Numeric fields — identifiers, activity codes, LFP scores, counts, areas and coordinates — are returned as JSON numbers rather than strings (`"ogc_fid": 36432`, not `"36432"`). Boolean fields are returned as `true` / `false` rather than `0`/`1` codes or `"t"`/`"f"` strings. This applies to **Search**, **Site Details**, **Site Boundary** and **Region Boundary**.
  * Client code comparing values as strings will stop matching: `anchoring === "1"` is now false where `anchoring === 1` is true. Loose comparison (`==`) and truthiness checks are unaffected. The previous behavior required casting in the client, which the documentation described.
  * Identifiers remain strings, including `site_id`, `ps_id`, `wdpa_id`, `iucn_cat` and `region_shortcode` — these are alphanumeric and were never safe to cast. Dates remain ISO 8601 strings.
  * `null` is preserved everywhere and is not converted to `0` or `false`. For activity fields, `null` (*Not Yet Coded*) remains distinct from `0` (*Allowed*). See Response Conventions.
* `subzone` and `children` are now true JSON booleans (`true`/`false`), matching the type already given in the field reference. Both previously returned `"0"` / `"1"` strings.

#### **2026-08-20 — Fixed**

* **Region Boundary** and the `regions` array from **Search** returned `is_multi_jurisdictional`, `includes_multi_jurisdictional_areas`, `region_report` and `variant` as the strings `"t"` and `"f"`. Both values are truthy in JavaScript and Python, so a check such as `if (region.is_multi_jurisdictional)` evaluated true for regions where the value was false. These now return `true` / `false`.
* **Search**: `summary.max_lfp` was returned as a string or a number depending on the result set — it was a number when no site in the result exceeded the initial value and a string once one did. It is now always a number.
* **Search**: `summary.max_tribal_exemptions` could be returned as `null` when any site in the result had no `tribal_exemptions` value recorded. It is now always a number.
* `primary_site_id` referenced a non-existent or inactive site on 1,772 active sites, and used `0` or an empty string in place of `null` on sites with no parent. All such values are now `null`, and any non-null `primary_site_id` resolves to an active site. `subzone` is now populated on every active site; it was previously absent on 9,592.
* `wdpa_id` returned `"0"` on 17,544 active sites that have no World Database on Protected Areas match. `"0"` is truthy in JavaScript and Python, so a check such as `if (site.wdpa_id)` was true for every site. These now return `null`.
* `wdpa_id` used an inconsistent separator where a site maps to several WDPA records — `"; "`, `";"`, `", "` and a bare space were all in use. All multi-value entries now use `"; "`. 1,566 active sites are affected. Consumers splitting this field on a single delimiter previously produced incorrect identifiers for some sites. See Site keys.
* `regulation_name` used an inconsistent separator where a site is governed by several regulations — `"; "`, `";"`, `" ; "` and a semicolon followed by a line break were all in use, and some values contained line breaks carried over from source documents. All multi-value entries now use `"; "` and contain no embedded line breaks. Empty strings are now `null`. 3,224 active sites are affected.

#### **2026-08-20 — Added**

* Site keys: `effective_from`, `effective_to` and `moratorium_reg_expiration_date` are documented as free text rather than dates. Where populated, values are typically a recurring month and day with no year, describing a seasonal closure boundary.
* Response Conventions: `last_reviewed` is documented — it records legal review of regulatory content and is not advanced by data corrections, unlike `last_update`.

#### **2026-08-14 — Added**

* **Search**, **Site Details**, and **Site Boundary** now return `display_simplified`, indicating whether the returned geometry has been simplified for display. `true` = simplified; `false` = returned as held; `null` = the site has no boundary record. Unlike `subzone` and `tribal_exemptions`, this is a true JSON boolean (`true`/`false`), not a `0`/`1` code. It is independent of `boundary_modification` — a site can be both digitized and display-simplified, which the single `boundary_modification` value could not previously express. See Site keys.

#### **2026-08-14 — Changed**

* `boundary_modification` now describes only what was done to the **source** boundary, with display simplification reported separately in `display_simplified`. The value list is now: `0` = Unmodified; `2` = Other modification (e.g. multiple source parts merged, clipped, or split); `3` = Digitized using best available data. Value `1` is retired and no longer assigned to any site.
  * The meaning of `2` is unchanged for boundaries with source-level edits — it has always covered merges, clips, splits and similar. What has changed is its membership: sites that were `1` or `2` *solely* because their geometry was simplified for display, with no other edit, now report `0` with `display_simplified: true`. A filter on `boundary_modification=2` therefore returns fewer sites than before, though every site it returns was correctly `2` previously. A filter on `boundary_modification=1` now returns nothing. Values `0` and `3` are unchanged. See Site keys.
* Boundary coordinates are now two-dimensional: each position is `[longitude, latitude]`. Previously a third ordinate was included, always `0` — it carried no depth or elevation information. This applies to all boundary output: **Site Boundary**, **Region Boundary**, **Site Details** (`site_boundary` and `bounds`), and **Search** (`bounds`). Most GeoJSON parsers accept both forms; client code that reads positions as fixed three-element arrays will need adjusting. See Response Conventions.
* Display geometry has been re-derived for 2,160 sites using a tolerance calculated from vector tile resolution rather than a fixed value. Maximum deviation from the authoritative boundary is now bounded at 9.55 m (LFP 1–2) or 2.39 m (LFP 3–5), improved from approximately 300 m previously. Returned geometries for affected sites are more detailed and contain more vertices; polygon and ring counts are unchanged, so no island or hole was added, dropped, filled, or merged. Point-in-polygon results against the returned geometry are now accurate to the tolerances above. `total_area`, `total_marine_area`, and `percent_marine_area` are unaffected — they have always been computed from the authoritative boundary.
* Simplification is now applied to boundaries exceeding 10,000 vertices, reduced from 100,000. Boundaries below that threshold are returned unsimplified and report `display_simplified: false`.
* Boundaries extending beyond ±85° latitude are returned unsimplified at full detail, as Web Mercator is undefined at those latitudes. A small number of polar and high-seas sites therefore return substantially larger geometries than comparable non-polar sites.
* `last_update` has been advanced for the 2,160 sites whose display geometry was re-derived. Consumers using `changed_since` will see these sites in their next synchronization. `last_reviewed` is unchanged — no regulatory content was reviewed as part of this work. See Data Synchronization.

#### **2026-08-14 — Fixed**

* **Site Boundary**, **Region Boundary**, and **Site Details** (with `export_boundaries=true`) returned an empty body with a `200` status for the largest geometries, instead of the requested boundary. Affected sites included national EEZs and high-seas areas; the response was truncated server-side after headers had been sent, so it could not be distinguished from a successful empty result. Consumers that cached these responses should re-fetch any boundary that came back empty.
* Eleven sites returned an empty geometry for `site_boundary` and `bounds`. These were produced by a fault in the previous simplification process and have been corrected; the affected sites now return valid boundaries.

#### **2026-07-29 — Fixed**

* **Search** now accepts `lfp=0`, which selects proposed sites. These sites were already returned in unfiltered results, but `lfp=0` was rejected as invalid, so they could not be selected. Keyword values (`high`, `mid`, `low`) continue to cover scores 1-5 only.

#### **2026-07-28 — Added**

* **Search**, **Site Details**, and **Site Boundary** now return `boundary_source` and `boundary_modification`, describing where a site's geometry came from and what was done to it: `0` = Unmodified; `1` = Coastline simplified for display; `2` = Simplified for display; `3` = Digitized using best available data. Area fields are always calculated from the unmodified source boundary when one exists, so levels `1` and `2` do not affect `total_area`, `total_marine_area`, or `percent_marine_area`. See [Site keys](/navigator-api-docs/field-reference/site-keys.md).
* **Site Boundary** returns `boundary_source` even when `site_boundary` is `null`, so a boundary withheld for redistribution reasons can be told apart from one that is simply unavailable. See [Boundary](/navigator-api-docs/api-reference/boundary.md).
* **Site Boundary** now returns `ogc_fid` and `ps_id`, so responses can be matched to requests when fetching concurrently. Both are returned regardless of which identifier the request used.
* **Region Boundary** now returns `region_id`, echoed from the request, and `boundary_source`, the provenance of the region boundary — the same field already present in the `regions` array from Search.

#### **2026-07-28 — Changed**

* **Site Details**: the previously undocumented `modification_level` field is now returned as `boundary_modification`. The value and its meaning are unchanged.
* **Site Details**: `boundary_source` was already returned but undocumented. It is now listed in [Site keys](/navigator-api-docs/field-reference/site-keys.md).
* **Search** no longer returns the undocumented `region` field. It was only ever an echo of the `region_id` request parameter — the region filter pinned it to the value supplied — so it carried no information the caller did not already have. Region filtering behavior is unchanged.

#### **2026-07-28 — Removed**

* **Search** no longer returns the undocumented `region` field. It was only ever an echo of the `region_id` request parameter — the region filter pinned it to the value supplied — so it carried no information the caller did not already have. Region filtering behavior is unchanged.
* **Site Details** no longer returns `latest_updates`. The field applied only to V1 sites and is no longer maintained.

#### **2026-07-28 — Fixed**

* **Search** now returns `400` when `region_id` (or the deprecated `rid`) is supplied without `v`, or when it is not a positive integer. Previously the region filter was applied to the `regions` array but silently skipped for `sites`, so such a request returned a filtered region alongside an unfiltered global site list. `v` has always been documented as required when `region_id` is used; it is now enforced.
* **Site Details** now returns `400` when `region_id` is supplied without `v`, or when it is not a positive integer — previously the region constraint was silently skipped.
* **Site Details**: the `region_id` join now matches on the full site version key (`site_id` + `site_major_version` + `site_minor_version`) rather than `site_id` alone. A site must now be in the specified region at the version returned; previously membership at any version satisfied the constraint. Requests that relied on the looser match may now return `404`.
* [Site keys](/navigator-api-docs/field-reference/site-keys.md): `species_of_concern` is returned only by Site Details and is now marked *(Site Details)*. The endpoint summary at the top of the page was also missing `url` and `latest_updates`.

#### **2026-07-23 — Added**

* **Search** responses (all modes, including `sites_updated`) now return `ps_id`, the ProtectedSeas site identifier, consistent with **Site Details**, **Boundary**, and the Site Keys reference. Previously, Search responses returned this value only under the key `site_id`, which was inconsistent with the documentation. Requests are unaffected — `ps_id` has always been the query parameter name.

#### **2026-07-23 — Deprecated**

* The `site_id` key in **Search** responses. It remains for now as an exact duplicate of `ps_id` for backward compatibility, and will be **Removed** in a future release (removal date to be announced in advance). Migrate code reading `site_id` from Search responses to `ps_id`; the Data Synchronization workflow now reflects this.

#### **2026-07-22 — Added**

* **Search** filters sites by individual fishing and marine-activity fields. Supply any activity field name (e.g. `anchoring`, `entry`, `bottom_trawling`) valued by activity code — `0` Allowed, `1` Prohibited, `2` Restricted, `3` N/A — or a comma-separated list. Multiple fields combine with AND. See [Activity filters](/navigator-api-docs/api-reference/search.md#activity-filters).
* The `lfp` parameter now also accepts numeric LFP codes `1`–`5` (e.g. `lfp=5` or `lfp=4,5`), alongside the existing `high` / `mid` / `low` keywords.
* **Search** accepts a `tribal_exemptions` filter (`0` = Yes, `1` = No).
* Supplying any activity or `tribal_exemptions` filter returns sites only (the `regions` array is omitted); an `lfp` filter continues to return regions.

#### **2026-07-08 — Fixed**

* Region-filtered site queries (`type=sites` with `region_id`) no longer return duplicate sites. A site mapped to a region was repeated once per stored version — inflating both the `sites` array and `site_count`; each matching site is now returned a single time.

#### **2026-06-22 — Added**

* **Search** and **Site Details** now return `category_id`, the stable integer key for a site's category (companion to the existing `category_name` label). See [Site Categories](/navigator-api-docs/field-reference/site-categories.md).
* **Search** accepts a new `category_id` query parameter to filter sites by category — a single ID or a comma-separated list (e.g. `category_id=6,7`). Supplying it returns sites only (the `regions` array is omitted), and it applies to both GET and POST/spatial queries.

#### **2026-06-22 — Changed**

* The derived `type` field (`MPA` / `Non-MPA`) on **Search** and **Site Details** is now computed from `category_id` rather than matched against the `category_name` text. Behavior is unchanged for current data (category 1 = `MPA`); the change removes fragility if category labels are reworded. For finer-grained classification, use `category_id` directly.

#### **2026-06-19 — Added**

* `sites_updated` accepts an optional `include_inactive` parameter. When `true`, the response also includes removed sites, each with a `status` field, so consumers can detect deletions without a full catalog sweep.

#### **2026-06-16 — Fixed**

* Site results are now returned in a stable, deterministic order. Paginating with `limit` and `page` no longer causes sites to occasionally shift between pages, so a full paginated sweep returns each site exactly once. See [Pagination](/navigator-api-docs/conventions/data-synchronization.md#pagination).

#### 2026-05-29 — Added

* Launched new API documentation, including endpoint references, response field definitions, and a Conventions section (authentication, errors, rate limits, and data synchronization). The previous Postman documentation is retired.
