Repository: planetlabs/planet-client-python
Pull request #1119 (2025-04-09 22:03:53)

Support bulk subs creation in client and add --bulk to CLI to invoke it
**Related Issue(s):**

Closes #


**Proposed Changes:**

For inclusion in changelog (if applicable):

1. Adds `client.bulk_create_subscriptions()` which allows creating multiple subscriptions at once by referencing a feature collection
2. Adds support for `planet subscriptions bulk-create` to bulk create using the above mechanism

Not intended for changelog:

1. 

**Diff of User Interface**

Old behavior:

New behavior:
❯ planet subscriptions request-catalog --item-types PSScene --asset-types ortho_visual --geometry pl:features/my/adrian-test-new-guinea-10geojson-xqRXaaZ --start-time 2021-01-01 --end-time 2021-01-05 > catalog_fc_sub_source.json
❯ planet subscriptions request --name "bg test bulk sub" --source catalog_fc_sub_source.json > catalog_fc_sub.json
❯ planet subscriptions create --bulk --hosting sentinel_hub catalog_fc_sub.json

**PR Checklist:**

- [x] This PR is as small and focused as possible
- [x] If this PR includes proposed changes for inclusion in the changelog, the title of this PR summarizes those changes and is ready for inclusion in the Changelog.
- [x] I have updated docstrings for function changes and docs in the 'docs' folder for user interface / behavior changes
- [x] This PR does not break any examples or I have updated them

**(Optional) @mentions for Notifications:**


goldenberg: I've now tested this via the CLI by running:

```
❯ planet subscriptions request-catalog --item-types PSScene --asset-types ortho_visual --geometry pl:features/my/adrian-test-new-guinea-10geojson-xqRXaaZ --start-time 2021-01-01 --end-time 2021-01-05 > catalog_fc_sub_source.json
❯ planet subscriptions request --name "bg test bulk sub" --source catalog_fc_sub_source.json > catalog_fc_sub.json
❯ planet subscriptions create --bulk --hosting sentinel_hub catalog_fc_sub.json
```

And I believe it works. Needs more testing though

