Repository: stac-utils/stac-rs (language: python)

Issue:
Support STAC v1.1.0-beta.1
https://github.com/radiantearth/stac-spec/releases/tag/v1.1.0-beta.1
STAC v1.1.0-beta.1
## Related issues

- Closes #290

## Description

Adds validation and migration for STAC v1.1.0, including CLI support that can be used in support of the release itself.

## Checklist

- [x] Unit tests
- [x] Documentation, including doctests
- [x] Git history is linear
- [x] Commit messages are descriptive
- [x] (optional) Git commit messages follow [conventional commits](https://www.conventionalcommits.org/en/v1.0.0/)
- [x] Code is formatted (`cargo fmt`)
- [x] `cargo test`
- [ ] Changes are added to the CHANGELOG



Discussion / hints:

Fix patch:
diff --git a/spec-examples/v1.1.0-beta.1/README.md b/spec-examples/v1.1.0-beta.1/README.md
new file mode 100644
index 00000000..a5f8d3f6
--- /dev/null
+++ b/spec-examples/v1.1.0-beta.1/README.md
@@ -0,0 +1,91 @@
+# STAC Examples
+
+This directory contains various examples for all parts of the STAC specification.
+It is structured to be two valid STACs, meaning both [catalog.json](catalog.json) and [collection.json](collection.json)
+should successfully load in various tools. They do not follow *all* the [best practices](../best-practices.md) for STAC, mostly
+due to the fact that they contrive examples to show the spec and we are hosting in GitHub. But we note below where they differ from an ideal catalog.
+
+The various fields are mostly fictional, to be able to demonstrate the various aspects of the spec as tersely as possible. To get a sense
+of real world STAC implementations we recommend exploring the [stac-examples](http://github.com/stac-utils/stac-examples) repo, which 
+gathers in one place copies of STAC [Items](../item-spec/item-spec.md) and [Collection](../collection-spec/collection-spec.md) 
+from a number of different production catalogs that all follow good STAC practices. And you should also explore the various catalogs
+listed on [STAC Index](http://stacindex.org), to see full catalogs in production.
+
+## Organization
+
+This directory contains two STAC implementations, both valid, but simplified a bit to be illustrative of the key concepts, so 
+they do not quite follow all the best practices. 
+
+### Simple Collection
+
+This STAC implementation consists of three files, all contained at the root of the examples directory
+
+**[collection.json](collection.json)** is a minimal 'simple collection', that links to three items. 
+
+**[simple-item.json](simple-item.json)** is the most minimal possible compliant Item record. Most all data will
+include additional fields, as STAC is designed to be a minimal common subset. But it is useful for showing exactly what is
+required.
+
+**[core-item.json](core-item.json)** is a more realistic example, for a hypothetical analytic image 
+acquisition from a satellite company called 'Remote Data'. It includes additional fields covering the [common 
+metadata](../commons/common-metadata.md). It also links to a variety of assets that is typical for
+satellite imagery, as most providers include a number of complementary files.
+
+**[extended-item.json](extended-item.json)** is arguably an even more realistic example, as it includes a number of the
+[extensions](../extensions/) that are commonly used, to demonstrate how implementations tend to start with the core, and add in
+a number of the core extensions. 
+
+**[collectionless-item.json](collectionless-item.json)** demonstrates the common metadata that is only used when an Item does not have 
+a collection. It is recommended to organize items in collections, but we wanted to show how this works. This is not technically in the
+'simple collection' of this section, but it follows the same pattern, so is included here.
+
+### Nested Catalog
+
+This STAC implementation shows a common pattern, starting with a catalog that links to a number of distinct collections, which may
+link down to a number of items.
+
+**[catalog.json](catalog.json)** is a minimal catalog implementation, linking to two other collections.
+
+**[collection-only/collection.json](collection-only/collection.json)** is a collection that does not link to any items. This
+demonstrates how is is possible to make use of STAC Collections without needing items, to serve as nice summarizing metadata for 
+tools that work with full layers / collections. This example collection is based on real Sentinel-2 values, so is not quite fictional,
+but should be taken as just an example.
+
+**[extensions-collection/collection.json](extensions-collection/collection.json)** contains a small number of items, that demonstrate
+more functionality available in STAC [extensions](../extensions/). These are linked to directly from the individual extensions. These
+items follow the recommendations for [Catalog Layout Best Practices](../best-practices.md#catalog-layout).
+
+## In Depth
+
+As mentioned above, the files in this examples directory form valid STAC implementations. They are all based on a 
+fictional remote sensing company called 'Remote Data', with a URL at remotedata.io. This domain has not been set up, so those links
+will not work, but any valid data provider should provide valid links to their homepage. 
+
+The examples use the `rd:` prefix to show how providers can use custom fields when there are not set fields. In the examples these
+do not link to a schema which is completely valid, but it is recommended that providers do write a JSON schema that can validate 
+their custom fields (we will work to add an example schema for the `rd:` fields in the future). 
+
+### Catalog Type
+
+One of the most important STAC Best Practices is to [use links consistently](../best-practices.md#use-of-links), following one of the
+described 'catalog types'. The catalogs described here are [Relative Published Catalogs](../best-practices.md#relative-published-catalog),
+that use absolute URL's to refer to their assets (so would be an example of a [Self-contained Metadata 
+Only](../best-practices.md#self-contained-metadata-only) catalog that is published).
+
+### Differences with STAC Best Practices
+
+One of the most important documents in this repository is the one about [best practices](../best-practices.md). It describes a number
+of practical recommendations gained by people actually implementing STAC. The core spec is designed to be as flexible as possible, so
+that it is not too rigid and unable to handle unanticipated needs. But we recommend following as many of the best practices as is 
+feasible, as it will help ensure various STAC tools work much better. The examples in this folder don't align with all the best
+practices, mostly because they are meant to demonstrate things as tersely as possible, and also because they live directly inside
+a github repository. As many people will look at these examples and take them as 'how things should be' we felt its important to
+highlight where things here differ from the actual best practices.
+
+#### Catalog Layout
+
+Another important recommendations concerns the [layout of STAC catalogs](../best-practices.md#catalog-layout). This is important
+for tools to be able to expect a certain layout, and most tools will follow the described layout. The simple collection that consists
+of the collection.json and its 3 linked items violates this. This is done to be able to show item examples directly in the root of
+the 'examples' folder, so people don't have to dig deep into folders to get a quick example. But a proper catalog layout would
+put the items in sub-directories, along with their assets.
diff --git a/spec-examples/v1.1.0-beta.1/catalog.json b/spec-examples/v1.1.0-beta.1/catalog.json
new file mode 100644
index 00000000..5ef3e827
--- /dev/null
+++ b/spec-examples/v1.1.0-beta.1/catalog.json
@@ -0,0 +1,43 @@
+{
+  "id": "examples",
+  "type": "Catalog",
+  "title": "Example Catalog",
+  "stac_version": "1.1.0-beta.1",
+  "description": "This catalog is a simple demonstration of an example catalog that is used to organize a hierarchy of collections and their items.",
+  "links": [
+    {
+      "rel": "root",
+      "href": "./catalog.json",
+      "type": "application/json"
+    },
+    {
+      "rel": "child",
+      "href": "./extensions-collection/collection.json",
+      "type": "application/json",
+      "title": "Collection Demonstrating STAC Extensions"
+    },
+    {
+      "rel": "child",
+      "href": "./collection-only/collection.json",
+      "type": "application/json",
+      "title": "Collection with no items (standalone)"
+    },
+    {
+      "rel": "child",
+      "href": "./collection-only/collection-with-schemas.json",
+      "type": "application/json",
+      "title": "Collection with no items (standalone with JSON Schemas)"
+    },
+    {
+      "rel": "item",
+      "href": "./collectionless-item.json",
+      "type": "application/json",
+      "title": "Item that does not have a collection (not recommended, but allowed by the spec)"
+    },
+    {
+      "rel": "self",
+      "href": "https://raw.githubusercontent.com/radiantearth/stac-spec/v1.1.0-beta.1/examples/catalog.json",
+      "type": "application/json"
+    }
+  ]
+}
diff --git a/spec-examples/v1.1.0-beta.1/collection-only/collection-with-schemas.json b/spec-examples/v1.1.0-beta.1/collection-only/collection-with-schemas.json
new file mode 100644
index 00000000..7481d08f
--- /dev/null
+++ b/spec-examples/v1.1.0-beta.1/collection-only/collection-with-schemas.json
@@ -0,0 +1,311 @@
+{
+  "stac_version": "1.1.0-beta.1",
+  "stac_extensions": [
+    "https://stac-extensions.github.io/eo/v2.0.0-beta.1/schema.json",
+    "https://stac-extensions.github.io/sat/v1.0.0/schema.json",
+    "https://stac-extensions.github.io/view/v1.0.0/schema.json"
+  ],
+  "id": "sentinel-2",
+  "type": "Collection",
+  "title": "Sentinel-2 MSI: MultiSpectral Instrument, Level-2A",
+  "description": "The SENTINEL-2 mission is a land monitoring constellation of two satellites each equipped with a MSI (Multispectral Imager) instrument covering 13 spectral bands providing high resolution optical imagery (i.e., 10m, 20m, 60 m) every 10 days with one satellite and 5 days with two satellites",
+  "license": "other",
+  "extent": {
+    "spatial": {
+      "bbox": [
+        [
+          -180,
+          -82.852377834669,
+          180,
+          82.819463367711
+        ]
+      ]
+    },
+    "temporal": {
+      "interval": [
+        [
+          "2017-04-12T02:57:21.459000Z",
+          "2021-04-22T11:30:12.767000Z"
+        ]
+      ]
+    }
+  },
+  "links": [
+    {
+      "rel": "parent",
+      "href": "../catalog.json",
+      "type": "application/json",
+      "title": "Example Catalog"
+    },
+    {
+      "rel": "root",
+      "href": "../catalog.json",
+      "type": "application/json",
+      "title": "Example Catalog"
+    },
+    {
+      "rel": "license",
+      "href": "https://scihub.copernicus.eu/twiki/pub/SciHubWebPortal/TermsConditions/Sentinel_Data_Terms_and_Conditions.pdf",
+      "title": "Legal notice on the use of Copernicus Sentinel Data and Service Information"
+    }
+  ],
+  "providers": [
+    {
+      "name": "European Union/ESA/Copernicus",
+      "roles": [
+        "producer",
+        "licensor"
+      ],
+      "url": "https://sentinel.esa.int/web/sentinel/user-guides/sentinel-2-msi"
+    },
+    {
+      "name": "AWS",
+      "roles": [
+        "host"
+      ],
+      "url": "https://registry.opendata.aws/sentinel-2/"
+    },
+    {
+      "name": "jeobrowser",
+      "roles": [
+        "processor"
+      ],
+      "url": "https://github.com/jjrom/resto"
+    }
+  ],
+  "summaries": {
+    "datetime": {
+      "minimum": "2017-04-12T02:57:21Z",
+      "maximum": "2021-04-22T11:30:12Z"
+    },
+    "instruments": {
+      "type": "string",
+      "const": "msi",
+      "title": "Multispectral Instrument",
+      "count": 6613431
+    },
+    "resto:landcover": {
+      "type": "string",
+      "oneOf": [
+        {
+          "const": "cultivated",
+          "title": "Cultivated",
+          "count": 490750
+        },
+        {
+          "const": "desert",
+          "title": "Desert",
+          "count": 543120
+        },
+        {
+          "const": "flooded",
+          "title": "Flooded",
+          "count": 5187
+        },
+        {
+          "const": "forest",
+          "title": "Forest",
+          "count": 767807
+        },
+        {
+          "const": "herbaceous",
+          "title": "Herbaceous",
+          "count": 674281
+        },
+        {
+          "const": "ice",
+          "title": "Ice",
+          "count": 231285
+        },
+        {
+          "const": "urban",
+          "title": "Urban",
+          "count": 1219
+        },
+        {
+          "const": "water",
+          "title": "Water",
+          "count": 2303314
+        }
+      ]
+    },
+    "resto:location": {
+      "type": "string",
+      "oneOf": [
+        {
+          "const": "tropical",
+          "title": "Tropical",
+          "count": 1807474
+        },
+        {
+          "const": "southern",
+          "title": "Southern",
+          "count": 1671685
+        },
+        {
+          "const": "northern",
+          "title": "Northern",
+          "count": 4876669
+        },
+        {
+          "const": "equatorial",
+          "title": "Equatorial",
+          "count": 27302
+        },
+        {
+          "const": "coastal",
+          "title": "Coastal",
+          "count": 1495516
+        }
+      ]
+    },
+    "platform": {
+      "type": "string",
+      "oneOf": [
+        {
+          "const": "sentinel-2b",
+          "title": "Sentinel 2B",
+          "count": 3495597
+        },
+        {
+          "const": "sentinel-2a",
+          "title": "Sentinel 2A",
+          "count": 3117831
+        }
+      ]
+    },
+    "resto:season": {
+      "type": "integer",
+      "oneOf": [
+        {
+          "const": 0,
+          "title": "Winter",
+          "count": 1621108
+        },
+        {
+          "const": 2,
+          "title": "Summer",
+          "count": 2279472
+        },
+        {
+          "const": 1,
+          "title": "Spring",
+          "count": 1577067
+        },
+        {
+          "const": 3,
+          "title": "Autumn",
+          "count": 1098015
+        }
+      ]
+    },
+    "bands": [
+      {
+        "title": "B1",
+        "eo:common_name": "coastal",
+        "eo:center_wavelength": 0.4439,
+        "gsd": 60
+      },
+      {
+        "title": "B2",
+        "eo:common_name": "blue",
+        "eo:center_wavelength": 0.4966,
+        "gsd": 10
+      },
+      {
+        "title": "B3",
+        "eo:common_name": "green",
+        "eo:center_wavelength": 0.56,
+        "gsd": 10
+      },
+      {
+        "title": "B4",
+        "eo:common_name": "red",
+        "eo:center_wavelength": 0.6645,
+        "gsd": 10
+      },
+      {
+        "title": "B5",
+        "eo:center_wavelength": 0.7039,
+        "gsd": 20
+      },
+      {
+        "title": "B6",
+        "eo:center_wavelength": 0.7402,
+        "gsd": 20
+      },
+      {
+        "title": "B7",
+        "eo:center_wavelength": 0.7825,
+        "gsd": 20
+      },
+      {
+        "title": "B8",
+        "eo:common_name": "nir",
+        "eo:center_wavelength": 0.8351,
+        "gsd": 10
+      },
+      {
+        "title": "B8A",
+        "eo:center_wavelength": 0.8648,
+        "gsd": 20
+      },
+      {
+        "title": "B9",
+        "eo:center_wavelength": 0.945,
+        "gsd": 60
+      },
+      {
+        "title": "B10",
+        "eo:center_wavelength": 0.13735,
+        "gsd": 60
+      },
+      {
+        "title": "B11",
+        "eo:common_name": "swir16",
+        "eo:center_wavelength": 0.16137,
+        "gsd": 20
+      },
+      {
+        "title": "B12",
+        "eo:common_name": "swir22",
+        "eo:center_wavelength": 0.22024,
+        "gsd": 20
+      }
+    ]
+  },
+  "item_assets": {
+    "B1": {
+      "title": "Band 1 (coastal)",
+      "type": "image/tiff; application=geotiff",
+      "roles": [
+        "data",
+        "visual"
+      ]
+    },
+    "B2": {
+      "title": "Band 2 (blue)",
+      "type": "image/tiff; application=geotiff",
+      "roles": [
+        "data",
+        "visual"
+      ]
+    },
+    "B3": {
+      "title": "Band 3 (green)",
+      "type": "image/tiff; application=geotiff",
+      "roles": [
+        "data",
+        "visual"
+      ]
+    },
+    "B4": {
+      "title": "Band 4 (red)",
+      "type": "image/tiff; application=geotiff",
+      "roles": [
+        "data",
+        "visual"
+      ]
+    }
+  }
+}
\ No newline at end of file
diff --git a/spec-examples/v1.1.0-beta.1/collection-only/collection.json b/spec-examples/v1.1.0-beta.1/collection-only/collection.json
new file mode 100644
index 00000000..6fae9810
--- /dev/null
+++ b/spec-examples/v1.1.0-beta.1/collection-only/collection.json
@@ -0,0 +1,233 @@
+{
+  "type": "Collection",
+  "stac_version": "1.1.0-beta.1",
+  "stac_extensions": [
+    "https://stac-extensions.github.io/eo/v2.0.0-beta.1/schema.json",
+    "https://stac-extensions.github.io/projection/v2.0.0/schema.json",
+    "https://stac-extensions.github.io/view/v1.0.0/schema.json"
+  ],
+  "id": "sentinel-2",
+  "title": "Sentinel-2 MSI: MultiSpectral Instrument, Level-1C",
+  "description": "Sentinel-2 is a wide-swath, high-resolution, multi-spectral\nimaging mission supporting Copernicus Land Monitoring studies,\nincluding the monitoring of vegetation, soil and water cover,\nas well as observation of inland waterways and coastal areas.\n\nThe Sentinel-2 data contain 13 UINT16 spectral bands representing\nTOA reflectance scaled by 10000. See the [Sentinel-2 User Handbook](https://sentinel.esa.int/documents/247904/685211/Sentinel-2_User_Handbook)\nfor details. In addition, three QA bands are present where one\n(QA60) is a bitmask band with cloud mask information. For more\ndetails, [see the full explanation of how cloud masks are computed.](https://sentinel.esa.int/web/sentinel/technical-guides/sentinel-2-msi/level-1c/cloud-masks)\n\nEach Sentinel-2 product (zip archive) may contain multiple\ngranules. Each granule becomes a separate Earth Engine asset.\nEE asset ids for Sentinel-2 assets have the following format:\nCOPERNICUS/S2/20151128T002653_20151128T102149_T56MNN. Here the\nfirst numeric part represents the sensing date and time, the\nsecond numeric part represents the product generation date and\ntime, and the final 6-character string is a unique granule identifier\nindicating its UTM grid reference (see [MGRS](https://en.wikipedia.org/wiki/Military_Grid_Reference_System)).\n\nFor more details on Sentinel-2 radiometric resoltuon, [see this page](https://earth.esa.int/web/sentinel/user-guides/sentinel-2-msi/resolutions/radiometric).\n",
+  "license": "other",
+  "keywords": [
+    "copernicus",
+    "esa",
+    "eu",
+    "msi",
+    "radiance",
+    "sentinel"
+  ],
+  "providers": [
+    {
+      "name": "European Union/ESA/Copernicus",
+      "roles": [
+        "producer",
+        "licensor"
+      ],
+      "url": "https://sentinel.esa.int/web/sentinel/user-guides/sentinel-2-msi"
+    }
+  ],
+  "extent": {
+    "spatial": {
+      "bbox": [
+        [
+          -180,
+          -56,
+          180,
+          83
+        ]
+      ]
+    },
+    "temporal": {
+      "interval": [
+        [
+          "2015-06-23T00:00:00Z",
+          null
+        ]
+      ]
+    }
+  },
+  "assets": {
+    "metadata_iso_19139": {
+      "roles": [
+        "metadata",
+        "iso-19139"
+      ],
+      "href": "https://storage.googleapis.com/open-cogs/stac-examples/sentinel-2-iso-19139.xml",
+      "title": "ISO 19139 metadata",
+      "type": "application/vnd.iso.19139+xml"
+    }
+  },
+  "summaries": {
+    "datetime": {
+      "minimum": "2015-06-23T00:00:00Z",
+      "maximum": "2019-07-10T13:44:56Z"
+    },
+    "platform": [
+      "sentinel-2a",
+      "sentinel-2b"
+    ],
+    "constellation": [
+      "sentinel-2"
+    ],
+    "instruments": [
+      "msi"
+    ],
+    "view:off_nadir": {
+      "minimum": 0,
+      "maximum": 100
+    },
+    "view:sun_elevation": {
+      "minimum": 6.78,
+      "maximum": 89.9
+    },
+    "gsd": [
+      10,
+      30,
+      60
+    ],
+    "proj:code": [
+      "EPSG:32601",
+      "EPSG:32602",
+      "EPSG:32603",
+      "EPSG:32604",
+      "EPSG:32605",
+      "EPSG:32606",
+      "EPSG:32607",
+      "EPSG:32608",
+      "EPSG:32609",
+      "EPSG:32610",
+      "EPSG:32611",
+      "EPSG:32612",
+      "EPSG:32613",
+      "EPSG:32614",
+      "EPSG:32615",
+      "EPSG:32616",
+      "EPSG:32617",
+      "EPSG:32618",
+      "EPSG:32619",
+      "EPSG:32620",
+      "EPSG:32621",
+      "EPSG:32622",
+      "EPSG:32623",
+      "EPSG:32624",
+      "EPSG:32625",
+      "EPSG:32626",
+      "EPSG:32627",
+      "EPSG:32628",
+      "EPSG:32629",
+      "EPSG:32630",
+      "EPSG:32631",
+      "EPSG:32632",
+      "EPSG:32633",
+      "EPSG:32634",
+      "EPSG:32635",
+      "EPSG:32636",
+      "EPSG:32637",
+      "EPSG:32638",
+      "EPSG:32639",
+      "EPSG:32640",
+      "EPSG:32641",
+      "EPSG:32642",
+      "EPSG:32643",
+      "EPSG:32644",
+      "EPSG:32645",
+      "EPSG:32646",
+      "EPSG:32647",
+      "EPSG:32648",
+      "EPSG:32649",
+      "EPSG:32650",
+      "EPSG:32651",
+      "EPSG:32652",
+      "EPSG:32653",
+      "EPSG:32654",
+      "EPSG:32655",
+      "EPSG:32656",
+      "EPSG:32657",
+      "EPSG:32658",
+      "EPSG:32659",
+      "EPSG:32660"
+    ],
+    "bands": [
+      {
+        "name": "B1",
+        "eo:common_name": "coastal",
+        "eo:center_wavelength": 0.4439
+      },
+      {
+        "name": "B2",
+        "eo:common_name": "blue",
+        "eo:center_wavelength": 0.4966
+      },
+      {
+        "name": "B3",
+        "eo:common_name": "green",
+        "eo:center_wavelength": 0.56
+      },
+      {
+        "name": "B4",
+        "eo:common_name": "red",
+        "eo:center_wavelength": 0.6645
+      },
+      {
+        "name": "B5",
+        "eo:center_wavelength": 0.7039
+      },
+      {
+        "name": "B6",
+        "eo:center_wavelength": 0.7402
+      },
+      {
+        "name": "B7",
+        "eo:center_wavelength": 0.7825
+      },
+      {
+        "name": "B8",
+        "eo:common_name": "nir",
+        "eo:center_wavelength": 0.8351
+      },
+      {
+        "name": "B8A",
+        "eo:center_wavelength": 0.8648
+      },
+      {
+        "name": "B9",
+        "eo:center_wavelength": 0.945
+      },
+      {
+        "name": "B10",
+        "eo:center_wavelength": 1.3735
+      },
+      {
+        "name": "B11",
+        "eo:common_name": "swir16",
+        "eo:center_wavelength": 1.6137
+      },
+      {
+        "name": "B12",
+        "eo:common_name": "swir22",
+        "eo:center_wavelength": 2.2024
+      }
+    ]
+  },
+  "links": [
+    {
+      "rel": "parent",
+      "href": "../catalog.json",
+      "type": "application/json",
+      "title": "Example Catalog"
+    },
+    {
+      "rel": "root",
+      "href": "../catalog.json",
+      "type": "application/json",
+      "title": "Example Catalog"
+    },
+    {
+      "rel": "license",
+      "href": "https://scihub.copernicus.eu/twiki/pub/SciHubWebPortal/TermsConditions/Sentinel_Data_Terms_and_Conditions.pdf",
+      "title": "Legal notice on the use of Copernicus Sentinel Data and Service Information"
+    }
+  ]
+}
\ No newline at end of file
diff --git a/spec-examples/v1.1.0-beta.1/collection.json b/spec-examples/v1.1.0-beta.1/collection.json
new file mode 100644
index 00000000..697243dc
--- /dev/null
+++ b/spec-examples/v1.1.0-beta.1/collection.json
@@ -0,0 +1,116 @@
+{
+  "id": "simple-collection",
+  "type": "Collection",
+  "stac_extensions": [
+    "https://stac-extensions.github.io/eo/v2.0.0-beta.1/schema.json",
+    "https://stac-extensions.github.io/projection/v2.0.0/schema.json",
+    "https://stac-extensions.github.io/view/v1.0.0/schema.json"
+  ],
+  "stac_version": "1.1.0-beta.1",
+  "description": "A simple collection demonstrating core catalog fields with links to a couple of items",
+  "title": "Simple Example Collection",
+  "keywords": [
+    "simple",
+    "example",
+    "collection"
+  ],
+  "providers": [
+    {
+      "name": "Remote Data, Inc",
+      "description": "Producers of awesome spatiotemporal assets",
+      "roles": [
+        "producer",
+        "processor"
+      ],
+      "url": "http://remotedata.io"
+    }
+  ],
+  "extent": {
+    "spatial": {
+      "bbox": [
+        [
+          172.91173669923782,
+          1.3438851951615003,
+          172.95469614953714,
+          1.3690476620161975
+        ]
+      ]
+    },
+    "temporal": {
+      "interval": [
+        [
+          "2020-12-11T22:38:32.125Z",
+          "2020-12-14T18:02:31.437Z"
+        ]
+      ]
+    }
+  },
+  "license": "CC-BY-4.0",
+  "summaries": {
+    "platform": [
+      "cool_sat1",
+      "cool_sat2"
+    ],
+    "constellation": [
+      "ion"
+    ],
+    "instruments": [
+      "cool_sensor_v1",
+      "cool_sensor_v2"
+    ],
+    "gsd": {
+      "minimum": 0.512,
+      "maximum": 0.66
+    },
+    "eo:cloud_cover": {
+      "minimum": 1.2,
+      "maximum": 1.2
+    },
+    "proj:cpde": [
+      "EPSG:32659"
+    ],
+    "view:sun_elevation": {
+      "minimum": 54.9,
+      "maximum": 54.9
+    },
+    "view:off_nadir": {
+      "minimum": 3.8,
+      "maximum": 3.8
+    },
+    "view:sun_azimuth": {
+      "minimum": 135.7,
+      "maximum": 135.7
+    }
+  },
+  "links": [
+    {
+      "rel": "root",
+      "href": "./collection.json",
+      "type": "application/json",
+      "title": "Simple Example Collection"
+    },
+    {
+      "rel": "item",
+      "href": "./simple-item.json",
+      "type": "application/geo+json",
+      "title": "Simple Item"
+    },
+    {
+      "rel": "item",
+      "href": "./core-item.json",
+      "type": "application/geo+json",
+      "title": "Core Item"
+    },
+    {
+      "rel": "item",
+      "href": "./extended-item.json",
+      "type": "application/geo+json",
+      "title": "Extended Item"
+    },
+    {
+      "rel": "self",
+      "href": "https://raw.githubusercontent.com/radiantearth/stac-spec/v1.1.0-beta.1/examples/collection.json",
+      "type": "application/json"
+    }
+  ]
+}
diff --git a/spec-examples/v1.1.0-beta.1/collectionless-item.json b/spec-examples/v1.1.0-beta.1/collectionless-item.json
new file mode 100644
index 00000000..e66dc7dd
--- /dev/null
+++ b/spec-examples/v1.1.0-beta.1/collectionless-item.json
@@ -0,0 +1,143 @@
+{
+  "stac_version": "1.1.0-beta.1",
+  "stac_extensions": [
+    "https://stac-extensions.github.io/view/v1.0.0/schema.json"
+  ],
+  "type": "Feature",
+  "id": "CS3-20160503_132131_08",
+  "bbox": [
+    -122.59750209,
+    37.48803556,
+    -122.2880486,
+    37.613537207
+  ],
+  "geometry": {
+    "type": "Polygon",
+    "coordinates": [
+      [
+        [
+          -122.308150179,
+          37.488035566
+        ],
+        [
+          -122.597502109,
+          37.538869539
+        ],
+        [
+          -122.576687533,
+          37.613537207
+        ],
+        [
+          -122.2880486,
+          37.562818007
+        ],
+        [
+          -122.308150179,
+          37.488035566
+        ]
+      ]
+    ]
+  },
+  "properties": {
+    "title": "Full Item",
+    "description": "A sample STAC Item demonstrates an Item that does not have a collection, which is not recommended, but allowed by the spec.",
+    "datetime": null,
+    "start_datetime": "2016-05-03T13:22:30Z",
+    "end_datetime": "2016-05-03T13:27:30Z",
+    "created": "2016-05-04T00:00:01Z",
+    "updated": "2017-01-01T00:30:55Z",
+    "license": "other",
+    "providers": [
+      {
+        "name": "Remote Data, Inc",
+        "description": "Producers of awesome spatiotemporal assets",
+        "roles": [
+          "producer",
+          "processor"
+        ],
+        "url": "http://remotedata.it"
+      }
+    ],
+    "platform": "cool_sat2",
+    "instruments": [
+      "cool_sensor_v1"
+    ],
+    "view:sun_elevation": 33.4,
+    "gsd": 0.512,
+    "cs:type": "scene",
+    "cs:anomalous_pixels": 0.14,
+    "cs:earth_sun_distance": 1.014156,
+    "cs:sat_id": "CS3",
+    "cs:product_level": "LV1B"
+  },
+  "links": [
+    {
+      "rel": "root",
+      "href": "./catalog.json",
+      "type": "application/json",
+      "title": "Example Catalog"
+    },
+    {
+      "rel": "parent",
+      "href": "./catalog.json",
+      "type": "application/json",
+      "title": "Example Catalog"
+    },
+    {
+      "rel": "alternate",
+      "type": "text/html",
+      "href": "http://cool-sat.com/catalog/CS3-20160503_132130_04/CS3-20160503_132130_04.html",
+      "title": "HTML representation of this STAC Item"
+    },
+    {
+      "rel": "license",
+      "type": "text/html",
+      "href": "http://remotedata.io/license.html",
+      "title": "Data License for Remote Data, Inc."
+    }
+  ],
+  "assets": {
+    "analytic": {
+      "href": "http://cool-sat.com/catalog/CS3-20160503_132130_04/analytic.tif",
+      "title": "4-Band Analytic",
+      "bands": [
+        {
+          "name": "band1"
+        },
+        {
+          "name": "band1"
+        },
+        {
+          "name": "band2"
+        },
+        {
+          "name": "band3"
+        }
+      ]
+    },
+    "thumbnail": {
+      "href": "http://cool-sat.com/catalog/CS3-20160503_132130_04/thumbnail.png",
+      "title": "Thumbnail",
+      "type": "image/png",
+      "roles": [
+        "thumbnail"
+      ]
+    },
+    "udm": {
+      "href": "http://cool-sat.com/catalog/CS3-20160503_132130_04/UDM.tif",
+      "title": "Unusable Data Mask"
+    },
+    "json-metadata": {
+      "href": "http://cool-sat.com/catalog/CS3-20160503_132130_04/extended-metadata.json",
+      "title": "Extended Metadata",
+      "type": "application/json",
+      "roles": [
+        "metadata"
+      ]
+    },
+    "ephemeris": {
+      "href": "http://cool-sat.com/catalog/CS3-20160503_132130_04/S3-20160503_132130_04.EPH",
+      "title": "Satellite Ephemeris Metadata"
+    }
+  }
+}
diff --git a/spec-examples/v1.1.0-beta.1/core-item.json b/spec-examples/v1.1.0-beta.1/core-item.json
new file mode 100644
index 00000000..5eb1e675
--- /dev/null
+++ b/spec-examples/v1.1.0-beta.1/core-item.json
@@ -0,0 +1,125 @@
+{
+  "stac_version": "1.1.0-beta.1",
+  "stac_extensions": [],
+  "type": "Feature",
+  "id": "20201211_223832_CS2",
+  "bbox": [
+    172.91173669923782,
+    1.3438851951615003,
+    172.95469614953714,
+    1.3690476620161975
+  ],
+  "geometry": {
+    "type": "Polygon",
+    "coordinates": [
+      [
+        [
+          172.91173669923782,
+          1.3438851951615003
+        ],
+        [
+          172.95469614953714,
+          1.3438851951615003
+        ],
+        [
+          172.95469614953714,
+          1.3690476620161975
+        ],
+        [
+          172.91173669923782,
+          1.3690476620161975
+        ],
+        [
+          172.91173669923782,
+          1.3438851951615003
+        ]
+      ]
+    ]
+  },
+  "properties": {
+    "title": "Core Item",
+    "description": "A sample STAC Item that includes examples of all common metadata",
+    "datetime": null,
+    "start_datetime": "2020-12-11T22:38:32.125Z",
+    "end_datetime": "2020-12-11T22:38:32.327Z",
+    "created": "2020-12-12T01:48:13.725Z",
+    "updated": "2020-12-12T01:48:13.725Z",
+    "platform": "cool_sat1",
+    "instruments": [
+      "cool_sensor_v1"
+    ],
+    "constellation": "ion",
+    "mission": "collection 5624",
+    "gsd": 0.512
+  },
+  "collection": "simple-collection",
+  "links": [
+    {
+      "rel": "collection",
+      "href": "./collection.json",
+      "type": "application/json",
+      "title": "Simple Example Collection"
+    },
+    {
+      "rel": "root",
+      "href": "./collection.json",
+      "type": "application/json",
+      "title": "Simple Example Collection"
+    },
+    {
+      "rel": "parent",
+      "href": "./collection.json",
+      "type": "application/json",
+      "title": "Simple Example Collection"
+    },
+    {
+      "rel": "alternate",
+      "type": "text/html",
+      "href": "http://remotedata.io/catalog/20201211_223832_CS2/index.html",
+      "title": "HTML version of this STAC Item"
+    }
+  ],
+  "assets": {
+    "analytic": {
+      "href": "https://storage.googleapis.com/open-cogs/stac-examples/20201211_223832_CS2_analytic.tif",
+      "type": "image/tiff; application=geotiff; profile=cloud-optimized",
+      "title": "4-Band Analytic",
+      "roles": [
+        "data"
+      ]
+    },
+    "thumbnail": {
+      "href": "https://storage.googleapis.com/open-cogs/stac-examples/20201211_223832_CS2.jpg",
+      "title": "Thumbnail",
+      "type": "image/png",
+      "roles": [
+        "thumbnail"
+      ]
+    },
+    "visual": {
+      "href": "https://storage.googleapis.com/open-cogs/stac-examples/20201211_223832_CS2.tif",
+      "type": "image/tiff; application=geotiff; profile=cloud-optimized",
+      "title": "3-Band Visual",
+      "roles": [
+        "visual"
+      ]
+    },
+    "udm": {
+      "href": "https://storage.googleapis.com/open-cogs/stac-examples/20201211_223832_CS2_analytic_udm.tif",
+      "title": "Unusable Data Mask",
+      "type": "image/tiff; application=geotiff"
+    },
+    "json-metadata": {
+      "href": "http://remotedata.io/catalog/20201211_223832_CS2/extended-metadata.json",
+      "title": "Extended Metadata",
+      "type": "application/json",
+      "roles": [
+        "metadata"
+      ]
+    },
+    "ephemeris": {
+      "href": "http://cool-sat.com/catalog/20201211_223832_CS2/20201211_223832_CS2.EPH",
+      "title": "Satellite Ephemeris Metadata"
+    }
+  }
+}
diff --git a/spec-examples/v1.1.0-beta.1/extended-item.json b/spec-examples/v1.1.0-beta.1/extended-item.json
new file mode 100644
index 00000000..45ad0128
--- /dev/null
+++ b/spec-examples/v1.1.0-beta.1/extended-item.json
@@ -0,0 +1,204 @@
+{
+  "stac_version": "1.1.0-beta.1",
+  "stac_extensions": [
+    "https://stac-extensions.github.io/eo/v2.0.0-beta.1/schema.json",
+    "https://stac-extensions.github.io/projection/v2.0.0/schema.json",
+    "https://stac-extensions.github.io/scientific/v1.0.0/schema.json",
+    "https://stac-extensions.github.io/view/v1.0.0/schema.json",
+    "https://stac-extensions.github.io/remote-data/v1.0.0/schema.json"
+  ],
+  "type": "Feature",
+  "id": "20201211_223832_CS2",
+  "bbox": [
+    172.91173669923782,
+    1.3438851951615003,
+    172.95469614953714,
+    1.3690476620161975
+  ],
+  "geometry": {
+    "type": "Polygon",
+    "coordinates": [
+      [
+        [
+          172.91173669923782,
+          1.3438851951615003
+        ],
+        [
+          172.95469614953714,
+          1.3438851951615003
+        ],
+        [
+          172.95469614953714,
+          1.3690476620161975
+        ],
+        [
+          172.91173669923782,
+          1.3690476620161975
+        ],
+        [
+          172.91173669923782,
+          1.3438851951615003
+        ]
+      ]
+    ]
+  },
+  "properties": {
+    "title": "Extended Item",
+    "description": "A sample STAC Item that includes a variety of examples from the stable extensions",
+    "keywords": [
+      "extended",
+      "example",
+      "item"
+    ],
+    "datetime": "2020-12-14T18:02:31.437000Z",
+    "created": "2020-12-15T01:48:13.725Z",
+    "updated": "2020-12-15T01:48:13.725Z",
+    "platform": "cool_sat2",
+    "instruments": [
+      "cool_sensor_v2"
+    ],
+    "gsd": 0.66,
+    "eo:cloud_cover": 1.2,
+    "proj:code": "EPSG:32659",
+    "proj:shape": [
+      5558,
+      9559
+    ],
+    "proj:transform": [
+      0.5,
+      0,
+      712710,
+      0,
+      -0.5,
+      151406,
+      0,
+      0,
+      1
+    ],
+    "view:sun_elevation": 54.9,
+    "view:off_nadir": 3.8,
+    "view:sun_azimuth": 135.7,
+    "rd:type": "scene",
+    "rd:anomalous_pixels": 0.14,
+    "rd:earth_sun_distance": 1.014156,
+    "rd:sat_id": "cool_sat2",
+    "rd:product_level": "LV3A",
+    "sci:doi": "10.5061/dryad.s2v81.2/27.2"
+  },
+  "collection": "simple-collection",
+  "links": [
+    {
+      "rel": "collection",
+      "href": "./collection.json",
+      "type": "application/json",
+      "title": "Simple Example Collection"
+    },
+    {
+      "rel": "root",
+      "href": "./collection.json",
+      "type": "application/json",
+      "title": "Simple Example Collection"
+    },
+    {
+      "rel": "parent",
+      "href": "./collection.json",
+      "type": "application/json",
+      "title": "Simple Example Collection"
+    },
+    {
+      "rel": "alternate",
+      "type": "text/html",
+      "href": "http://remotedata.io/catalog/20201211_223832_CS2/index.html",
+      "title": "HTML version of this STAC Item"
+    }
+  ],
+  "assets": {
+    "analytic": {
+      "href": "https://storage.googleapis.com/open-cogs/stac-examples/20201211_223832_CS2_analytic.tif",
+      "type": "image/tiff; application=geotiff; profile=cloud-optimized",
+      "title": "4-Band Analytic",
+      "roles": [
+        "data"
+      ],
+      "bands": [
+        {
+          "name": "band1",
+          "eo:common_name": "blue",
+          "eo:center_wavelength": 0.47,
+          "eo:full_width_half_max": 70
+        },
+        {
+          "name": "band2",
+          "eo:common_name": "green",
+          "eo:center_wavelength": 0.56,
+          "eo:full_width_half_max": 80
+        },
+        {
+          "name": "band3",
+          "eo:common_name": "red",
+          "eo:center_wavelength": 0.645,
+          "eo:full_width_half_max": 90
+        },
+        {
+          "name": "band4",
+          "eo:common_name": "nir",
+          "eo:center_wavelength": 0.8,
+          "eo:full_width_half_max": 152
+        }
+      ]
+    },
+    "thumbnail": {
+      "href": "https://storage.googleapis.com/open-cogs/stac-examples/20201211_223832_CS2.jpg",
+      "title": "Thumbnail",
+      "type": "image/png",
+      "roles": [
+        "thumbnail"
+      ]
+    },
+    "visual": {
+      "href": "https://storage.googleapis.com/open-cogs/stac-examples/20201211_223832_CS2.tif",
+      "type": "image/tiff; application=geotiff; profile=cloud-optimized",
+      "title": "3-Band Visual",
+      "roles": [
+        "visual"
+      ],
+      "bands": [
+        {
+          "name": "band3",
+          "eo:common_name": "red",
+          "eo:center_wavelength": 0.645,
+          "eo:full_width_half_max": 90
+        },
+        {
+          "name": "band2",
+          "eo:common_name": "green",
+          "eo:center_wavelength": 0.56,
+          "eo:full_width_half_max": 80
+        },
+        {
+          "name": "band1",
+          "eo:common_name": "blue",
+          "eo:center_wavelength": 0.47,
+          "eo:full_width_half_max": 70
+        }
+      ]
+    },
+    "udm": {
+      "href": "https://storage.googleapis.com/open-cogs/stac-examples/20201211_223832_CS2_analytic_udm.tif",
+      "title": "Unusable Data Mask",
+      "type": "image/tiff; application=geotiff"
+    },
+    "json-metadata": {
+      "href": "http://remotedata.io/catalog/20201211_223832_CS2/extended-metadata.json",
+      "title": "Extended Metadata",
+      "type": "application/json",
+      "roles": [
+        "metadata"
+      ]
+    },
+    "ephemeris": {
+      "href": "http://cool-sat.com/catalog/20201211_223832_CS2/20201211_223832_CS2.EPH",
+      "title": "Satellite Ephemeris Metadata"
+    }
+  }
+}
diff --git a/spec-examples/v1.1.0-beta.1/extensions-collection/collection.json b/spec-examples/v1.1.0-beta.1/extensions-collection/collection.json
new file mode 100644
index 00000000..9c0ae912
--- /dev/null
+++ b/spec-examples/v1.1.0-beta.1/extensions-collection/collection.json
@@ -0,0 +1,68 @@
+{
+  "id": "extensions-collection",
+  "type": "Collection",
+  "stac_version": "1.1.0-beta.1",
+  "description": "A heterogeneous collection containing deeper examples of various extensions",
+  "links": [
+    {
+      "rel": "parent",
+      "href": "../catalog.json",
+      "type": "application/json",
+      "title": "Example Catalog"
+    },
+    {
+      "rel": "root",
+      "href": "../catalog.json",
+      "type": "application/json",
+      "title": "Example Catalog"
+    },
+    {
+      "rel": "item",
+      "href": "./proj-example/proj-example.json",
+      "title": "Proj extension example"
+    },
+    {
+      "rel": "license",
+      "href": "https://remotedata.io/license.html",
+      "title": "Remote Data License Terms"
+    }
+  ],
+  "stac_extensions": [],
+  "title": "Collection of Extension Items",
+  "keywords": [
+    "examples",
+    "sar",
+    "projection"
+  ],
+  "providers": [
+    {
+      "name": "Remote Data, Inc.",
+      "roles": [
+        "producer",
+        "licensor"
+      ],
+      "url": "https://remotedata.io"
+    }
+  ],
+  "extent": {
+    "spatial": {
+      "bbox": [
+        [
+          -180,
+          -56,
+          180,
+          83
+        ]
+      ]
+    },
+    "temporal": {
+      "interval": [
+        [
+          "2009-05-20T02:40:01.042784Z",
+          "2018-11-03T23:59:55.112875Z"
+        ]
+      ]
+    }
+  },
+  "license": "other"
+}
diff --git a/spec-examples/v1.1.0-beta.1/extensions-collection/proj-example/proj-example.json b/spec-examples/v1.1.0-beta.1/extensions-collection/proj-example/proj-example.json
new file mode 100644
index 00000000..e2e6283b
--- /dev/null
+++ b/spec-examples/v1.1.0-beta.1/extensions-collection/proj-example/proj-example.json
@@ -0,0 +1,285 @@
+{
+  "type": "Feature",
+  "stac_version": "1.1.0-beta.1",
+  "id": "proj-example",
+  "properties": {
+    "datetime": "2018-10-01T01:08:32.033000Z",
+    "proj:code": "EPSG:32614",
+    "proj:wkt2": "PROJCS[\"WGS 84 / UTM zone 14N\",GEOGCS[\"WGS 84\",DATUM[\"WGS_1984\",SPHEROID[\"WGS 84\",6378137,298.257223563,AUTHORITY[\"EPSG\",\"7030\"]],AUTHORITY[\"EPSG\",\"6326\"]],PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]],UNIT[\"degree\",0.01745329251994328,AUTHORITY[\"EPSG\",\"9122\"]],AUTHORITY[\"EPSG\",\"4326\"]],UNIT[\"metre\",1,AUTHORITY[\"EPSG\",\"9001\"]],PROJECTION[\"Transverse_Mercator\"],PARAMETER[\"latitude_of_origin\",0],PARAMETER[\"central_meridian\",-99],PARAMETER[\"scale_factor\",0.9996],PARAMETER[\"false_easting\",500000],PARAMETER[\"false_northing\",0],AUTHORITY[\"EPSG\",\"32614\"],AXIS[\"Easting\",EAST],AXIS[\"Northing\",NORTH]]",
+    "proj:projjson": {
+      "$schema": "https://proj.org/schemas/v0.2/projjson.schema.json",
+      "type": "ProjectedCRS",
+      "name": "WGS 84 / UTM zone 14N",
+      "base_crs": {
+        "name": "WGS 84",
+        "datum": {
+          "type": "GeodeticReferenceFrame",
+          "name": "World Geodetic System 1984",
+          "ellipsoid": {
+            "name": "WGS 84",
+            "semi_major_axis": 6378137,
+            "inverse_flattening": 298.257223563
+          }
+        },
+        "coordinate_system": {
+          "subtype": "ellipsoidal",
+          "axis": [
+            {
+              "name": "Geodetic latitude",
+              "abbreviation": "Lat",
+              "direction": "north",
+              "unit": "degree"
+            },
+            {
+              "name": "Geodetic longitude",
+              "abbreviation": "Lon",
+              "direction": "east",
+              "unit": "degree"
+            }
+          ]
+        },
+        "id": {
+          "authority": "EPSG",
+          "code": 4326
+        }
+      },
+      "conversion": {
+        "name": "UTM zone 14N",
+        "method": {
+          "name": "Transverse Mercator",
+          "id": {
+            "authority": "EPSG",
+            "code": 9807
+          }
+        },
+        "parameters": [
+          {
+            "name": "Latitude of natural origin",
+            "value": 0,
+            "unit": "degree",
+            "id": {
+              "authority": "EPSG",
+              "code": 8801
+            }
+          },
+          {
+            "name": "Longitude of natural origin",
+            "value": -99,
+            "unit": "degree",
+            "id": {
+              "authority": "EPSG",
+              "code": 8802
+            }
+          },
+          {
+            "name": "Scale factor at natural origin",
+            "value": 0.9996,
+            "unit": "unity",
+            "id": {
+              "authority": "EPSG",
+              "code": 8805
+            }
+          },
+          {
+            "name": "False easting",
+            "value": 500000,
+            "unit": "metre",
+            "id": {
+              "authority": "EPSG",
+              "code": 8806
+            }
+          },
+          {
+            "name": "False northing",
+            "value": 0,
+            "unit": "metre",
+            "id": {
+              "authority": "EPSG",
+              "code": 8807
+            }
+          }
+        ]
+      },
+      "coordinate_system": {
+        "subtype": "Cartesian",
+        "axis": [
+          {
+            "name": "Easting",
+            "abbreviation": "E",
+            "direction": "east",
+            "unit": "metre"
+          },
+          {
+            "name": "Northing",
+            "abbreviation": "N",
+            "direction": "north",
+            "unit": "metre"
+          }
+        ]
+      },
+      "area": "World - N hemisphere - 102°W to 96°W - by country",
+      "bbox": {
+        "south_latitude": 0,
+        "west_longitude": -102,
+        "north_latitude": 84,
+        "east_longitude": -96
+      },
+      "id": {
+        "authority": "EPSG",
+        "code": 32614
+      }
+    },
+    "proj:geometry": {
+      "coordinates": [
+        [
+          [
+            169200,
+            3712800
+          ],
+          [
+            403200,
+            3712800
+          ],
+          [
+            403200,
+            3951000
+          ],
+          [
+            169200,
+            3951000
+          ],
+          [
+            169200,
+            3712800
+          ]
+        ]
+      ],
+      "type": "Polygon"
+    },
+    "proj:bbox": [
+      169200,
+      3712800,
+      403200,
+      3951000
+    ],
+    "proj:centroid": {
+      "lat": 34.595302781575604,
+      "lon": -101.34448382627504
+    },
+    "proj:shape": [
+      8391,
+      8311
+    ],
+    "proj:transform": [
+      30,
+      0,
+      224985,
+      0,
+      -30,
+      6790215,
+      0,
+      0,
+      1
+    ]
+  },
+  "geometry": {
+    "type": "Polygon",
+    "coordinates": [
+      [
+        [
+          152.52758,
+          60.63437
+        ],
+        [
+          149.1755,
+          61.19016
+        ],
+        [
+          148.13933,
+          59.51584
+        ],
+        [
+          151.33786,
+          58.97792
+        ],
+        [
+          152.52758,
+          60.63437
+        ]
+      ]
+    ]
+  },
+  "links": [
+    {
+      "rel": "root",
+      "href": "../../catalog.json",
+      "type": "application/json",
+      "title": "Example Catalog"
+    },
+    {
+      "rel": "parent",
+      "href": "../collection.json",
+      "type": "application/json",
+      "title": "Collection of Extension Items"
+    },
+    {
+      "rel": "collection",
+      "href": "../collection.json",
+      "type": "application/json",
+      "title": "Collection of Extension Items"
+    }
+  ],
+  "assets": {
+    "B1": {
+      "href": "https://landsat-pds.s3.amazonaws.com/c1/L8/107/018/LC08_L1TP_107018_20181001_20181001_01_RT/LC08_L1TP_107018_20181001_20181001_01_RT_B1.TIF",
+      "type": "image/tiff; application=geotiff",
+      "title": "Band 1 (coastal)",
+      "bands": [
+        {
+          "name": "B1",
+          "eo:common_name": "coastal",
+          "eo:center_wavelength": 0.44,
+          "eo:full_width_half_max": 0.02
+        }
+      ]
+    },
+    "B8": {
+      "href": "https://landsat-pds.s3.amazonaws.com/c1/L8/107/018/LC08_L1TP_107018_20181001_20181001_01_RT/LC08_L1TP_107018_20181001_20181001_01_RT_B8.TIF",
+      "type": "image/tiff; application=geotiff",
+      "title": "Band 8 (panchromatic)",
+      "bands": [
+        {
+          "name": "B8",
+          "eo:center_wavelength": 0.59,
+          "eo:full_width_half_max": 0.18
+        }
+      ],
+      "proj:shape": [
+        16781,
+        16621
+      ],
+      "proj:transform": [
+        15,
+        0,
+        224992.5,
+        0,
+        -15,
+        6790207.5,
+        0,
+        0,
+        1
+      ]
+    }
+  },
+  "bbox": [
+    148.13933,
+    59.51584,
+    152.52758,
+    60.63437
+  ],
+  "stac_extensions": [
+    "https://stac-extensions.github.io/eo/v2.0.0-beta.1/schema.json",
+    "https://stac-extensions.github.io/projection/v2.0.0/schema.json"
+  ],
+  "collection": "landsat-8-l1"
+}
diff --git a/spec-examples/v1.1.0-beta.1/simple-item.json b/spec-examples/v1.1.0-beta.1/simple-item.json
new file mode 100644
index 00000000..d0c7f764
--- /dev/null
+++ b/spec-examples/v1.1.0-beta.1/simple-item.json
@@ -0,0 +1,81 @@
+{
+  "stac_version": "1.1.0-beta.1",
+  "stac_extensions": [],
+  "type": "Feature",
+  "id": "20201211_223832_CS2",
+  "bbox": [
+    172.91173669923782,
+    1.3438851951615003,
+    172.95469614953714,
+    1.3690476620161975
+  ],
+  "geometry": {
+    "type": "Polygon",
+    "coordinates": [
+      [
+        [
+          172.91173669923782,
+          1.3438851951615003
+        ],
+        [
+          172.95469614953714,
+          1.3438851951615003
+        ],
+        [
+          172.95469614953714,
+          1.3690476620161975
+        ],
+        [
+          172.91173669923782,
+          1.3690476620161975
+        ],
+        [
+          172.91173669923782,
+          1.3438851951615003
+        ]
+      ]
+    ]
+  },
+  "properties": {
+    "datetime": "2020-12-11T22:38:32.125000Z"
+  },
+  "collection": "simple-collection",
+  "links": [
+    {
+      "rel": "collection",
+      "href": "./collection.json",
+      "type": "application/json",
+      "title": "Simple Example Collection"
+    },
+    {
+      "rel": "root",
+      "href": "./collection.json",
+      "type": "application/json",
+      "title": "Simple Example Collection"
+    },
+    {
+      "rel": "parent",
+      "href": "./collection.json",
+      "type": "application/json",
+      "title": "Simple Example Collection"
+    }
+  ],
+  "assets": {
+    "visual": {
+      "href": "https://storage.googleapis.com/open-cogs/stac-examples/20201211_223832_CS2.tif",
+      "type": "image/tiff; application=geotiff; profile=cloud-optimized",
+      "title": "3-Band Visual",
+      "roles": [
+        "visual"
+      ]
+    },
+    "thumbnail": {
+      "href": "https://storage.googleapis.com/open-cogs/stac-examples/20201211_223832_CS2.jpg",
+      "title": "Thumbnail",
+      "type": "image/jpeg",
+      "roles": [
+        "thumbnail"
+      ]
+    }
+  }
+}
diff --git a/stac-validate/CHANGELOG.md b/stac-validate/CHANGELOG.md
index 8fe5f111..c9d44bdc 100644
--- a/stac-validate/CHANGELOG.md
+++ b/stac-validate/CHANGELOG.md
@@ -9,6 +9,15 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
 ### Added
 
 - `impl Default for Validator` ([#252](https://github.com/stac-utils/stac-rs/pull/252))
+- Support for validating versions other than v1.0.0 ([#293](https://github.com/stac-utils/stac-rs/pull/293))
+
+### Changed
+
+- `ValidateCore::validate_core_json` now takes a mutable reference to the validator ([#293](https://github.com/stac-utils/stac-rs/pull/293))
+
+### Removed
+
+- `ValidateCore::validate_core` ([#293](https://github.com/stac-utils/stac-rs/pull/293))
 
 ## [0.1.2] - 2024-04-29
 
diff --git a/stac-validate/Cargo.toml b/stac-validate/Cargo.toml
index 8b34e415..21e65e07 100644
--- a/stac-validate/Cargo.toml
+++ b/stac-validate/Cargo.toml
@@ -22,3 +22,4 @@ url = "2"
 [dev-dependencies]
 geojson = "0.24"
 stac = { version = "0.7", path = "../stac", features = ["geo"] }
+rstest = "0.22"
diff --git a/stac-validate/src/error.rs b/stac-validate/src/error.rs
index d4ec882e..fb66c2f5 100644
--- a/stac-validate/src/error.rs
+++ b/stac-validate/src/error.rs
@@ -11,6 +11,10 @@ pub enum Error {
     #[error("cannot resolve json-schema scheme: {0}")]
     CannotResolveJsonSchemaScheme(Url),
 
+    /// Missing stac_version.
+    #[error("missing stac_version attribute")]
+    MissingStacVersion,
+
     /// The `stac_extensions` vector, or its contents, are not the correct type.
     #[error("incorrect stac extensions type")]
     IncorrectStacExtensionsType(serde_json::Value),
@@ -23,6 +27,10 @@ pub enum Error {
     #[error("invalid url scheme: {0}")]
     InvalidUrlScheme(Url),
 
+    /// Invalid JSONSchema.
+    #[error("invalid json-schema at url: {0}")]
+    InvalidSchema(String),
+
     /// [reqwest::Error]
     #[error(transparent)]
     Reqwest(#[from] reqwest::Error),
diff --git a/stac-validate/src/lib.rs b/stac-validate/src/lib.rs
index caa87987..e8b639c9 100644
--- a/stac-validate/src/lib.rs
+++ b/stac-validate/src/lib.rs
@@ -71,6 +71,7 @@ pub type Result<T> = std::result::Result<T, Error>;
 mod tests {
     use crate::Validate;
     use geojson::{Geometry, Value};
+    use rstest as _;
     use stac::{Catalog, Collection, Item};
 
     #[test]
diff --git a/stac-validate/src/validate.rs b/stac-validate/src/validate.rs
index 5cef040f..11bd20dd 100644
--- a/stac-validate/src/validate.rs
+++ b/stac-validate/src/validate.rs
@@ -59,22 +59,6 @@ pub trait Validate: ValidateCore {
 /// If your STAC object is the same version as [stac::STAC_VERSION], this will
 /// be a quick, cheap operation, since the schemas are stored in the library.
 pub trait ValidateCore: Serialize {
-    /// Validate a [serde_json::Value] against a specific STAC jsonschema.
-    ///
-    /// #  Examples
-    ///
-    /// [stac::Item] implements [ValidateCore]:
-    ///
-    /// ```
-    /// use stac_validate::ValidateCore;
-    /// let item = stac::Item::new("an-id");
-    /// item.validate_core().unwrap();
-    /// ```
-    fn validate_core(&self) -> Result<()> {
-        let value = serde_json::to_value(self)?;
-        Self::validate_core_json(&value, &Validator::new())
-    }
-
     /// Validate a [serde_json::Value] against a specific STAC jsonschema.
     ///
     /// #  Examples
@@ -87,15 +71,15 @@ pub trait ValidateCore: Serialize {
     ///
     /// let item = Item::new("an-id");
     /// let value = serde_json::to_value(item).unwrap();
-    /// Item::validate_core_json(&value, &stac_validate::Validator::new()).unwrap();
+    /// Item::validate_core_json(&value, &mut stac_validate::Validator::new()).unwrap();
     /// ```
-    fn validate_core_json(value: &Value, validator: &Validator) -> Result<()>;
+    fn validate_core_json(value: &Value, validator: &mut Validator) -> Result<()>;
 }
 
 impl Validate for Item {}
 
 impl ValidateCore for Item {
-    fn validate_core_json(value: &Value, validator: &Validator) -> Result<()> {
+    fn validate_core_json(value: &Value, validator: &mut Validator) -> Result<()> {
         validator.validate_item(value)
     }
 }
@@ -103,7 +87,7 @@ impl ValidateCore for Item {
 impl Validate for Catalog {}
 
 impl ValidateCore for Catalog {
-    fn validate_core_json(value: &Value, validator: &Validator) -> Result<()> {
+    fn validate_core_json(value: &Value, validator: &mut Validator) -> Result<()> {
         validator.validate_catalog(value)
     }
 }
@@ -111,7 +95,7 @@ impl ValidateCore for Catalog {
 impl Validate for Collection {}
 
 impl ValidateCore for Collection {
-    fn validate_core_json(value: &Value, validator: &Validator) -> Result<()> {
+    fn validate_core_json(value: &Value, validator: &mut Validator) -> Result<()> {
         validator.validate_collection(value)
     }
 }
@@ -119,7 +103,7 @@ impl ValidateCore for Collection {
 impl Validate for stac::Value {}
 
 impl ValidateCore for stac::Value {
-    fn validate_core_json(value: &Value, validator: &Validator) -> Result<()> {
+    fn validate_core_json(value: &Value, validator: &mut Validator) -> Result<()> {
         if let Some(type_) = value.get("type") {
             if let Some(type_) = type_.as_str() {
                 match type_ {
@@ -141,7 +125,7 @@ impl ValidateCore for stac::Value {
 impl Validate for ItemCollection {}
 
 impl ValidateCore for ItemCollection {
-    fn validate_core_json(value: &Value, validator: &Validator) -> Result<()> {
+    fn validate_core_json(value: &Value, validator: &mut Validator) -> Result<()> {
         validator.validate_item_collection(value)
     }
 }
@@ -149,7 +133,7 @@ impl ValidateCore for ItemCollection {
 impl Validate for Value {}
 
 impl ValidateCore for Value {
-    fn validate_core_json(value: &Value, validator: &Validator) -> Result<()> {
+    fn validate_core_json(value: &Value, validator: &mut Validator) -> Result<()> {
         if let Some(type_) = value.get("type") {
             if let Some(type_) = type_.as_str() {
                 match type_ {
diff --git a/stac-validate/src/validator.rs b/stac-validate/src/validator.rs
index a3e2d09d..334c14ea 100644
--- a/stac-validate/src/validator.rs
+++ b/stac-validate/src/validator.rs
@@ -1,6 +1,7 @@
 use crate::{Error, Result, Validate};
-use jsonschema::{JSONSchema, SchemaResolver, SchemaResolverError};
+use jsonschema::{CompilationOptions, JSONSchema, SchemaResolver, SchemaResolverError};
 use serde_json::Value;
+use stac::Version;
 use std::{
     collections::HashMap,
     sync::Arc,
@@ -14,10 +15,11 @@ use url::Url;
 /// schemas.
 #[derive(Debug)]
 pub struct Validator {
-    item_schema: JSONSchema,
-    catalog_schema: JSONSchema,
-    collection_schema: JSONSchema,
+    item_schemas: HashMap<Version, JSONSchema>,
+    catalog_schemas: HashMap<Version, JSONSchema>,
+    collection_schemas: HashMap<Version, JSONSchema>,
     extension_schemas: HashMap<String, JSONSchema>,
+    compilation_options: CompilationOptions,
 }
 
 #[derive(Default)]
@@ -34,25 +36,41 @@ impl Validator {
     /// ```
     pub fn new() -> Validator {
         let mut options = JSONSchema::options();
-        let options = options.with_resolver(Resolver);
-        Validator {
-            item_schema: options
+        let options_with_resolver = options.with_resolver(Resolver);
+        let mut item_schemas = HashMap::new();
+        let _ = item_schemas.insert(
+            Version::v1_0_0,
+            options_with_resolver
                 .compile(
                     &serde_json::from_str(include_str!("../schemas/v1.0.0/item.json")).unwrap(),
                 )
                 .unwrap(),
-            catalog_schema: options
+        );
+        let mut catalog_schemas = HashMap::new();
+        let _ = catalog_schemas.insert(
+            Version::v1_0_0,
+            options_with_resolver
                 .compile(
                     &serde_json::from_str(include_str!("../schemas/v1.0.0/catalog.json")).unwrap(),
                 )
                 .unwrap(),
-            collection_schema: options
+        );
+        let mut collection_schemas = HashMap::new();
+        let _ = collection_schemas.insert(
+            Version::v1_0_0,
+            options_with_resolver
                 .compile(
                     &serde_json::from_str(include_str!("../schemas/v1.0.0/collection.json"))
                         .unwrap(),
                 )
                 .unwrap(),
+        );
+        Validator {
+            item_schemas,
+            catalog_schemas,
+            collection_schemas,
             extension_schemas: HashMap::new(),
+            compilation_options: options,
         }
     }
 
@@ -71,25 +89,79 @@ impl Validator {
         validatable.validate_with_validator(self)
     }
 
-    pub(crate) fn validate_item(&self, item: &Value) -> Result<()> {
-        self.item_schema
+    pub(crate) fn validate_item(&mut self, item: &Value) -> Result<()> {
+        let version = version(item)?;
+        self.item_schema_for(version)?
             .validate(item)
             .map_err(Error::from_validation_errors)
     }
 
-    pub(crate) fn validate_catalog(&self, item: &Value) -> Result<()> {
-        self.catalog_schema
-            .validate(item)
+    fn item_schema_for(&mut self, version: Version) -> Result<&JSONSchema> {
+        if !self.item_schemas.contains_key(&version) {
+            let schema = self.fetch_schema(&format!(
+                "https://schemas.stacspec.org/v{}/item-spec/json-schema/item.json",
+                version
+            ))?;
+            let _ = self.item_schemas.insert(version, schema);
+        }
+        Ok(self
+            .item_schemas
+            .get(&version)
+            .expect("if we didn't have it, we should have just fetched it"))
+    }
+
+    pub(crate) fn validate_catalog(&mut self, catalog: &Value) -> Result<()> {
+        let version = version(catalog)?;
+        self.catalog_schema_for(version)?
+            .validate(catalog)
             .map_err(Error::from_validation_errors)
     }
 
-    pub(crate) fn validate_collection(&self, collection: &Value) -> Result<()> {
-        self.collection_schema
+    fn catalog_schema_for(&mut self, version: Version) -> Result<&JSONSchema> {
+        if !self.catalog_schemas.contains_key(&version) {
+            let schema = self.fetch_schema(&format!(
+                "https://schemas.stacspec.org/v{}/catalog-spec/json-schema/catalog.json",
+                version
+            ))?;
+            let _ = self.catalog_schemas.insert(version, schema);
+        }
+        Ok(self
+            .catalog_schemas
+            .get(&version)
+            .expect("if we didn't have it, we should have just fetched it"))
+    }
+
+    pub(crate) fn validate_collection(&mut self, collection: &Value) -> Result<()> {
+        let version = version(collection)?;
+        self.collection_schema_for(version)?
             .validate(collection)
             .map_err(Error::from_validation_errors)
     }
 
-    pub(crate) fn validate_item_collection(&self, item_collection: &Value) -> Result<()> {
+    fn collection_schema_for(&mut self, version: Version) -> Result<&JSONSchema> {
+        if !self.collection_schemas.contains_key(&version) {
+            let schema = self.fetch_schema(&format!(
+                "https://schemas.stacspec.org/v{}/collection-spec/json-schema/collection.json",
+                version
+            ))?;
+            let _ = self.collection_schemas.insert(version, schema);
+        }
+        Ok(self
+            .collection_schemas
+            .get(&version)
+            .expect("if we didn't have it, we should have just fetched it"))
+    }
+
+    fn fetch_schema(&mut self, url: &str) -> Result<JSONSchema> {
+        let response = reqwest::blocking::get(url)?;
+        let value: Value = response.json()?;
+        let options = self.compilation_options.with_resolver(Resolver);
+        options
+            .compile(&value)
+            .map_err(|_| Error::InvalidSchema(url.to_string()))
+    }
+
+    pub(crate) fn validate_item_collection(&mut self, item_collection: &Value) -> Result<()> {
         if let Some(items) = item_collection.get("features") {
             if let Some(items) = items.as_array() {
                 let mut errors = Vec::new();
@@ -257,3 +329,13 @@ fn get_extension(href: String) -> Result<(String, JSONSchema)> {
         .map_err(Error::from_validation_error)?;
     Ok((href, schema))
 }
+
+fn version(value: &Value) -> Result<Version> {
+    value
+        .as_object()
+        .and_then(|object| object.get("stac_version"))
+        .and_then(|value| value.as_str())
+        .map(|version| version.parse())
+        .transpose()?
+        .ok_or(Error::MissingStacVersion)
+}
diff --git a/stac/CHANGELOG.md b/stac/CHANGELOG.md
index da043654..52b54e48 100644
--- a/stac/CHANGELOG.md
+++ b/stac/CHANGELOG.md
@@ -6,6 +6,15 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
 
 ## [Unreleased]
 
+### Added
+
+- `Version` enum ([#293](https://github.com/stac-utils/stac-rs/pull/293))
+
+### Changed
+
+- `STAC_VERSION` is now a `Version`, not a string ([#293](https://github.com/stac-utils/stac-rs/pull/293))
+- `version` fields on collection, catalog, and item are now public ([#293](https://github.com/stac-utils/stac-rs/pull/293))
+
 ## [0.7.2] - 2024-07-24
 
 ### Fixed
diff --git a/stac/src/catalog.rs b/stac/src/catalog.rs
index 30d39636..a8ca2006 100644
--- a/stac/src/catalog.rs
+++ b/stac/src/catalog.rs
@@ -1,4 +1,4 @@
-use crate::{Error, Extensions, Fields, Href, Link, Links, Result, STAC_VERSION};
+use crate::{Error, Extensions, Fields, Href, Link, Links, Result, Version, STAC_VERSION};
 use serde::{Deserialize, Serialize};
 use serde_json::{Map, Value};
 
@@ -28,7 +28,7 @@ pub struct Catalog {
 
     /// The STAC version the `Catalog` implements.
     #[serde(rename = "stac_version")]
-    version: String,
+    pub version: Version,
 
     /// A list of extension identifiers the `Catalog` implements.
     #[serde(rename = "stac_extensions")]
@@ -73,7 +73,7 @@ impl Catalog {
     pub fn new(id: impl ToString, description: impl ToString) -> Catalog {
         Catalog {
             r#type: CATALOG_TYPE.to_string(),
-            version: STAC_VERSION.to_string(),
+            version: STAC_VERSION,
             extensions: Vec::new(),
             id: id.to_string(),
             title: None,
diff --git a/stac/src/collection.rs b/stac/src/collection.rs
index 23c80eae..098e7ce8 100644
--- a/stac/src/collection.rs
+++ b/stac/src/collection.rs
@@ -1,4 +1,6 @@
-use crate::{Asset, Assets, Error, Extensions, Fields, Href, Link, Links, Result, STAC_VERSION};
+use crate::{
+    Asset, Assets, Error, Extensions, Fields, Href, Link, Links, Result, Version, STAC_VERSION,
+};
 use serde::{Deserialize, Serialize};
 use serde_json::{Map, Value};
 use std::collections::HashMap;
@@ -31,7 +33,7 @@ pub struct Collection {
 
     /// The STAC version the `Collection` implements.
     #[serde(rename = "stac_version")]
-    version: String,
+    pub version: Version,
 
     /// A list of extension identifiers the `Collection` implements.
     #[serde(rename = "stac_extensions")]
@@ -166,7 +168,7 @@ impl Collection {
     pub fn new(id: impl ToString, description: impl ToString) -> Collection {
         Collection {
             r#type: COLLECTION_TYPE.to_string(),
-            version: STAC_VERSION.to_string(),
+            version: STAC_VERSION,
             extensions: Vec::new(),
             id: id.to_string(),
             title: None,
diff --git a/stac/src/error.rs b/stac/src/error.rs
index 2113a9db..96173560 100644
--- a/stac/src/error.rs
+++ b/stac/src/error.rs
@@ -102,6 +102,10 @@ pub enum Error {
     #[error("unknown \"type\": {0}")]
     UnknownType(String),
 
+    /// Unsupported version.
+    #[error("unsupported version: {0}")]
+    UnsupportedVersion(String),
+
     /// [url::ParseError]
     #[error(transparent)]
     Url(#[from] url::ParseError),
diff --git a/stac/src/item.rs b/stac/src/item.rs
index f931adb8..c4eb053b 100644
--- a/stac/src/item.rs
+++ b/stac/src/item.rs
@@ -1,6 +1,8 @@
 //! STAC Items.
 
-use crate::{Asset, Assets, Error, Extensions, Fields, Href, Link, Links, Result, STAC_VERSION};
+use crate::{
+    Asset, Assets, Error, Extensions, Fields, Href, Link, Links, Result, Version, STAC_VERSION,
+};
 use chrono::{DateTime, FixedOffset, Utc};
 use geojson::{feature::Id, Feature, Geometry};
 use serde::{Deserialize, Serialize};
@@ -40,7 +42,7 @@ pub struct Item {
 
     /// The STAC version the `Item` implements.
     #[serde(rename = "stac_version")]
-    version: String,
+    pub version: Version,
 
     /// A list of extensions the `Item` implements.
     #[serde(
@@ -110,7 +112,7 @@ pub struct FlatItem {
     r#type: String,
 
     #[serde(rename = "stac_version", default = "default_stac_version")]
-    version: String,
+    version: Version,
 
     /// This column is required, but can be empty if no STAC extensions were used.
     #[serde(
@@ -369,7 +371,7 @@ impl Item {
     pub fn new(id: impl ToString) -> Item {
         Item {
             r#type: ITEM_TYPE.to_string(),
-            version: STAC_VERSION.to_string(),
+            version: STAC_VERSION,
             extensions: Vec::new(),
             id: id.to_string(),
             geometry: None,
@@ -613,7 +615,7 @@ impl Item {
         }
         Ok(FlatItem {
             r#type: ITEM_TYPE.to_string(),
-            version: STAC_VERSION.to_string(),
+            version: STAC_VERSION,
             extensions: self.extensions,
             id: self.id,
             geometry: self.geometry,
@@ -769,8 +771,8 @@ where
     crate::serialize_type(r#type, serializer, ITEM_TYPE)
 }
 
-fn default_stac_version() -> String {
-    STAC_VERSION.to_string()
+fn default_stac_version() -> Version {
+    STAC_VERSION
 }
 
 fn default_type() -> String {
@@ -782,7 +784,7 @@ mod tests {
     use super::{Builder, FlatItem, Item};
     use crate::{
         extensions::{Projection, Raster},
-        Asset, Extensions, STAC_VERSION,
+        Asset, Extensions, Version, STAC_VERSION,
     };
     use geojson::{feature::Id, Feature};
     use serde_json::Value;
@@ -998,7 +1000,7 @@ mod tests {
 
         let flat_item = FlatItem {
             r#type: "Feature".to_string(),
-            version: "1.0.0".to_string(),
+            version: Version::v1_0_0,
             extensions: Vec::new(),
             id: "an-id".to_string(),
             geometry: Some(Geometry::new(Value::Point(vec![-105.1, 41.1]))),
diff --git a/stac/src/lib.rs b/stac/src/lib.rs
index 440cf752..838ec61f 100644
--- a/stac/src/lib.rs
+++ b/stac/src/lib.rs
@@ -134,6 +134,7 @@ mod item_collection;
 pub mod link;
 pub mod media_type;
 mod value;
+mod version;
 
 pub use {
     asset::{Asset, Assets},
@@ -149,10 +150,11 @@ pub use {
     item_collection::{ItemCollection, ITEM_COLLECTION_TYPE},
     link::{Link, Links},
     value::Value,
+    version::Version,
 };
 
 /// The default STAC version supported by this library.
-pub const STAC_VERSION: &str = "1.0.0";
+pub const STAC_VERSION: Version = Version::v1_0_0;
 
 /// Custom [Result](std::result::Result) type for this crate.
 pub type Result<T> = std::result::Result<T, Error>;
diff --git a/stac/src/version.rs b/stac/src/version.rs
new file mode 100644
index 00000000..e9570c98
--- /dev/null
+++ b/stac/src/version.rs
@@ -0,0 +1,41 @@
+use crate::Error;
+use serde::{Deserialize, Serialize};
+use std::{fmt::Display, str::FromStr};
+
+/// A version of the STAC specification.
+#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize, Eq, Hash)]
+#[allow(non_camel_case_types)]
+pub enum Version {
+    /// [v1.0.0](https://github.com/radiantearth/stac-spec/releases/tag/v1.0.0)
+    #[serde(rename = "1.0.0")]
+    v1_0_0,
+
+    /// [v1.1.0-beta.1](https://github.com/radiantearth/stac-spec/releases/tag/v1.1.0-beta.1)
+    #[serde(rename = "1.1.0-beta.1")]
+    v1_1_0_beta_1,
+}
+
+impl FromStr for Version {
+    type Err = Error;
+
+    fn from_str(s: &str) -> Result<Self, Self::Err> {
+        match s {
+            "1.0.0" => Ok(Version::v1_0_0),
+            "1.1.0-beta.1" => Ok(Version::v1_1_0_beta_1),
+            _ => Err(Error::UnsupportedVersion(s.to_string())),
+        }
+    }
+}
+
+impl Display for Version {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        write!(
+            f,
+            "{}",
+            match self {
+                Version::v1_0_0 => "1.0.0",
+                Version::v1_1_0_beta_1 => "1.1.0-beta.1",
+            }
+        )
+    }
+}


Test patch:
diff --git a/stac-validate/tests/examples.rs b/stac-validate/tests/examples.rs
new file mode 100644
index 00000000..2e583c51
--- /dev/null
+++ b/stac-validate/tests/examples.rs
@@ -0,0 +1,16 @@
+use rstest::rstest;
+use stac::Value;
+use stac_validate::Validate;
+use std::path::PathBuf;
+
+#[rstest]
+fn v1_0_0(#[files("../spec-examples/v1.0.0/**/*.json")] path: PathBuf) {
+    let value: Value = stac::read(path.to_str().unwrap()).unwrap();
+    value.validate().unwrap();
+}
+
+#[rstest]
+fn v1_1_0_beta_1(#[files("../spec-examples/v1.1.0-beta.1/**/*.json")] path: PathBuf) {
+    let value: Value = stac::read(path.to_str().unwrap()).unwrap();
+    value.validate().unwrap();
+}