Destinations API Overview
The Planet Destinations API enables users to securely store and manage cloud storage buckets and credentials as Destinations on Planet Insights Platform. Storing credentials once and referencing them later streamlines data delivery workflows with improved efficiency and security.
Destinations for the following cloud storage services are supported:
- Amazon S3
- Google Cloud Storage
- Microsoft Azure Blob Storage
- Oracle Cloud Storage
- Any service that implements the S3 compatibility API
Limitations and Access Control
The Destinations API has the following organizational constraints:
-
Destination Quota: Each organization can create up to 50 destinations.
-
Visibility and Usage: All destinations are visible to and can be used by any member of an organization.
-
Modification Permissions: Only the owner (creator) of a destination or an organization administrator can modify a destination.
-
Unique Names: Destinations names must be unique within an organization. If a name is not specified during creation, the bucket or container name is used by default. The uniqueness constraint applies regardless of whether a name was provided or the default was used.
Rate Limits
All Destinations API endpoints are rate limited to 3 requests per second per user. Learn about rate limits in the Rate Limits Overview.
Permissions
For all cloud storage providers, credentials with both write and delete permissions must be used.
When a destination is created or updated, Planet verifies access by attempting to write and then delete a test file named planetverify.txt
. If the permissions are correctly configured, this file will be removed immediately and will not appear in the storage bucket or container.
If a lingering planetverify.txt
file is found, it may indicate that Planet has write access but lacks delete permissions. In that case, check the bucket policy or access control settings to ensure Planet has both write and delete access.
Destination credentials are not revalidated when referenced in other APIs. If credentials expire or change, update them via the Destinations API to avoid delivery failures.
Destination References
Destination references are unique identifiers for cloud storage destinations. Like Feature References, they allow users to reference a destination in Planet API requests without repeatedly providing cloud storage credentials.
The destination reference ID is included in the destination’s metadata under the pl:ref
property. For example:
pl:destinations/my-azure-destination-BzFRgmr
pl:destinations/my-s3-destination-CKxV9io
A destination may be referenced using either the full ID (pl:destinations/my-azure-destination-BzFRgmr
) or the short ID (pl:destinations/BzFRgmr
).
Both formats are valid and function identically. However, we recommend using the full format, as it improves readability, especially when working with multiple destinations.
Destination references can be used in the following Planet APIs:
- Orders API: When placing orders for Planet data.
- Subscriptions API: When creating or managing data subscriptions.
Examples
For detailed specifications for each request type, refer to the API Reference.
All examples below use placeholder values such as IDs, bucket names, and credentials that must be replaced with actual values before execution.
Create Destination
Amazon S3
For Amazon S3 delivery use an AWS account with GetObject
, PutObject
, and DeleteObject
permissions.
- CURL
- CLI
- Python SDK
curl -X POST https://api.planet.com/destinations/v1 \
-H "Authorization: api-key $PL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "my s3 destination",
"type": "s3",
"parameters": {
"bucket": "$BUCKET",
"aws_region": "$REGION",
"aws_access_key_id": "$AWS_ACCESS_KEY_ID",
"aws_secret_access_key": "$AWS_SECRET_ACCESS_KEY"
}
}'
planet destinations create s3 \
--bucket $BUCKET \
--region $REGION \
--access-key-id $ACCESS_KEY_ID \
--secret-access-key $SECRET_ACCESS_KEY \
--name my-s3-destination \
--pretty
from planet.sync import Planet
from planet.exceptions import APIError, ClientError
pl = Planet()
req = {
"name": "my s3 destination",
"type": "amazon_s3",
"parameters": {
"bucket": "<example-bucket>",
"aws_region": "<example-region>",
"aws_access_key_id": "<example-aws-access-key-id>",
"aws_secret_access_key": "<example-example-aws-secret-access-key>",
},
}
try:
d = pl.destinations.create_destination(req)
print(f"Destination: {d['id']}")
print(f" - created: {d['created']}")
print(f" - type: {d['type']}")
print(f" - pl:ref: {d['pl:ref']}")
except APIError as e:
print(f"API Error: {e}")
except ClientError as e:
print(f"Client Error: {e}")
except Exception as e:
print(f"An unexpected error occurred: {e}")
Google Cloud Storage
For Google Cloud Storage delivery, a service account with storage.objects.create
, storage.objects.get
, and storage.objects.delete
permissions is required.
Access should be restricted to the specified delivery path, without read or write permissions to other storage locations.
The Google Cloud Storage delivery option requires a single-line base64 version of the service account credentials for use by the credentials
parameter.
Download the service account credentials in JSON format (not P12) and encode them as a base64 string, use a command line operation such as:
cat my_creds.json | base64 | tr -d '\n'
- CURL
- CLI
- Python SDK
curl -X POST https://api.planet.com/destinations/v1 \
-H "Authorization: api-key $PL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "my gcs destination",
"type": "google_cloud_storage",
"parameters": {
"bucket": "$BUCKET",
"credentials": "$CREDENTIALS"
}
}'
planet destinations create gcs \
--bucket $BUCKET \
--credentials $CREDENTIALS \
--name my-gcs-destination \
--pretty
from planet.sync import Planet
from planet.exceptions import APIError, ClientError
pl = Planet()
req = {
"name": "my gcs destination",
"type": "google_cloud_storage",
"parameters": {
"bucket": "<example-bucket>",
"credentials": "<example-credentials>",
},
}
try:
d = pl.destinations.create_destination(req)
print(f"Destination: {d['id']}")
print(f" - created: {d['created']}")
print(f" - type: {d['type']}")
print(f" - pl:ref: {d['pl:ref']}")
except APIError as e:
print(f"API Error: {e}")
except ClientError as e:
print(f"Client Error: {e}")
except Exception as e:
print(f"An unexpected error occurred: {e}")
Microsoft Azure Blob Storage
For Microsoft Azure delivery use an Azure account with read
, write
, delete
, and list
permissions.
- CURL
- CLI
- Python SDK
curl -X POST https://api.planet.com/destinations/v1 \
-H "Authorization: api-key $PL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "my azure destination",
"type": "azure_blob_storage",
"parameters": {
"account": "$ACCOUNT",
"container": "$CONTAINER",
"sas_token": "$SAS_TOKEN"
}
}'
planet destinations create azure \
--container $CONTAINER \
--account $ACCOUNT \
--sas-token $SAS_TOKEN \
--name my-azure-destination \
--pretty
from planet.sync import Planet
from planet.exceptions import APIError, ClientError
pl = Planet()
req = {
"name": "my azure destination",
"type": "azure_blob_storage",
"parameters": {
"account": "<example-account",
"container": "<example-container>",
"sas_token": "<example-sas-token>",
# "storage_endpoint_suffix": "<example-storage-endpoint-suffix>", # optional
},
}
try:
d = pl.destinations.create_destination(req)
print(f"Destination: {d['id']}")
print(f" - created: {d['created']}")
print(f" - type: {d['type']}")
print(f" - pl:ref: {d['pl:ref']}")
except APIError as e:
print(f"API Error: {e}")
except ClientError as e:
print(f"Client Error: {e}")
except Exception as e:
print(f"An unexpected error occurred: {e}")
Oracle Cloud Storage
For Oracle Cloud Storage delivery, use an Oracle account with read
, write
, and delete
permissions. For authentication, use a Customer Secret Key which consists of an Access Key/Secret Key pair.
- CURL
- CLI
- Python SDK
curl -X POST https://api.planet.com/destinations/v1 \
-H "Authorization: api-key $PL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "my oracle destination",
"type": "oracle_cloud_storage",
"parameters": {
"bucket": "$BUCKET",
"region": "$REGION",
"namespace": "$NAMESPACE",
"customer_access_key_id": "$CUSTOMER_ACCESS_KEY_ID",
"customer_secret_key": "$CUSTOMER_SECRET_KEY"
},
}'
planet destinations create ocs \
--bucket $BUCKET \
--access-key-id $ACCESS_KEY_ID \
--secret-access-key $SECRET_ACCESS_KEY \
--namespace $NAMESPACE \
--region $REGION \
--name my-ocs-destination \
--pretty
from planet.sync import Planet
from planet.exceptions import APIError, ClientError
pl = Planet()
req = {
"name": "my ocs destination",
"type": "oracle_cloud_storage",
"parameters": {
"bucket": "<example-bucket>",
"region": "<example-region>",
"namespace": "<example-namespace>",
"customer_access_key_id": "<example-customer-access-key-id>",
"customer_secret_key": "<example-customer-secret-key>",
},
}
try:
d = pl.destinations.create_destination(req)
print(f"Destination: {d['id']}")
print(f" - created: {d['created']}")
print(f" - type: {d['type']}")
print(f" - pl:ref: {d['pl:ref']}")
except APIError as e:
print(f"API Error: {e}")
except ClientError as e:
print(f"Client Error: {e}")
except Exception as e:
print(f"An unexpected error occurred: {e}")
S3 Compatible
S3 compatible delivery allows data to be sent to any cloud storage provider that supports the Amazon S3 API.
To use this delivery method, use an account with read
, write
, and delete
permissions on the target bucket. Authentication is performed using an Access Key and Secret Key pair.
While this delivery method is designed to work with any S3-compatible provider, not all integrations have been explicitly tested. Some providers may advertise S3 compatibility but deviate from the API in subtle ways that can cause issues. We encourage testing ensure compatibility.
Pay particular attention to the use_path_style
parameter, as it is a common source of issues. For example, Oracle Cloud requires use_path_style
to be true
, while Open Telekom Cloud requires it to be false
.
- CURL
- CLI
- Python SDK
curl -X POST https://api.planet.com/destinations/v1 \
-H "Authorization: api-key $PL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "my s3 compatible destination",
"type": "s3_compatible",
"parameters": {
"bucket": "$BUCKET",
"region": "$REGION",
"endpoint": "$ENDPOINT",
"access_key_id": "$ACCESS_KEY_ID",
"secret_access_key": "$SECRET_ACCESS_KEY"
},
}'
planet destinations create s3-compatible \
--bucket $BUCKET \
--endpoint $ENDPOINT \
--region $REGION \
--access-key-id $ACCESS_KEY_ID \
--secret-access-key $SECRET_ACCESS_KEY \
--name my-s3-compatible-destination \
--pretty
from planet.sync import Planet
from planet.exceptions import APIError, ClientError
pl = Planet()
req = {
"name": "my s3 compatible destination",
"type": "s3_compatible",
"parameters": {
"bucket": "<example-bucket>",
"region": "<example-region>",
"endpoint": "<example-endpoint>",
"access_key_id": "<example-access-key-id>",
"secret_access_key": "<example-secret-access-key>",
# "use_path_style": True # optional
},
}
try:
d = pl.destinations.create_destination(req)
print(f"Destination: {d['id']}")
print(f" - created: {d['created']}")
print(f" - type: {d['type']}")
print(f" - pl:ref: {d['pl:ref']}")
except APIError as e:
print(f"API Error: {e}")
except ClientError as e:
print(f"Client Error: {e}")
except Exception as e:
print(f"An unexpected error occurred: {e}")
Get Destination
- CURL
- CLI
- Python SDK
curl -X GET https://api.planet.com/destinations/v1/my-s3-destination-CKxV9io \
-H "Authorization: api-key $PL_API_KEY"
planet destinations get my-s3-destination-CKxV9io --pretty
from planet.sync import Planet
from planet.exceptions import APIError, ClientError
pl = Planet()
destination_id = "my-s3-destination-CKxV9io"
try:
d = pl.destinations.get_destination(destination_id)
print(f"Destination: {d['id']}")
print(f" - created: {d['created']}")
print(f" - type: {d['type']}")
print(f" - pl:ref: {d['pl:ref']}")
except APIError as e:
print(f"API Error: {e}")
except ClientError as e:
print(f"Client Error: {e}")
except Exception as e:
print(f"An unexpected error occurred: {e}")
Modify Destination
Parameters
When updating destination parameters, only the authentication credentials can be modified. Structural properties like bucket name, region, or storage provider cannot be changed. If such an update is required, create a new destination.
Amazon S3
- CURL
- CLI
- Python SDK
curl -X PATCH https://api.planet.com/destinations/v1/my-s3-destination-CKxV9io \
-H "Authorization: api-key $PL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"parameters": {
"aws_access_key_id": "$AWS_ACCESS_KEY_ID",
"aws_secret_access_key": "$AWS_SECRET_ACCESS_KEY"
}
}'
planet destinations update s3 \
my-s3-destination-CKxV9io \
--access-key-id $ACCESS_KEY_ID \
--secret-access-key $SECRET_ACCESS_KEY \
--pretty
from planet.sync import Planet
from planet.exceptions import APIError, ClientError
pl = Planet()
req = {
"parameters": {
"aws_access_key_id": "<example-aws-access-key-id>",
"aws_secret_access_key": "<example-example-aws-secret-access-key>",
}
}
destination_id = "my-s3-destination-CKxV9io"
try:
d = pl.destinations.patch_destination(destination_id, req)
print(f"Destination: {d['id']}")
print(f" - updated: {d['updated']}")
print(f" - type: {d['type']}")
print(f" - pl:ref: {d['pl:ref']}")
except APIError as e:
print(f"API Error: {e}")
except ClientError as e:
print(f"Client Error: {e}")
except Exception as e:
print(f"An unexpected error occurred: {e}")
Google Cloud Storage
- CURL
- CLI
- Python SDK
curl -X PATCH https://api.planet.com/destinations/v1/my-gcs-destination-9dhkZ6n \
-H "Authorization: api-key $PL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"parameters": {
"credentials": "$CREDENTIALS"
}
}'
planet destinations update gcs \
my-gcs-destination-9dhkZ6n \
--credentials $CREDENTIALS \
--pretty
from planet.sync import Planet
from planet.exceptions import APIError, ClientError
pl = Planet()
req = {"parameters": {"credentials": "<example-credentials>"}}
destination_id = "my-gcs-destination-9dhkZ6n"
try:
d = pl.destinations.patch_destination(destination_id, req)
print(f"Destination: {d['id']}")
print(f" - updated: {d['updated']}")
print(f" - type: {d['type']}")
print(f" - pl:ref: {d['pl:ref']}")
except APIError as e:
print(f"API Error: {e}")
except ClientError as e:
print(f"Client Error: {e}")
except Exception as e:
print(f"An unexpected error occurred: {e}")
Microsoft Azure Blob Storage
- CURL
- CLI
- Python SDK
curl -X PATCH https://api.planet.com/destinations/v1/my-azure-destination-d9k1nz4s \
-H "Authorization: api-key $PL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"parameters": {
"sas_token": "$SAS_TOKEN"
}
}'
planet destinations update azure \
my-azure-destination-d9k1nz4s \
--sas-token $SAS_TOKEN \
--pretty
from planet.sync import Planet
from planet.exceptions import APIError, ClientError
pl = Planet()
req = {"parameters": {"sas_token": "<example-sas-token>"}}
destination_id = "my-azure-destination-d9k1nz4s"
try:
d = pl.destinations.patch_destination(destination_id, req)
print(f"Destination: {d['id']}")
print(f" - updated: {d['updated']}")
print(f" - type: {d['type']}")
print(f" - pl:ref: {d['pl:ref']}")
except APIError as e:
print(f"API Error: {e}")
except ClientError as e:
print(f"Client Error: {e}")
except Exception as e:
print(f"An unexpected error occurred: {e}")
Oracle Cloud Storage
- CURL
- CLI
- Python SDK
curl -X PATCH https://api.planet.com/destinations/v1/my-oracle-destination-1mxhd5t \
-H "Authorization: api-key $PL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"parameters": {
"customer_access_key_id": "$CUSTOMER_ACCESS_KEY_ID",
"customer_secret_key": "$CUSTOMER_SECRET_KEY"
},
}'
planet destinations update ocs \
my-oracle-destination-1mxhd5t \
--access-key-id $ACCESS_KEY_ID \
--secret-access-key $SECRET_ACCESS_KEY \
--pretty
from planet.sync import Planet
from planet.exceptions import APIError, ClientError
pl = Planet()
req = {
"parameters": {
"customer_access_key_id": "<example-customer-access-key-id>",
"customer_secret_key": "<example-customer-secret-key>",
}
}
destination_id = "my-oracle-destination-1mxhd5t"
try:
d = pl.destinations.patch_destination(destination_id, req)
print(f"Destination: {d['id']}")
print(f" - updated: {d['updated']}")
print(f" - type: {d['type']}")
print(f" - pl:ref: {d['pl:ref']}")
except APIError as e:
print(f"API Error: {e}")
except ClientError as e:
print(f"Client Error: {e}")
except Exception as e:
print(f"An unexpected error occurred: {e}")
S3 Compatible
- CURL
- CLI
- Python SDK
curl -X PATCH https://api.planet.com/destinations/v1/my-s3-compatible-destination-diwn7xm \
-H "Authorization: api-key $PL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"parameters": {
"access_key_id": "$ACCESS_KEY_ID",
"secret_access_key": "$SECRET_ACCESS_KEY"
},
}'
planet destinations update s3-compatible \
my-s3-compatible-destination-diwn7xm \
--access-key-id $ACCESS_KEY_ID \
--secret-access-key $SECRET_ACCESS_KEY \
--pretty
from planet.sync import Planet
from planet.exceptions import APIError, ClientError
pl = Planet()
req = {
"parameters": {
"access_key_id": "<example-access-key-id>",
"secret_access_key": "<example-secret-access-key>",
}
}
destination_id = "my-s3-compatible-destination-diwn7xm"
try:
d = pl.destinations.patch_destination(destination_id, req)
print(f"Destination: {d['id']}")
print(f" - updated: {d['updated']}")
print(f" - type: {d['type']}")
print(f" - pl:ref: {d['pl:ref']}")
except APIError as e:
print(f"API Error: {e}")
except ClientError as e:
print(f"Client Error: {e}")
except Exception as e:
print(f"An unexpected error occurred: {e}")
Rename Destination
Renaming a destination is purely cosmetic and has no effect on existing workflows.
- CURL
- CLI
- Python SDK
curl -X PATCH https://api.planet.com/destinations/v1/my-s3-destination-CKxV9io \
-H "Authorization: api-key $PL_API_KEY" \
-H "Content-Type: application/json" \
-d '{"name": "A New Name"}'
planet destinations rename my-s3-destination-CKxV9io "a new name" --pretty
from planet.sync import Planet
from planet.exceptions import APIError, ClientError
pl = Planet()
req = {"name": "a new name"}
destination_id = "my-s3-destination-CKxV9io"
try:
resp = pl.destinations.patch_destination(destination_id, req)
print(f"Destination: {d['id']}")
print(f" - updated: {d['updated']}")
print(f" - name: {d['name']}")
print(f" - type: {d['type']}")
print(f" - pl:ref: {d['pl:ref']}")
except APIError as e:
print(f"API Error: {e}")
except ClientError as e:
print(f"Client Error: {e}")
except Exception as e:
print(f"An unexpected error occurred: {e}")
Archive Destination
Archiving a destination removes it from the default list view and has no affect on existing workflows. However, archived destinations cannot be used to create new orders or subscriptions. Archived destinations do not count toward an organization's quota of 50 destinations.
- CURL
- CLI
- Python SDK
curl -X PATCH https://api.planet.com/destinations/v1/my-s3-destination-CKxV9io \
-H "Authorization: api-key $PL_API_KEY" \
-H "Content-Type: application/json" \
-d '{"archive": true}' // unarchive with false
planet destinations archive my-s3-destination-CKxV9io --pretty
from planet.sync import Planet
from planet.exceptions import APIError, ClientError
pl = Planet()
req = {"archive": True}
destination_id = "my-s3-destination-CKxV9io"
try:
d = pl.destinations.patch_destination(destination_id, req)
print(f"Destination: {d['id']}")
print(f" - archived: {d['archived']}")
print(f" - type: {d['type']}")
print(f" - pl:ref: {d['pl:ref']}")
except APIError as e:
print(f"API Error: {e}")
except ClientError as e:
print(f"Client Error: {e}")
except Exception as e:
print(f"An unexpected error occurred: {e}")
List Destinations
- CURL
- CLI
- Python SDK
curl -X GET https://api.planet.com/destinations/v1 \
-H "Authorization: api-key $PL_API_KEY"
planet destinations list --pretty
from planet.sync import Planet
from planet.exceptions import APIError, ClientError
pl = Planet()
try:
resp = pl.destinations.list_destinations()
destinations = resp["destinations"]
print(f"Found {len(destinations)} destinations:")
for d in destinations:
print(f"Destination: {d['id']}")
print(f" - created: {d['created']}")
print(f" - type: {d['type']}")
print(f" - pl:ref: {d['pl:ref']}")
except APIError as e:
print(f"API Error: {e}")
except ClientError as e:
print(f"Client Error: {e}")
except Exception as e:
print(f"An unexpected error occurred: {e}")
Filter options: The following query parameters can filter the destinations list:
?is_owner=true
- Show only destinations created by the requesting user.?can_write=true
- Show only destinations that the requesting user can modify.?archived=true
- Include archived destinations in the response.
Subscriptions API
To create a subscription using a destination, use the following delivery format:
- JSON
"delivery": {
"type": "destination",
"parameters": {
"ref": "pl:destinations/my-s3-destination-CKxV9io",
"path_prefix": "planet-scenes" // optional path prefix
}
}
To filter subscriptions by their associated destination, use the destination_ref
query parameter with the List Subscriptions endpoint:
- CURL
- CLI
curl -X GET "https://api.planet.com/subscriptions/v1?destination_ref=pl:destinations/my-s3-destination-CKxV9io" \
--include \
-H "Authorization: api-key $PL_API_KEY"
planet subscriptions list --destination-ref my-s3-destination-CKxV9io
Orders API
To create a order using a destination, use the following delivery format:
- JSON
"delivery": {
"destination": {
"ref": "pl:destinations/my-s3-destination-CKxV9io",
"path_prefix": "planet-scenes" // optional path prefix
}
}
To filter orders by their associated destination, use the destination_ref
query parameter with the List Orders endpoint:
- CURL
- CLI
curl -X GET "https://api.planet.com/compute/ops/orders/v2?destination_ref=pl:destinations/my-s3-destination-CKxV9io" \
--include \
-H "Authorization: api-key $PL_API_KEY"
planet orders list --destination-ref my-s3-destination-CKxV9io