Patch:
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index a5b9a2e..85541bf 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -229,7 +229,7 @@ type-related bugs. The nox session that calls mypy is named analyze.
 Documentation is built from Markdown files in the `docs` directory using
 [MkDocs](https://www.mkdocs.org/) according to `mkdocs.yml`. The API reference
 is auto-populated from code docstrings. These docstrings must be in the
-[google format](https://mkdocstrings.github.io/python/usage/docstrings/google/)
+[google format](https://mkdocstrings.github.io/handlers/python/#google-style)
 (note: we use `Parameters` in our docstrings).
 
 By default, Nox builds the docs along with other CI checks. However, Nox can
diff --git a/README.md b/README.md
index f33170a..18ed81b 100644
--- a/README.md
+++ b/README.md
@@ -5,21 +5,21 @@
 
 The [Planet](https://planet.com) Software Development Kit (SDK) for Python
 provides both a Python API and a command-line interface (CLI)
-to make use of [the Planet APIs](https://docs.planet.com/develop/apis/).
+to make use of [the Planet APIs](https://developers.planet.com/docs/apis/).
 Everything you need to get started is found in our
 [online documentation](https://planet-sdk-for-python-v2.readthedocs.io/en/latest/).
 
 Version 2.0 includes support for the core workflows of the following APIs:
 
-* [Data](https://docs.planet.com/develop/apis/data/) - Search for imagery from Planet's data catalog.
-* [Orders](https://docs.planet.com/develop/apis/orders/) - Process and download or deliver imagery.
-* [Subscriptions](https://docs.planet.com/develop/apis/subscriptions/) - Set up a search to auto-process and deliver imagery.
-* [Features](https://docs.planet.com/develop/apis/features/) - Upload areas of interest to the Planet platform.
+* [Data](https://developers.planet.com/docs/data/) - Search for imagery from Planet's data catalog.
+* [Orders](https://developers.planet.com/docs/orders/) - Process and download or deliver imagery.
+* [Subscriptions](https://developers.planet.com/docs/subscriptions/) - Set up a search to auto-process and deliver imagery.
+* [Features](https://developers.planet.com/docs/apis/features/) - Upload areas of interest to the Planet platform.
 
 After the initial 2.0 release there will be additional work to support the
-remaining Planet APIs: [basemaps](https://docs.planet.com/develop/apis/basemaps/),
-[tasking](https://docs.planet.com/develop/apis/tasking/) and
-[analytics](https://docs.planet.com/develop/apis/analytics/).
+remaining Planet APIs: [basemaps](https://developers.planet.com/docs/basemaps/),
+[tasking](https://developers.planet.com/docs/tasking/) and
+[analytics](https://developers.planet.com/docs/analytics/).
 
 ## Versions and Stability
 
diff --git a/design-docs/CLI-Data.md b/design-docs/CLI-Data.md
index 843b1d6..009769c 100644
--- a/design-docs/CLI-Data.md
+++ b/design-docs/CLI-Data.md
@@ -1,7 +1,7 @@
 # Data Command-Line Interface Specification
 
 This document lays out the command-line interface to interact with the Planet
-[Data API](https://docs.planet.com/develop/apis/data/).
+[Data API](https://developers.planet.com/docs/apis/data/).
 
 ## Meta: Errors
 
diff --git a/design-docs/CLI-Orders.md b/design-docs/CLI-Orders.md
index e1ff7e9..434bccc 100644
--- a/design-docs/CLI-Orders.md
+++ b/design-docs/CLI-Orders.md
@@ -1,7 +1,7 @@
 # Orders Command-Line Interface Specification
 
 This document lays out the command-line interface to interact with the Planet
-[Orders API](https://docs.planet.com/develop/apis/orders/).
+[Orders API](https://developers.planet.com/docs/orders/).
 
 ## list
 
diff --git a/design-docs/CLI-Subscriptions.md b/design-docs/CLI-Subscriptions.md
index be835a9..e267466 100644
--- a/design-docs/CLI-Subscriptions.md
+++ b/design-docs/CLI-Subscriptions.md
@@ -1,7 +1,7 @@
 # Subscriptions Command-Line Interface Specification
 
 This documents lays out the command-line interface to interact with the 
-Planet [Subscriptions API](https://docs.planet.com/develop/apis/subscriptions/)
+Planet [Subscriptions API](https://developers.planet.com/docs/subscriptions/reference/)
 
 A subscription connects catalog sources to a data processing pipeline. It can 
 run those tools on new data when it is available. It can process existing data 
@@ -21,8 +21,8 @@ be easier to design and implement.
 
 **Essential reading:** 
 
-https://docs.planet.com/develop/apis/subscriptions/
-https://docs.planet.com/develop/apis/subscriptions/reference/
+https://developers.planet.com/docs/subscriptions/reference/
+https://developers.planet.com/docs/subscriptions/
 
 **Commands:**
 
@@ -272,10 +272,11 @@ Options:
 
 Edit a subscription, such as one with a future start date, before it starts running.
 
+https://developers.planet.com/docs/subscriptions/#edit-a-subscription mentions 
 caveats and limitations:
- * After a subscription transitions to running, changes to the start_time and item_types fields are not allowed. 
- * The edit will only apply to future item publications and deliveries and no items will be redelivered.
- *  Backfill subscriptions cannot be edited.
+ * Backfill cannot be updated.
+ * After a subscription is running, only source items can be modified, and not 
+   all of them.
 
 
 ### Interface
diff --git a/design-docs/content-plan.md b/design-docs/content-plan.md
index 5880e64..d51ef2d 100644
--- a/design-docs/content-plan.md
+++ b/design-docs/content-plan.md
@@ -13,18 +13,18 @@ For a complete list of the project board, source, and current documentation buil
 
 ## A note regarding location of qualification documentation:
 
-The SDK and CLI are low-level interfaces mirroring much of the API, itself. While this documentation should make it easy for developers to use the SDK and CLI, core Planet API concepts, clarifying content, and considerations might be better located in the core API documentation on [Planet](https://docs.planet.com/develop/apis/), and then linked to from content produced here.
+The SDK and CLI are low-level interfaces mirroring much of the API, itself. While this documentation should make it easy for developers to use the SDK and CLI, core Planet API concepts, clarifying content, and considerations might be better located in the core API documentation on [Planet](https://developers.planet.com/docs/apis/), and then linked to from content produced here.
 
 ## SSoT
 
-We are currently publishing documentation on [planet.com](https://docs.planet.com/develop/sdks/#planet-sdk-for-python-and-cli), [github.com](https://github.com/planetlabs/planet-client-python), and on [readthedocs.com](https://planet-sdk-for-python-v2.readthedocs.io). Providing a single source of truth (SSoT) ensures one definitive source of documentation, reducing the dilution of information, errors, and maintenance efforts.
+We are currently publishing documentation on [planet.com](https://developers.planet.com/docs/pythonclient/), [github.io](https://planetlabs.github.io/planet-client-python/index.html), [github wiki](https://github.com/planetlabs/planet-client-python/wiki), and on [readthedocs.com](https://planet-sdk-for-python.readthedocs.io/en/latest/). Providing a single source of truth (SSoT) ensures one definitive source of documentation, reducing the dilution of information, errors, and maintenance efforts.
 
 ### Ticket to be filed
 
 Implement mkdocs to leverage features of readthedocs.com, but publish only on one platform. This would be planet.com unless we are making a concerted effort to recruit 3rd party contributors to the SDK, in which case, it could stay on readthedocs.com. So the publication landscape would be as follows:
 
 * Publish the SDK V2 documentation on readthedocs.com.
-* Do not mirror the SDK V2 documentation on docs.planet.com.
+* Do not mirror the SDK V2 documentation on developers.planet.com.
 * End-of-life the GitHub wiki content for V2, and rely on the readme, the contributing, the changes, and the published documentation to convey information published at the wiki in 2017.
 * End-of-life the github.io channel for V2, and rely on readthedocs.com as the single source of truth.
 
@@ -42,7 +42,7 @@ Provide a getting started experience that presumes the user has not used an SDK
 
 Provide a relational visualization (e.g.: a dashboard of sorts) of the SDK, CLI, and API, and link to the landing page for each.
 
-Platform overview documentation should be created on the DevCenter to explain the SDK and CLI in the context of the other Planet offerings, within the Planet platform. (This is an internal ticket on docs.planet.com, not the SDK GitHub project issues list.) The SDK should reference this overview.
+Platform overview documentation should be created on the DevCenter to explain the SDK and CLI in the context of the other Planet offerings, within the Planet platform. (This is an internal ticket on developers.planet.com, not the SDK GitHub project issues list.) The SDK should reference this overview.
 
 ## Code snippets
 
@@ -104,7 +104,7 @@ Add a considerations section to the documentation, either to the getting started
 
 ## readme.rst
 
-The [current readme file](https://github.com/planetlabs/planet-client-python/blob/main/README.md) follows industry standards and is adequate.
+The [current readme file](https://github.com/planetlabs/planet-client-python%23readme) follows industry standards and is adequate.
 
 ### Ticket to be filed
 
@@ -193,11 +193,11 @@ Investigate using MkDocs plugin to derive changes.txt items.
 
 ### Published
 
-[Readme](https://github.com/planetlabs/planet-client-python/blob/main/README.md)
+[Readme](https://github.com/planetlabs/planet-client-python/tree/ef8a27178d21316256ef8a5de6ee6d0758be981c%23readme)
 
 [GitHub Wiki](https://github.com/planetlabs/planet-client-python/wiki)
 
-[SDK Devcenter landing page](https://docs.planet.com/)
+[SDK Devcenter landing page](https://developers.planet.com/open/)
 
 [planet · PyPI](https://pypi.org/project/planet/)
 
@@ -213,18 +213,23 @@ Investigate using MkDocs plugin to derive changes.txt items.
 
 [https://github.com/planetlabs/planet-client-python/](https://github.com/planetlabs/planet-client-python/)
 
-#### Current V2 docs
-[https://planet-sdk-for-python-v2.readthedocs.io/](https://planet-sdk-for-python-v2.readthedocs.io/)
-#### V1.4.9 docs
-[https://planet-sdk-for-python.readthedocs.io/en/latest/](https://planet-sdk-for-python.readthedocs.io)
+#### Current V2 docs (erroneously tagged V1.4.9)
+[https://planet-sdk-for-python.readthedocs.io/en/latest/](https://planet-sdk-for-python.readthedocs.io/en/latest)
+
+#### Current V1.4.9 docs
+[https://developers.planet.com/docs/pythonclient/](https://developers.planet.com/docs/pythonclient/)
 
 and
 
 [https://planetlabs.github.io/planet-client-python/index.html](https://planetlabs.github.io/planet-client-python/index.html)
 
-#### V1.4.9 docs source
+#### Current V1.4.9 docs source
 [https://github.com/planetlabs/planet-client-python/tree/master/docs](https://github.com/planetlabs/planet-client-python/tree/master/docs)
 
+and
+
+[https://github.com/planetlabs/planet-client-python//docs](https://github.com/planetlabs/planet-client-python//docs)
+
 ## GitHub flavored markdown
 
 This document was created using [GitHub flavored markdown](https://docs.github.com/en/get-started/writing-on-github/getting-started-with-writing-and-formatting-on-github/basic-writing-and-formatting-syntax#GitHub-flavored-markdown)
diff --git a/docs/cli/cli-data.md b/docs/cli/cli-data.md
index dda3167..8e745aa 100644
--- a/docs/cli/cli-data.md
+++ b/docs/cli/cli-data.md
@@ -4,11 +4,11 @@ title: CLI for Data API Tutorial
 
 ## Introduction
 
-The `planet data` CLI commands enable interaction with the [Data API](https://docs.planet.com/develop/apis/data/),
+The `planet data` CLI commands enable interaction with the [Data API](https://developers.planet.com/docs/apis/data/),
 which lets you search Planet’s catalog (including select public datasets like Sentinel 2 and Landsat 8).
 Currently the CLI has focused on the core search functionality, implementing
-[Quick Search](https://docs.planet.com/develop/apis/data/reference/#tag/Item-Search/operation/QuickSearch)
-and [stats](https://docs.planet.com/develop/apis/data/reference/#tag/Item-Stats/operation/Stats) plus some
+[Quick Search](https://developers.planet.com/docs/apis/data/reference/#tag/Item-Search/operation/QuickSearch)
+and [stats](https://developers.planet.com/docs/apis/data/reference/#tag/Item-Stats/operation/Stats) plus some
 partial saved search functionality.
 
 ## `data search` command basics
@@ -87,8 +87,8 @@ This outputs the last 100 scenes.
 
 ### Search on Item Type
 
-These first searches were done on the [PSScene](https://docs.planet.com/data/imagery/planetscope/psscene/) 'item type', but you
-can use any [Item Type](https://docs.planet.com/develop/apis/data/items/#item-types) that Planet offers in 
+These first searches were done on the [PSScene](https://developers.planet.com/docs/data/psscene/) 'item type', but you
+can use any [Item Type](https://developers.planet.com/docs/apis/data/items-assets/#item-types) that Planet offers in 
 its catalog. The item type is the first argument of the `search` command, followed by the 'filter'. Note that
 you can specify any number of item types here:
 
@@ -318,8 +318,8 @@ planet data filter --asset ortho_analytic_8b_sr --asset udm2 \
 ```
 
 You can find the list of available assets in each Item Type Page, like 
-[available assets](https://docs.planet.com/data/imagery/planetscope/psscene/) for PSScene. You can see
-[a table of all Item Types](https://docs.planet.com/develop/apis/data/items/#item-types), which links to 
+[available assets](https://developers.planet.com/docs/data/psscene/#available-asset-types) for PSScene. You can see
+[a table of all Item Types](https://developers.planet.com/docs/data/psscene/#available-asset-types), which links to 
 the page for each with their list of asset types.
 
 Note that the asset filter doesn't perform any validation, so if your searches aren't returning anything check to make
@@ -494,7 +494,7 @@ be faster for working with a small number of items & assets.
 ### Activate an Asset
 
 All items in the Data API have a list of assets. This includes the main imagery geotiff files, usually in a few
-different formats, and also accompanying files like the [Usable Data Mask](https://docs.planet.com/data/imagery/udm/)
+different formats, and also accompanying files like the [Usable Data Mask](https://developers.planet.com/docs/data/udm-2/)
  (UDM) and JSON metadata. You can't immediately download them, as they must first be created in the cloud, known as
 'activated'. To activate data you need to get its item id, plus the name of the asset - the available ones
 can be seen by looking at the Item’s JSON. Once you have the item id and asset type you can run the CLI
@@ -542,7 +542,7 @@ Download has a few different options:
 ## Saved Searches
 
 The core `planet data search` command uses what is called a 'quick search' in the API. The API 
-also supports what we call a '[saved searches](https://docs.planet.com/develop/apis/data/item-search/#saved-search)',
+also supports what we call a '[saved searches](https://developers.planet.com/docs/apis/data/quick-saved-search/#saved-search)',
 and the CLI supports this as well. 
 
 ### List Searches
diff --git a/docs/cli/cli-guide.md b/docs/cli/cli-guide.md
index 5a5701b..dc501de 100644
--- a/docs/cli/cli-guide.md
+++ b/docs/cli/cli-guide.md
@@ -110,7 +110,7 @@ One of the commands you’ll use most frequently is `planet data filter`. This 
 planet data filter --permission --std-quality
 ```
 
-Look at the console output to see some default filters. `PermissionFilter` filters the output to only contain imagery that you have permission to download. You’ll also see `quality_category`, which means the output lists only images in the [`standard quality` category](https://docs.planet.com/data/imagery/planetscope/#standard-versus-test-imagery). Without these options, an empty filter is generated which would be used to disable filtering and simply return all results.
+Look at the console output to see some default filters. `PermissionFilter` filters the output to only contain imagery that you have permission to download. You’ll also see `quality_category`, which means the output lists only images in the [`standard quality` category](https://developers.planet.com/docs/data/planetscope/#image-quality-standard-vs-test-imagery). Without these options, an empty filter is generated which would be used to disable filtering and simply return all results.
 
 !!!note "The --help switch is your friend"
     You can do a lot with this `filter` command. We recommend running `planet data filter --help` often to get a reference of how the commands work.
diff --git a/docs/cli/cli-intro.md b/docs/cli/cli-intro.md
index fd3afc1..2c9c76b 100644
--- a/docs/cli/cli-intro.md
+++ b/docs/cli/cli-intro.md
@@ -13,9 +13,9 @@ responses are all textual. For more on what a command-line is see
 ## Why would I use Planet’s CLI?
 
 Planet offers a number of ways to interact with its API’s, from 
-[Planet Explorer](https://docs.planet.com/platform/get-started/access-data/), which is a full 
-web-based GUI, to [plug-ins for QGIS](https://docs.planet.com/platform/integrations/qgis) 
-and [ArcGIS Pro](https://docs.planet.com/platform/integrations/arcgis/) for those who want
+[Planet Explorer](https://developers.planet.com/docs/apps/explorer/), which is a full 
+web-based GUI, to [plug-ins for QGIS](https://developers.planet.com/docs/integrations/qgis/) 
+and [ArcGIS Pro](https://developers.planet.com/docs/integrations/arcgis/) for those who want
 to stay in their desktop GIS environment. 
 
 The Planet CLI offers more direct interaction with the API’s, as its commands more directly
diff --git a/docs/cli/cli-orders.md b/docs/cli/cli-orders.md
index 0fe3bff..f6f85b1 100644
--- a/docs/cli/cli-orders.md
+++ b/docs/cli/cli-orders.md
@@ -4,7 +4,7 @@ title: CLI for Orders API Tutorial
 
 ## Introduction
 
-The `planet orders` command enables interaction with the [Orders API](https://docs.planet.com/develop/apis/orders/),
+The `planet orders` command enables interaction with the [Orders API](https://developers.planet.com/apis/orders/),
 which lets you activate and download Planet data products in bulk, and apply various
 'tools' to your processes. This tutorial takes you through all the main capabilities
 of the CLI for creating and downloading orders. It depends on several more advanced
@@ -143,8 +143,8 @@ planet orders get 782b414e-4e34-4f31-86f4-5b757bd062d7
 
 ### Create an Order Request
 
-To create an order you need a name, a [bundle](https://docs.planet.com/develop/apis/orders/product_bundles),
- one or more id’s, and an [item type](https://docs.planet.com/develop/apis/data/items/#item-types):
+To create an order you need a name, a [bundle](https://developers.planet.com/apis/orders/product-bundles-reference/),
+ one or more id’s, and an [item type](https://developers.planet.com/docs/apis/data/items-assets/#item-types):
 
 First lets get the ID of an item you have download access to, using the Data API:
 
@@ -199,7 +199,7 @@ planet orders request \
 ```
 
 #### Fallback bundles
-Orders API will deliver [fallback bundles](https://docs.planet.com/develop/apis/orders/sources/#fallback-bundles) if the first choice product bundle fails for any reason.  You can specify one or more fallback bundles by using the `--fallback-bundle` option which accepts a comma separated string of fallback bundles:
+Orders API will deliver [fallback bundles](https://developers.planet.com/apis/orders/scenes/#order-type-and-fallback-bundles) if the first choice product bundle fails for any reason.  You can specify one or more fallback bundles by using the `--fallback-bundle` option which accepts a comma separated string of fallback bundles:
 
 ```sh
 planet orders request \
@@ -265,7 +265,8 @@ planet orders request \
 - The --collection-id is also optional. If you decide to use this, ensure that the order request and the collection have matching bands. If you're unsure, allow the system to create a new collection for you by omitting the --collection-id option. This will ensure the newly set-up collection is configured correctly, and you can subsequently add items to this collection as needed.
 - The --create-configuration option will create a new [layer configuration](https://apps.sentinel-hub.com/dashboard/#/configurations) in Sentinel Hub on your behalf. This option cannot be used with --collection-id.
 
-For more information on Sentinel Hub hosting, see the [Orders API documentation](https://docs.planet.com/develop/apis/orders/delivery/#image-collection-sentinel-hub)
+For more information on Sentinel Hub hosting, see the [Orders API documentation](https://developers.planet.com/apis/orders/delivery/#delivery-to-sentinel-hub-collection) and the [Linking Planet User to Sentinel Hub User
+](https://support.planet.com/hc/en-us/articles/16550358397469-Linking-Planet-User-to-Sentinel-Hub-User) support post.
 
 ### Save an Order Request
 
@@ -525,7 +526,7 @@ Since clip is so heavily used it has its own dedicated command in the CLI. All
 the other tools use the `--tools` option, that points to a file. The file should
 contain JSON that follows the format for a toolchain, the "tools" section of an order.
 The toolchain options and format are given in
-[Creating Toolchains](https://docs.planet.com/develop/apis/orders/tools/#creating-toolchains).
+[Creating Toolchains](https://developers.planet.com/apis/orders/tools/#creating-toolchains).
 
 Example: `tools.json`
 ```
@@ -740,7 +741,7 @@ planet orders request \
 
 Currently this needs to be done for any 'composite' operation, as STAC output from composites is not yet
 supported (but is coming). You can explicitly add `--stac`, but it is the default, so does not need to
-be included. For more information about Planet’s STAC output see the [Orders API documentation](https://docs.planet.com/develop/apis/orders/delivery/#stac-metadata).
+be included. For more information about Planet’s STAC output see the [Orders API documentation](https://developers.planet.com/apis/orders/delivery/#stac-metadata).
 
 Orders with Google Earth Engine delivery will force the STAC flag to false.
 
@@ -749,7 +750,7 @@ Orders with Google Earth Engine delivery will force the STAC flag to false.
 Another option is to deliver your orders directly to a cloud bucket, like AWS S3 or Google Cloud Storage.
 The file given with the `--delivery` option should contain JSON that follows
 the options and format given in
-[Delivery to Cloud Storage](https://docs.planet.com/develop/apis/orders/delivery/#delivery-to-cloud-storage).
+[Delivery to Cloud Storage](https://developers.planet.com/docs/orders/delivery/#delivery-to-cloud-storage).
 
 An example would be:
 
@@ -792,7 +793,7 @@ and use the CLI to customize it.
 
 ### Basemaps Orders
 
-One of the newer features in Planet’s Orders API is the ability to [order basemaps](https://docs.planet.com/develop/apis/orders/sources/#basemaps-source-type).
+One of the newer features in Planet’s Orders API is the ability to [order basemaps](https://developers.planet.com/apis/orders/basemaps/).
 The CLI does not yet support a 'convenience' method to easily create the JSON - you unfortunately
 can't yet use `planet orders request` to help form an orders request. But all the other CLI functionality
 supports ordering basemaps through the Orders API.
diff --git a/docs/cli/cli-subscriptions.md b/docs/cli/cli-subscriptions.md
index 0e111e2..ea0c683 100644
--- a/docs/cli/cli-subscriptions.md
+++ b/docs/cli/cli-subscriptions.md
@@ -5,7 +5,7 @@ title: CLI for Subscriptions API Tutorial
 ## Introduction
 
 The `planet subscriptions` command enables interaction with the
-[Subscriptions API](https://docs.planet.com/develop/apis/subscriptions/)
+[Subscriptions API](https://developers.planet.com/apis/subscriptions/)
 that make it possible to set up a recurring search criteria. Using `planet subscriptions`, you can automatically process
 and deliver new imagery to a cloud bucket. It also has a powerful 'backfill' capability
 to bulk order historical imagery to your area of interest. This tutorial takes you
@@ -107,7 +107,7 @@ This is a full subscriptions JSON request, with the credentials redacted, so you
 to replace your own for it to work. Below we’ll show the convenience methods that will
 help create a custom one more easily. If you'd like to get things working for now then
 just replace the 'delivery' section with your cloud credentials, see the
-[core subscriptions delivery docs](https://docs.planet.com/develop/apis/subscriptions/delivery/)
+[core subscriptions delivery docs](https://developers.planet.com/docs/subscriptions/delivery/)
 for more information.
 
 To create a new subscription with the CLI, use the `create` command and the json file you just created:
@@ -140,7 +140,7 @@ The `list` command supports filtering on a variety of fields:
 * `--hosting`: Filter on subscriptions containing a hosting location (e.g. SentinelHub). Accepted values are `true` or `false`.
 * `--name-contains`: Filter on subscriptions with a name that contains the provided string.
 * `--name`: Filter on subscriptions with a specific name
-* `--source-type`: Filter by the source type of the subscription. For the full list of available source types, see [Subscription Source Types](https://docs.planet.com/develop/apis/subscriptions/sources/#catalog-source-type). Multiple source type args are allowed.
+* `--source-type`: Filter by the source type of the subscription. For the full list of available source types, see [Subscription Source Types](https://developers.planet.com/docs/subscriptions/source/#subscription-source-types). Multiple source type args are allowed.
 * `--start-time`: Filter on the subscription start time or an interval of start times.
 * `--status`: Filter on the status of the subscription. Status options include `running`, `cancelled`, `preparing`, `pending`, `completed`, `suspended`, and `failed`. Multiple status args are allowed.
 * `--updated`: Filter on the subscription update time or an interval of updated times.
@@ -217,7 +217,7 @@ You can also filter by status:
 planet subscriptions results SUBSCRIPTION_ID --status processing
 ```
 
-See the Subscriptions API documentation for the [official list of available statuses](https://docs.planet.com/develop/apis/subscriptions/#states--status-descriptions).
+See the Subscriptions API documentation for the [official list of available statuses](https://developers.planet.com/docs/subscriptions/#subscription-status).
 
 #### Results as comma-separated values (CSV)
 
@@ -247,6 +247,49 @@ planet subscriptions patch cb817760-1f07-4ee7-bba6-bcac5346343f \
     patched-attributes.json
 ```
 
+### Bulk Create Subscriptions
+
+To create many subscriptions for different geometries at once, use the `bulk-create` subcommand.
+
+This command allows submitting a bulk create request that references a feature collection defined in
+the Features API, which will create a subscription for every feature in the collection.
+
+Define a subscription that references a feature collection:
+
+```json
+{
+  "name": "new guinea psscene bulk subscription",
+  "source": {
+    "parameters": {
+      "item_types": [
+        "PSScene"
+      ],
+      "asset_types": [
+        "ortho_visual"
+      ],
+      "geometry": {
+        "type": "ref",
+        "content": "pl:features/my/test-new-guinea-10geojson-xqRXaaZ"
+      },
+      "start_time": "2021-01-01T00:00:00Z",
+      "end_time": "2021-01-05T00:00:00Z"
+    }
+  }
+}
+```
+
+And issue the `bulk-create` command with the appropriate hosting or delivery options. A link to list
+the resulting subscriptions will be returned:
+
+```sh
+planet subscriptions bulk-create --hosting sentinel_hub catalog_fc_sub.json
+{
+  "_links": {
+    "list": "https://api.planet.com/subscriptions/v1?created=2025-04-16T23%3A44%3A35Z%2F..&geom_ref=pl%3Afeatures%2Fmy%2Ftest-new-guinea-10geojson-xqRXaaZ&name=new+guinea+psscene+bulk subscription"
+  }
+}
+```
+
 ### Cancel Subscription
 
 Cancelling a subscription is simple with the CLI:
@@ -267,7 +310,7 @@ tools to process the data plus notifications on the status.
 ### Catalog Request
 
 The first place to start is the `request-catalog` command, which generates all the JSON for the
-[catalog source](https://docs.planet.com/develop/apis/subscriptions/sources/#catalog-source-type) block. The core
+[catalog source](https://developers.planet.com/docs/subscriptions/source/#catalog-source-type) block. The core
 of this is quite similar to a Data API search request, though with more required fields. The minimal
 required commands would be a request like:
 
@@ -281,8 +324,8 @@ planet subscriptions request-catalog \
 
 You request which item types you want to deliver, and the asset types for it. Note that the `asset-types` are a bit
 different than the `--bundle` command in Orders, a bundle is a set of asset-types. You can see the list of asset types
-for [PSScene](https://docs.planet.com/data/imagery/planetscope/psscene/), [SkySatCollect](https://docs.planet.com/data/imagery/skysat/item-types/skysatcollect/),
-and [SkySatScene](https://docs.planet.com/data/imagery/skysat/item-types/skysatscene/). The other item-types
+for [PSScene](https://developers.planet.com/docs/data/psscene/#available-asset-types), [SkySatCollect](https://developers.planet.com/docs/data/skysatcollect/),
+and [SkySatScene](https://developers.planet.com/docs/data/skysatscene/#available-asset-types). The other item-types
 also have similar listings of their asset types. For the required `start-time` and optional `end-time` you must
 use dates formatted as RFC 3339 or ISO 8601 formats. A nice time converter is available at [time.lol](https://time.lol/).
 Just select 'ISO 8601' (third one on the list), or 'RFC 3339' (8th on the list).
@@ -339,7 +382,7 @@ planet subscriptions request-catalog \
     --rrule 'FREQ=MONTHLY;BYMONTH=3,4,5,6,7,8,9,10'
 ```
 
-For more information on the `rrule` parameter see the [recurrence rules](https://docs.planet.com/develop/apis/subscriptions/sources/#rrule-recurrence-rule)
+For more information on the `rrule` parameter see the [recurrence rules](https://developers.planet.com/docs/subscriptions/source/#rrules-recurrence-rules)
 documentation.
 
 #### Filter
@@ -376,7 +419,7 @@ By using the `--time-range-type` you can choose to temporally filter by
 acquisition or publication time. The `--publishing-stage` option allows you to
 receive the earliest preview imagery or wait until finalized imagery is
 available. See [Catalog Source
-Types:Parameters](https://docs.planet.com/develop/apis/subscriptions/sources/#parameters)
+Types:Parameters](https://developers.planet.com/docs/subscriptions/source/#parameters)
 for more details.
 
 ```sh
@@ -414,7 +457,7 @@ Planet's catalog. The `planet subscriptions request-pv` command can construct th
 part of a Planetary Variable request like `request-catalog` does for cataloged
 imagery. Planetary Variable subscriptions come in 4 types and are further
 subdivided within these types by an identifier. See [Subscribing to Planetary
-Variables](https://docs.planet.com/develop/apis/subscriptions/sources/#planetary-variable-and-analysis-ready-source-types)
+Variables](https://developers.planet.com/docs/subscriptions/pvs-subs/#planetary-variables-types-and-ids)
 for details. To constrain data delivery by space and time, you will use the
 `--geometry`, `start-time`, and `end-time` options described above.
 
@@ -455,7 +498,7 @@ There are some other tools that are often good to include. To use more than one
 just put them in an array in the JSON:
 
 The toolchain options and format are given in
-[Supported Tools](https://docs.planet.com/develop/apis/subscriptions/tools/#tools-reference)
+[Supported Tools](https://developers.planet.com/docs/subscriptions/tools/#supported-tools)
 section of the subscriptions docs:
 
 Example: `more-tools.json`
@@ -498,7 +541,7 @@ Example: `more-tools.json`
 One other essential block is the `delivery` JSON. Like with tools there is no convenience
 method, as of yet. You must write out the JSON for this section.
 You can find the full documentation for the delivery options in
-the [Subscriptions Delivery documentation](https://docs.planet.com/develop/apis/subscriptions/delivery/).
+the [Subscriptions Delivery documentation](https://developers.planet.com/docs/subscriptions/delivery/).
 
 An example of a delivery.json file that you would save as a file to pass into the
 `subscriptions request` command is:
@@ -552,7 +595,8 @@ planet subscriptions request \
     | planet subscriptions create -
 ```
 
-For more information on Sentinel Hub hosting, see the [Subscriptions API documentation](https://docs.planet.com/develop/apis/subscriptions/delivery/#image-collection-sentinel-hub)
+For more information on Sentinel Hub hosting, see the [Subscriptions API documentation](https://developers.planet.com/docs/subscriptions/delivery/#delivery-to-sentinel-hub-collection) and the [Linking Planet User to Sentinel Hub User
+](https://support.planet.com/hc/en-us/articles/16550358397469-Linking-Planet-User-to-Sentinel-Hub-User) support post.
 
 
 #### Summaries
diff --git a/docs/cli/cli-tips-tricks.md b/docs/cli/cli-tips-tricks.md
index 7c2de01..c13b220 100644
--- a/docs/cli/cli-tips-tricks.md
+++ b/docs/cli/cli-tips-tricks.md
@@ -40,7 +40,7 @@ people will open up a desktop tool like QGIS or ArcGIS Pro and save the file. Bu
 tools that can get you back into the CLI workflow more quickly.
 
 #### Use the Features API
-Rather than using GeoJSON in the SDK, upload your GeoJSON to the [Features API](https://docs.planet.com/develop/apis/features/) and use references
+Rather than using GeoJSON in the SDK, upload your GeoJSON to the [Features API](https://developers.planet.com/docs/apis/features/) and use references
 across the system with the sdk.
 References are used in the geometry block of our services in a GeoJSON blob like:
 ```json
diff --git a/docs/get-started/get-your-planet-account.md b/docs/get-started/get-your-planet-account.md
index d324cee..3e856bd 100644
--- a/docs/get-started/get-your-planet-account.md
+++ b/docs/get-started/get-your-planet-account.md
@@ -23,7 +23,7 @@ Once in Explorer, you can select the user icon in the upper right corner to go t
 
 ### Sign up for the Planet Developer Program
 
-If you don’t have an account, but you’d like to take our APIs for a spin and see how you might intergrate Planet into your existing geospatial workflows, you can sign up for the <a href="https://learn.planet.com/developer-trial-request.html" target="_blank">Developer Program</a>.
+If you don’t have an account, but you’d like to take our APIs for a spin and see how you might intergrate Planet into your existing geospatial workflows, you can sign up for the <a href="https://developers.planet.com/devtrial/" target="_blank">Developer Program</a>.
 
 ## Authenticating with the Planet server
 
diff --git a/docs/get-started/venv-tutorial.md b/docs/get-started/venv-tutorial.md
index 8694e6d..56717c1 100644
--- a/docs/get-started/venv-tutorial.md
+++ b/docs/get-started/venv-tutorial.md
@@ -106,7 +106,7 @@ Check the version again to confirm it was installed:
 You should see a number that begins with 1.
 
 !!!note "If a version 1 doesn’t appear"
-    If you don’t see a version 1 number, then you may need to adjust your path. If you have trouble getting the version for the Planet SDK v1 that you know you’ve installed, feel free to [discuss with us](https://community.planet.com). We can troubleshoot together and then update the steps here.
+    If you don’t see a version 1 number, then you may need to adjust your path. If you have trouble getting the version for the Planet SDK v1 that you know you’ve installed, feel free to [discuss with us](https://github.com/planetlabs/planet-client-python/discussions). We can troubleshoot together and then update the steps here.
 
 #### Deactivate version 1
 
diff --git a/docs/python/async-sdk-guide.md b/docs/python/async-sdk-guide.md
index af01624..9805235 100644
--- a/docs/python/async-sdk-guide.md
+++ b/docs/python/async-sdk-guide.md
@@ -146,7 +146,7 @@ if __name__ == '__main__':
 
 ## Create an order
 
-The Orders Client mostly mirrors the [Planet Orders API](https://docs.planet.com/develop/apis/orders/reference/#tag/Orders). This SDK provides additional abilities, for example to poll for order completion and to download an entire order.
+The Orders Client mostly mirrors the [Planet Orders API](https://developers.planet.com/docs/orders/reference/#tag/Orders). This SDK provides additional abilities, for example to poll for order completion and to download an entire order.
 
 ### Create an order request
 
@@ -366,7 +366,7 @@ orders_list = [o async for o in client.list_orders()]
 ## Query the data catalog
 
 The Data Client mostly mirrors the
-[Data API](https://docs.planet.com/develop/apis/data/reference/),
+[Data API](https://developers.planet.com/docs/apis/data/reference/),
 with the only difference being the addition of functionality to activate an
 asset, poll for when activation is complete, and download the asset.
 
diff --git a/docs/python/sdk-guide.md b/docs/python/sdk-guide.md
index 56a7086..bb0a17d 100644
--- a/docs/python/sdk-guide.md
+++ b/docs/python/sdk-guide.md
@@ -184,7 +184,7 @@ def download_and_validate():
 ### Placing an Order
 
 Once you have a list of scenes you want to download, you can place an order for assets using the Orders API client. Please review
-[Items and Assets](https://docs.planet.com/develop/apis/data/items/) for a refresher on item types
+[Items and Assets](https://developers.planet.com/docs/apis/data/items-assets/) in the Developer Center for a refresher on item types
 and asset types.
 
 Use the `order_request` module to build an order request, and then use the `orders.create_order()` method to place the order.
@@ -267,7 +267,7 @@ subscription = pl.subscriptions.create_subscription(request)
 
 ### Features API Collections and Features
 
-The Python SDK now supports [Features API](https://docs.planet.com/develop/apis/features/) Collections and Features (note: in the SDK and API, Features are often referred to as items in a collection).
+The Python SDK now supports [Features API](https://developers.planet.com/docs/apis/features/) Collections and Features (note: in the SDK and API, Features are often referred to as items in a collection).
 
 Collections and Features/items that you create in in the SDK will be visible in Features API and Features Manager.
 
@@ -302,7 +302,7 @@ You can pass collection items/features directly to other SDK methods. Any method
 a Features API Feature.
 
 !!!note
-    When passing a Features API Feature to other methods, the [feature ref](https://docs.planet.com/develop/apis/features/#feature-references) will be used. This means any searches or subscriptions you create will be linked to your feature.
+    When passing a Features API Feature to other methods, the [feature ref](https://developers.planet.com/docs/apis/features/feature-references/) will be used. This means any searches or subscriptions you create will be linked to your feature.
 
 ```python
 # collection_id: the ID of a collection in Features API
diff --git a/docs/resources/index.md b/docs/resources/index.md
index ff7bdc4..9cf2d07 100644
--- a/docs/resources/index.md
+++ b/docs/resources/index.md
@@ -10,22 +10,22 @@ The following examples were created specifically to show you how to use the SDK
 
 * [data_download_multiple_assets.py](https://github.com/planetlabs/planet-client-python/blob/main/examples/data_download_multiple_assets.py) - this Python script orders, activates, and downloads two assets
 * [orders_create_and_download_multiple_orders.py](https://github.com/planetlabs/planet-client-python/blob/main/examples/orders_create_and_download_multiple_orders.py) - this Python script creates two orders, each with unique Area of Interest (AoI), preventing a combined download
-* [Planet API Python Client](https://github.com/planetlabs/notebooks/blob/master/jupyter-notebooks/Data-API/planet_python_client_introduction.ipynb) - a Python notebook to introduce Planet’s Data API and the `planet` module
+* [Planet API Python Client](https://github.com/planetlabs/notebooks/blob/master/jupyter-notebooks/data-api-tutorials/planet_python_client_introduction.ipynb) - a Python notebook to introduce Planet’s Data API and the `planet` module
 * [Orders API & Planet SDK](https://github.com/planetlabs/notebooks/blob/665f165e59f2c3584976ad2dde569c649e631c0b/jupyter-notebooks/orders_api_tutorials/Planet_SDK_Orders_demo.ipynb) - a Python notebook shows how to get started with Planet SDK and the Orders API.
 * [Analysis Ready Data Tutorial Part 1: Introduction and Best Practices](https://github.com/planetlabs/notebooks/blob/6cc220ff6db246353af4798be219ee1fe7e858b0/jupyter-notebooks/analysis-ready-data/ard_1_intro_and_best_practices.ipynb) - this Python notebook uses the SDK to prepare Analysis Ready Data.
 * [Analysis Ready Data Tutorial Part 2](https://github.com/planetlabs/notebooks/blob/6cc220ff6db246353af4798be219ee1fe7e858b0/jupyter-notebooks/analysis-ready-data/ard_2_use_case_1.ipynb) - the first use case in this Python notebook leverages the SDK’s `order_request` feature to prepare an NDVI time stack and the second use case visualizes the NDVI imagery.
 
 ### Other examples
 
-Besides the SDK-specific examples, above, you can find many examples that show how to access Planet data in the documentation and Planet School at the [Planet Developers Center](https://docs.planet.com).Also, more working examples are on the [Planet Labs Python notebooks](https://github.com/planetlabs/notebooks) on GitHub.
+Besides the SDK-specific examples, above, you can find many examples that show how to access Planet data in the documentation and Planet School at the [Planet Developers Center](https://developers.planet.com).Also, more working examples are on the [Planet Labs Python notebooks](https://github.com/planetlabs/notebooks) on GitHub.
 
 ## Planet APIs
 
 This pre-release SDK has implemented interfaces for several Planet APIs. Check out the documentation for the underlying API:
 
-* [Data](https://docs.planet.com/develop/apis/data/)
-* [Orders](https://docs.planet.com/develop/apis/orders/)
-* [Subscriptions](https://docs.planet.com/develop/apis/subscriptions/)
+* [Data](https://developers.planet.com/docs/apis/data/)
+* [Orders](https://developers.planet.com/apis/orders/)
+* [Subscriptions](https://developers.planet.com/docs/subscriptions/)
 
 ## Email Developer Relations
 
diff --git a/mkdocs.yml b/mkdocs.yml
index bed6067..2c38a97 100644
--- a/mkdocs.yml
+++ b/mkdocs.yml
@@ -1,6 +1,6 @@
 site_name: Planet SDK for Python
 site_url: https://planet-sdk-for-python-v2.readthedocs.io/en/latest/
-site_author: https://docs.planet.com
+site_author: https://developers.planet.com
 site_description: >-
   A Python library to discover and retrieve earth observation data from Planet Labs PBC.
 
diff --git a/planet/cli/subscriptions.py b/planet/cli/subscriptions.py
index 4cc65c3..8b91f0f 100644
--- a/planet/cli/subscriptions.py
+++ b/planet/cli/subscriptions.py
@@ -203,6 +203,60 @@ async def create_subscription_cmd(ctx, request, pretty, **kwargs):
         echo_json(sub, pretty)
 
 
+@subscriptions.command(name="bulk-create")  # type: ignore
+@click.argument("request", type=types.JSON())
+@click.option(
+    "--hosting",
+    type=click.Choice([
+        "sentinel_hub",
+    ]),
+    default=None,
+    help='Hosting type. Currently, only "sentinel_hub" is supported.',
+)
+@click.option("--collection-id",
+              default=None,
+              help='Collection ID for Sentinel Hub hosting. '
+              'If omitted, a new collection will be created.')
+@click.option(
+    '--create-configuration',
+    is_flag=True,
+    help='Automatically create a layer configuration for your collection. '
+    'If omitted, no configuration will be created.')
+@pretty
+@click.pass_context
+@translate_exceptions
+@coro
+async def bulk_create_subscription_cmd(ctx, request, pretty, **kwargs):
+    """Bulk create subscriptions.
+
+    Submits a bulk subscription request for creation and prints a link to list
+    the resulting subscriptions.
+
+    REQUEST is the full description of the subscription to be created. It must
+    be JSON and can be specified a json string, filename, or '-' for stdin.
+
+    Other flag options are hosting, collection_id, and create_configuration.
+    The hosting flag specifies the hosting type, the collection_id flag specifies the
+    collection ID for Sentinel Hub, and the create_configuration flag specifies
+    whether or not to create a layer configuration for your collection. If the
+    collection_id is omitted, a new collection will be created. If the
+    create_configuration flag is omitted, no configuration will be created. The
+    collection_id flag and create_configuration flag cannot be used together.
+    """
+    hosting = kwargs.get("hosting", None)
+    collection_id = kwargs.get("collection_id", None)
+    create_configuration = kwargs.get('create_configuration', False)
+
+    if hosting == "sentinel_hub":
+        hosting_info = sentinel_hub(collection_id, create_configuration)
+        request["hosting"] = hosting_info
+
+    async with subscriptions_client(ctx) as client:
+        links = await client.bulk_create_subscriptions([request])
+        # Bulk create returns just a link to an endpoint to list created subscriptions.
+        echo_json(links, pretty)
+
+
 @subscriptions.command(name='cancel')  # type: ignore
 @click.argument('subscription_id')
 @pretty
@@ -509,7 +563,7 @@ def request_pv(var_type, var_id, geometry, start_time, end_time, pretty):
     """Generate a Planetary Variable subscription source.
 
     Planetary Variables come in 4 types and are further subdivided
-    within these types. See [Subscribing to Planetary Variables](https://docs.planet.com/develop/apis/subscriptions/sources/#planetary-variable-and-analysis-ready-source-types)
+    within these types. See [Subscribing to Planetary Variables](https://developers.planet.com/docs/subscriptions/pvs-subs/#planetary-variables-types-and-ids)
     or the [OpenAPI spec](https://api.planet.com/subscriptions/v1/spec) for
     more details.
     """
diff --git a/planet/clients/features.py b/planet/clients/features.py
index e11a7e9..63ab627 100644
--- a/planet/clients/features.py
+++ b/planet/clients/features.py
@@ -30,7 +30,7 @@ class FeaturesClient:
     """Asyncronous Features API client
 
     For more information about the Features API, see the documentation at
-    https://docs.planet.com/develop/apis/features/
+    https://developers.planet.com/docs/apis/features/
 
     Example:
         ```python
diff --git a/planet/clients/orders.py b/planet/clients/orders.py
index 98ea9b9..cdee7a9 100644
--- a/planet/clients/orders.py
+++ b/planet/clients/orders.py
@@ -32,7 +32,7 @@ STATS_PATH = '/stats/orders/v2'
 ORDERS_PATH = '/orders/v2'
 BULK_PATH = '/bulk/orders/v2'
 
-# Order states https://docs.planet.com/develop/apis/orders/#states
+# Order states https://developers.planet.com/apis/orders/states/
 # this is in order of state progression except for final states
 ORDER_STATE_SEQUENCE = \
     ('queued', 'running', 'failed', 'success', 'partial', 'cancelled')
diff --git a/planet/clients/subscriptions.py b/planet/clients/subscriptions.py
index df1638c..0638ec1 100644
--- a/planet/clients/subscriptions.py
+++ b/planet/clients/subscriptions.py
@@ -1,7 +1,7 @@
 """Planet Subscriptions API Python client."""
 
 import logging
-from typing import Any, AsyncIterator, Awaitable, Dict, Optional, Sequence, TypeVar
+from typing import Any, AsyncIterator, Awaitable, Dict, Optional, Sequence, TypeVar, List
 
 from typing_extensions import Literal
 
@@ -203,6 +203,34 @@ class SubscriptionsClient:
             sub = resp.json()
             return sub
 
+    async def bulk_create_subscriptions(self, requests: List[dict]) -> Dict:
+        """
+        Create multiple subscriptions in bulk. Currently, the list of requests can only contain one item.
+
+        Args:
+            requests (List[dict]): A list of dictionaries where each dictionary
+            represents a subscription to be created.
+
+        Raises:
+            APIError: If the API returns an error response.
+            ClientError: If there is an issue with the client request.
+
+        Returns:
+            The response including a _links key to the list endpoint for use finding the created subscriptions.
+        """
+        try:
+            url = f'{self._base_url}/bulk'
+            resp = await self._session.request(
+                method='POST', url=url, json={'subscriptions': requests})
+        # Forward APIError. We don't strictly need this clause, but it
+        # makes our intent clear.
+        except APIError:
+            raise
+        except ClientError:  # pragma: no cover
+            raise
+        else:
+            return resp.json()
+
     async def cancel_subscription(self, subscription_id: str) -> None:
         """Cancel a Subscription.
 
diff --git a/planet/http.py b/planet/http.py
index b093923..2fabe24 100644
--- a/planet/http.py
+++ b/planet/http.py
@@ -370,7 +370,7 @@ class Session(BaseSession):
         in the threshold value being returned.
 
         Ref:
-        * https://docs.planet.com/develop/apis/data/#api-mechanics
+        * https://developers.planet.com/docs/data/api-mechanics/
         * https://cloud.google.com/iot/docs/how-tos/exponential-backoff
         """
         random_number_milliseconds = random.randint(0, 999) / 1000.0
diff --git a/planet/order_request.py b/planet/order_request.py
index e562f30..0a91190 100644
--- a/planet/order_request.py
+++ b/planet/order_request.py
@@ -396,7 +396,7 @@ def _tool(name: str, parameters: dict) -> dict:
     """Create the API spec representation of a tool.
 
     See [Tools and Toolchains](
-    https://docs.planet.com/develop/apis/subscriptions/tools)
+    https://developers.planet.com/docs/orders/tools-toolchains/)
     for more information on available tools and tool parameters.
 
     Parameters:
diff --git a/planet/subscription_request.py b/planet/subscription_request.py
index 8fb52a0..6856030 100644
--- a/planet/subscription_request.py
+++ b/planet/subscription_request.py
@@ -294,7 +294,7 @@ def planetary_variable_source(
     """Construct a Planetary Variable subscription source.
 
     Planetary Variables come in 4 types and are further subdivided
-    within these types. See [Subscribing to Planetary Variables](https://docs.planet.com/develop/apis/subscriptions/sources/#planetary-variable-and-analysis-ready-source-types)
+    within these types. See [Subscribing to Planetary Variables](https://developers.planet.com/docs/subscriptions/pvs-subs/#planetary-variables-types-and-ids)
     or the [OpenAPI spec](https://api.planet.com/subscriptions/v1/spec) for
     more details.
 
diff --git a/planet/sync/subscriptions.py b/planet/sync/subscriptions.py
index 72e4615..f22f899 100644
--- a/planet/sync/subscriptions.py
+++ b/planet/sync/subscriptions.py
@@ -1,6 +1,6 @@
 """Planet Subscriptions API Python client."""
 
-from typing import Any, Dict, Iterator, Optional, Sequence, Union
+from typing import Any, Dict, Iterator, Optional, Sequence, Union, List
 
 from typing_extensions import Literal
 
@@ -136,6 +136,22 @@ class SubscriptionsAPI:
         return self._client._call_sync(
             self._client.create_subscription(request))
 
+    def bulk_create_subscriptions(self, requests: List[Dict]) -> Dict:
+        """Bulk create subscriptions.
+
+        Args:
+            request (List[dict]): list of descriptions of a bulk creation.
+
+        Returns:
+            response including link to list of created subscriptions
+
+        Raises:
+            APIError: on an API server error.
+            ClientError: on a client error.
+        """
+        return self._client._call_sync(
+            self._client.bulk_create_subscriptions(requests))
+
     def cancel_subscription(self, subscription_id: str) -> None:
         """Cancel a Subscription.
 


Test patch:
diff --git a/tests/integration/test_subscriptions_api.py b/tests/integration/test_subscriptions_api.py
index 23d99d3..25b299d 100644
--- a/tests/integration/test_subscriptions_api.py
+++ b/tests/integration/test_subscriptions_api.py
@@ -122,6 +122,17 @@ create_mock = respx.mock()
 create_mock.route(M(url=TEST_URL),
                   method='POST').mock(side_effect=modify_response)
 
+bulk_create_mock = respx.mock()
+bulk_create_mock.route(
+    M(url=f'{TEST_URL}/bulk'), method='POST'
+).mock(return_value=Response(
+    200,
+    json={
+        '_links': {
+            'list': f'{TEST_URL}/subscriptions/v1?created={datetime.now().isoformat()}/&geom_ref=pl:features:test_features&name=test-sub'
+        }
+    }))
+
 update_mock = respx.mock()
 update_mock.route(M(url=f'{TEST_URL}/test'),
                   method='PUT').mock(side_effect=modify_response)
@@ -334,6 +345,18 @@ async def test_create_subscription_success():
         assert sub['name'] == 'test'
 
 
+@pytest.mark.anyio
+@bulk_create_mock
+async def test_bulk_create_subscription_success():
+    """Bulk subscription is created, description has the expected items."""
+    async with Session() as session:
+        client = SubscriptionsClient(session, base_url=TEST_URL)
+        resp = await client.bulk_create_subscriptions([{
+            'name': 'test', 'delivery': 'yes, please', 'source': 'test'
+        }])
+        assert '/subscriptions/v1?' in resp['_links']['list']
+
+
 @create_mock
 def test_create_subscription_success_sync():
     """Subscription is created, description has the expected items."""
@@ -346,6 +369,18 @@ def test_create_subscription_success_sync():
     assert sub['name'] == 'test'
 
 
+@bulk_create_mock
+def test_bulk_create_subscription_success_sync():
+    """Subscription is created, description has the expected items."""
+
+    pl = Planet()
+    pl.subscriptions._client._base_url = TEST_URL
+    resp = pl.subscriptions.bulk_create_subscriptions([{
+        'name': 'test', 'delivery': 'yes, please', 'source': 'test'
+    }])
+    assert '/subscriptions/v1?' in resp['_links']['list']
+
+
 @pytest.mark.anyio
 @create_mock
 async def test_create_subscription_with_hosting_success():
diff --git a/tests/integration/test_subscriptions_cli.py b/tests/integration/test_subscriptions_cli.py
index dcdaf29..b911f7d 100644
--- a/tests/integration/test_subscriptions_cli.py
+++ b/tests/integration/test_subscriptions_cli.py
@@ -25,6 +25,7 @@ from planet.cli import cli
 from test_subscriptions_api import (api_mock,
                                     cancel_mock,
                                     create_mock,
+                                    bulk_create_mock,
                                     failing_api_mock,
                                     get_mock,
                                     patch_mock,
@@ -138,6 +139,28 @@ def test_subscriptions_create_success(invoke, cmd_arg, runner_input):
     assert result.exit_code == 0  # success.
 
 
+@pytest.mark.parametrize('cmd_arg, runner_input',
+                         [('-', json.dumps(GOOD_SUB_REQUEST)),
+                          (json.dumps(GOOD_SUB_REQUEST), None),
+                          ('-', json.dumps(GOOD_SUB_REQUEST_WITH_HOSTING)),
+                          (json.dumps(GOOD_SUB_REQUEST_WITH_HOSTING), None)])
+@bulk_create_mock
+def test_subscriptions_bulk_create_success(invoke, cmd_arg, runner_input):
+    """Subscriptions creation succeeds with a valid subscription request."""
+
+    # The "-" argument says "read from stdin" and the input keyword
+    # argument specifies what bytes go to the runner's stdin.
+    result = invoke(
+        ['bulk-create', cmd_arg],
+        input=runner_input,
+        # Note: catch_exceptions=True (the default) is required if we want
+        # to exercise the "translate_exceptions" decorator and test for
+        # failure.
+        catch_exceptions=True)
+
+    assert result.exit_code == 0  # success.
+
+
 # Invalid JSON.
 BAD_SUB_REQUEST = '{0: "lolwut"}'