AWS Marketplace

Automating updates to your Single AMI listings in AWS Marketplace with Catalog API

Catalog API for AWS Marketplace enables you as a seller to manage your listings more seamlessly. It is currently available for software packaged as single Amazon Machine Images (AMI) or containers. If you have AMI or container products listed in AWS Marketplace, you can now add new versions and, in the case of containers, repositories. You can also restrict old versions and update information about the product or its versions. You can also use the Catalog API to check the status of your request and retrieve product details.

Using Catalog API to manage your AMI product

Using the Catalog API helps you automate your publishing pipelines. Until now, when you needed to new versions of your single AMI product to your AWS Marketplace listing, you had to manually submit those changes. Now, you can integrate your release process or continuous integration/continuous delivery (CI/CD) pipelines with Catalog API to automate this process. Furthermore, if you have a large catalog and update your listings frequently, using the Catalog API can help you streamline and reduce time dedicated to the update process.

In this post, I will show you how to use Catalog API to programmatically update product details, add new AMI versions, update version details, and restrict specific versions.

Solution walkthrough

This solution walkthrough includes the following sections:

  • Prerequisites
  • A. Updating product details
  • B. Describing update status
  • C. Adding a new AMI version
  • D. Describing AMI details
  • E. Updating AMI version details
  • F. Restricting an AMI version

Prerequisites

  1. Find your Product ID. As a seller, the first thing you need is to find the Product ID of your product. To find your Product ID, go to the AWS Marketplace Management Portal for Server products. In your list of current server products, choose the product you want to update using Catalog API and copy the Product ID. You can also use ListEntities API with the EntityType set to AmiProduct.

The Product ID is only available after your single-AMI product is in the limited state in AWS Marketplace. Products in the limited state are visible only to your seller AWS account and test accounts you specify. All new products are first published into the limited state for testing before they are made publicly available in AWS Marketplace. For more information on submitting your product, please visit the Seller guide on single-AMI products.

  1. Verify permissions. Make sure the IAM user or role you are using has the proper permissions to manage your products in AWS Marketplace. You can attach either the AWSMarketplaceSellerFullAccess or AWSMarketplaceSellerProductsFullAccess described in Policies and permissions for AWS Marketplace sellers of the seller guide. Alternatively, you can grant the user or role least privilege by granting only the permissions required to perform the API calls for Catalog API. To view the specific IAM actions for Catalog API, see the actions table in Actions, resources, and condition keys for AWS Marketplace Catalog.

Catalog API clients are available in multiple AWS Software Development Keys (AWS SDKs).

  1. AWS CloudShell and AWS CLI. The following walkthrough uses AWS CloudShell, a browser-based shell with AWS Command Line Interface (AWS CLI) pre-installed in the seller AWS account. Because AWS CloudShell inherits the credentials of the user signed in to the AWS Management Console, make sure to log in with a user that has permissions to manage your products.
  2. An application to convert JSON objects into JSON strings. The following walkthrough uses the command line application jq to convert JSON objects into JSON strings. jq is pre-installed in AWS CloudShell, but can also be installed with many package managers. For example, you can run sudo yum install -y jq on Amazon Linux 2 or sudo apt-get install -y jq on Ubuntu.

A. Updating product details

In this first section, I show how to make changes to your product details using the StartChangeSet API with the change type UpdateInformation.

Here is a sample product that has the following details:

  • Product title: My AMI Product
  • Short description: My AMI product that makes it simple to do something.
  • Long description: My AMI product that makes it simple to do something. For some industries, it’s been reported that this solution increases productivity by 10 times.

The following screenshot shows the product detail page for My AMI Product with those short and long descriptions.


In this exercise, you will only update the title, short description, and long description of this product. You can update other product details as well. See the Catalog API documentation for a full list of product details that you can change. Any details omitted in your request will use the values in the latest version.

To update the product details, do the following steps in AWS CloudShell, replacing the values in italics with values specific to your product.

  1. Set a variable to the product ID of your product. To find your product ID, refer to the Prerequisites section.
    PRODUCT_ID="example1-abcd-1234-5ef6-7890abcdef12";
  2. Set a variable to a JSON object that includes the details that you want to change.
    DETAILS_JSON='{
      "ProductTitle": "My AMI Product Updated",
      "ShortDescription": "My AMI product short description updated.",
      "LongDescription": "My AMI product long description updated."
    }';
  3. To pass this JSON object through Catalog API, you must convert the JSON object into a JSON string so that you can nest it into another JSON object as a string. Run the following command and use jq to do the conversion and set the output to another variable called DETAILS_JSON_STRING.
    DETAILS_JSON_STRING="$(echo "${DETAILS_JSON}" | jq 'tostring';)";

    Optionally, you can view the value of the converted JSON string by running the command echo "${DETAILS_JSON_STRING}". The following is an example of that JSON object after the conversion to a JSON string with the JSON control characters properly escaped.

    "{\"ProductTitle\":\"My AMI Product Updated\",\"ShortDescription\":\"My AMI product short description updated.\",\"LongDescription\":\"My AMI product long description updated.\"}"

  4. Run the following AWS CLI command for StartChangeSet API with the variables PRODUCT_ID and DETAILS_JSON_STRING from steps A.1 and 3. Use UpdateInformation as the change type. This starts a change set to update the product information.
    aws marketplace-catalog start-change-set \
    --catalog "AWSMarketplace" \
    --change-set '[
      {
        "ChangeType": "UpdateInformation",
        "Entity": {
          "Identifier": "'"${PRODUCT_ID}"'",
          "Type": "AmiProduct@1.0"
        },
        "Details": '"${DETAILS_JSON_STRING}"'
      }
    ]';

    After running the commands, your output should include the change set ID and the change set Amazon Resource Number (ARN). The change set ID in the following result is example123456789012abcdef.

    {
      "ChangeSetId": "example123456789012abcdef",
      "ChangeSetArn": "arn:aws:aws-marketplace:us-east-1:123456789012:AWSMarketplace/ChangeSet/example123456789012abcdef"
    }

You have now started a change set to change the title, short description, and long description of your product. Change sets take time to apply. In the following section, you check its status.

B. Describing update status

After starting a change set, you can check its status by calling the DescribeChangeSet API with the change set ID returned in the StartChangeSet API response.

To check the status of your change set, run the following command in AWS CloudShell, but replace the value in italics with the change set ID you got in step A.4.

  1. Run the following AWS CLI command with your change set ID.
    aws marketplace-catalog describe-change-set \
    --catalog "AWSMarketplace" \
    --change-set-id "example123456789012abcdef";
  2. Change sets take time, so run this command in intervals until the change set succeeds or fails.

When the change set succeeds, the Status property in the JSON output has a value of SUCCEEDED. The following is an example response of a successful change set that has been edited for brevity.

{
  "ChangeSetId": "example123456789012abcdef",
  "ChangeSetArn": "arn:aws:aws-marketplace:us-east-1:123456789012:AWSMarketplace/ChangeSet/example123456789012abcdef",
...
  "Status": "SUCCEEDED",
...
  "ChangeSet": [
    {
      "ChangeType": "UpdateInformation",
      "Entity": {
        "Type": "AmiProduct@1.0",
        "Identifier": "example1-abcd-1234-5ef6-7890abcdef12"
      },
      "Details": "{\"ProductTitle\":\"My AMI Product Updated\",\"ShortDescription\":\"My AMI product short description updated.\",\"LongDescription\":\"My AMI product long description updated.\"}",
      "ErrorDetailList": []
    }
  ]
}

Currently, there isn’t any notification for when the change set status changes. You must continuously poll this API for the status. To view all status possibilities, visit the Catalog API documentation on ChangeSetSummaryListItem.

You have now successfully updated product details. In the following section, you add a new AMI version.

C. Adding a new AMI version

In this section, you use the same StartChangeSet API used in section A. Updating product details, but you use AddDeliveryOptions as the change type to add a new AMI version.

When you add a new AMI version, you are actually adding a delivery option inside the new AMI version. For single AMI products, each AMI version only has one delivery option.

To add a new AMI version, do the following steps in AWS CloudShell, replacing the values in italics with values specific to your product.

  1. If you haven’t already done so, create a service role that allows AWS Marketplace to assume and access your AMI image in your account. For step-by-step instructions on creating this IAM role, see Giving AWS Marketplace access to your AMI in the seller guide. Once you have the service role, locate and copy the ARN of the role by viewing its details in the IAM Management Console. An ARN is an Amazon Resource Name that uniquely identifies AWS resources. In this case, the ARN identifies the service role you created.
  2. Set a variable to the ARN of your service role by running the following command, replacing the information in italics with the ARN from step C.1.
    MP_ROLE_ARN="arn:aws:iam::123456789012:role/AwsMarketplaceAmiIngestion";
  3. Set a variable to the product ID of your product.
    PRODUCT_ID="example1-abcd-1234-5ef6-7890abcdef12";
  4. Set a variable to a JSON object that includes the details for this new version. In the following example, the new details for my product include a version title of 3.0.1, release notes called My new release notes and my new AMI ID ami-1234567890abcdef. It also includes an operating system (OS) name of Amazon Linux, my OS version, usage instructions, recommended instance type, and the allowed protocol, port, and IP range for the default security group.
    DETAILS_JSON='{
      "Version": {
        "VersionTitle": "3.0.1",
        "ReleaseNotes": "My new release notes"
      },
      "DeliveryOptions": [
        {
          "Details": {
            "AmiDeliveryOptionDetails": {
              "AmiSource": {
                "AmiId": "ami-1234567890abcdef",
                "AccessRoleArn": "'"${MP_ROLE_ARN}"'",
                "UserName": "ec2-user",
                "OperatingSystemName": "AMAZONLINUX",
                "OperatingSystemVersion": "4.14.133-113.112.amzn2.x86_64"
              },
              "UsageInstructions": "Connect via SSH and follow prompts.",
              "RecommendedInstanceType": "t2.medium",
              "SecurityGroups": [
                {
                  "IpProtocol": "tcp",
                  "FromPort": 443,
                  "ToPort": 443,
                  "IpRanges": [
                    "0.0.0.0/0"
                  ]
                }
              ]
            }
          }
        }
      ]
    }';
  5. Similar to step A.3 of, you must convert the JSON object into a JSON string so you can nest it into another JSON object as a string. To do that, run the following command. Use jq again to do the conversion and set the output to another variable called DETAILS_JSON_STRING.
    DETAILS_JSON_STRING="$(echo "${DETAILS_JSON}" | jq 'tostring';)";
  6. Run the following AWS CLI command for StartChangeSet API with the variables PRODUCT_ID and DETAILS_JSON_STRING from steps C.3 and 5. Use AddDeliveryOptions for the change type. This starts a change set to add a new AMI version.
    aws marketplace-catalog start-change-set \
    --catalog "AWSMarketplace" \
    --change-set '[
      {
        "ChangeType": "AddDeliveryOptions",
        "Entity": {
          "Identifier": "'"${PRODUCT_ID}"'",
          "Type": "AmiProduct@1.0"
        },
        "Details": '"${DETAILS_JSON_STRING}"'
      }
    ]';

    After running the command, your output should include the change set ID and the change set ARN.

    {
      "ChangeSetId": "example123456789012abcdef",
      "ChangeSetArn": "arn:aws:aws-marketplace:us-east-1:123456789012:AWSMarketplace/ChangeSet/example123456789012abcdef"
    }

    To get the status of your change set, repeat the steps in section B.

Since this is a new AMI version, it can take a few hours to complete. During this time, AWS Marketplace scans the AMI for critical vulnerabilities and copies it to the Regions your product is available in. If any issues are found, the status will show FAILED, and the reason will be provided. Make sure to review the seller guide on the best practices for building AMIs, the AMI product checklist, and the AMI security policies.

When the change set status changes to SUCCEEDED, your new version is immediately available.

  • If your product is in the limited state and has not been published publicly yet, it will stay in the limited state.
  • If your product is public in AWS Marketplace, this new version will be available to the public. Furthermore, your existing users will receive an email notifying them the new version is available, linking to the version’s release notes, and suggesting that they upgrade to the latest version. You will also receive a copy of the email sent to the email of the root user of the seller AWS account.

Your new version and existing version(s) will be available for buyers to select from on the configuration page of your product in AWS Marketplace. The following screenshot shows my example product configuration page in AWS Marketplace showing two available versions: 3.0.1 and 2.0.1 and their release dates.

In section E. Updating AMI version details, you will update the details of this AMI version. However, before you can do that, you must retrieve the delivery option ID that was created for this new AMI version. Section D. Describing AMI details shows how to retrieve your delivery option ID.

D. Describing AMI details

In this section, you retrieve the versions and AMI details of your product using DescribeEntity API and format it in the CLI for easier reading.

The purpose in this section is to locate a delivery option ID. A delivery option is created each time you add a new AMI version. Every AMI version of a single AMI product has one delivery option. You use this delivery option ID in the following sections E. Updating AMI version details and F. Restricting an AMI version to modify the usage instructions and restrict the delivery option of an AMI version.

To locate a delivery option ID, do the following steps in AWS CloudShell, replacing the values in italics with values specific to your product.

  1. Run the following AWS CLI command, replacing the product ID in italics with your product ID from step C.3.
    aws marketplace-catalog describe-entity \
    --catalog "AWSMarketplace" \
    --entity-id "example1-abcd-1234-5ef6-7890abcdef12";

    The actual output is long; the following example has been edited for brevity. Even so, it is a bit difficult to read, especially the Details property. The Details property is a JSON string with JSON control characters, such as double quotation marks, escaped.

    {
      "EntityType": "AmiProduct@1.0",
      "EntityIdentifier": "example1-abcd-1234-5ef6-7890abcdef12@3",
    ...
      "Details": "{\"Versions\":[{\"Id\":\"example2-0000-aaaa-5ef6-7890abcdef12\",\"ReleaseNotes\":\"My new release notes\",\"UpgradeInstructions\":null,\"VersionTitle\":\"3.0.1\",\"CreationDate\":\"2021-03-02T00:00:00.000Z\",\"Sources\":[{\"Id\":\"example3-1111-bbbb-5ef6-7890abcdef12\",\"Type\":\"AmazonMachineImage\",..."
    ...

  2. Since the Details property is what you need, run the command from step D.1 again, but use the --query filter of AWS CLI to select just the Details property.
    aws marketplace-catalog describe-entity \
    --catalog "AWSMarketplace" \
    --entity-id "example1-abcd-1234-5ef6-7890abcdef12" \
    --query 'Details';

    The following shows the Details property I received after running the command in this step.

    "{\"Versions\":[{\"Id\":\"example2-0000-aaaa-5ef6-7890abcdef12\",\"ReleaseNotes\":\"My new release notes\",\"UpgradeInstructions\":null,\"VersionTitle\":\"3.0.1\",\"CreationDate\":\"2021-03-02T00:00:00.000Z\",\"Sources\":[{\"Id\":\"example3-1111-bbbb-5ef6-7890abcdef12\",\"Type\":\"AmazonMachineImage\",..."

    Since the Details property is still a JSON string, you must parse and format it for readability.

  3. To output a pretty-formatted JSON object, use jq to parse the JSON string back into a JSON object. First, pipe | the Details property outputted into jq. Then, use its built-in function fromjson to clean it up, as shown in the following command:
aws marketplace-catalog describe-entity \
--catalog "AWSMarketplace" \
--entity-id "example1-abcd-1234-5ef6-7890abcdef12" \
--query 'Details' | jq 'fromjson';

The output should now look something like the following. This example has been edited for brevity.

{
  "Versions": [
    {
      "Id": "example2-0000-aaaa-0000-aaaaaaaaaaaa",
      "ReleaseNotes": "My new release notes",
      "UpgradeInstructions": null,
      "VersionTitle": "3.0.1",
      "CreationDate": "2021-03-02T00:00:00.000Z",
      "Sources": [
        {
          "Id": "example3-1111-bbbb-1111-bbbbbbbbbbbb",
          "Type": "AmazonMachineImage",
...
      "DeliveryOptions": [
        {
          "Id": "example4-2222-cccc-2222-cccccccccccc",
          "Type": "AmazonMachineImage",
          "SourceId": "example3-1111-bbbb-1111-bbbbbbbbbbbb",
          "ShortDescription": "No description provided for this delivery method",
          "Instructions": {
            "Usage": "Connect via SSH and follow prompts."
          },
          "Recommendations": {
            "SecurityGroups": [
              {
                "Protocol": "tcp",
                "FromPort": 443,
                "ToPort": 443,
                "CidrIps": [
                  "0.0.0.0/0"
                ]
...

Because you will be updating the AMI usage instruction in section E, copy the delivery option ID of the version you want to edit from this output. You can locate delivery option IDs in the JSON path Versions[].DeliveryOptions[].Id of the Details JSON. For the example output above, example4-2222-cccc-2222-cccccccccccc is the ID of the delivery option that we will update the usage instructions to in the following section.

  1. (Optional) Alternatively, you can use jq to do some additional filtering for you. For example, run the following AWS CLI command to find the delivery option ID by matching a specific VersionTitle.
    aws marketplace-catalog describe-entity \
    --catalog "AWSMarketplace" \
    --entity-id "example1-abcd-1234-5ef6-7890abcdef12" \
    --query 'Details' | jq --raw-output 'fromjson'\
    ' | .Versions[]'\
    ' | select(.VersionTitle == "3.0.1")'\
    ' | .DeliveryOptions[0].Id';

    The following is the output of this additional filtering.

    example4-2222-cccc-2222-cccccccccccc

E. Updating AMI version details

In this section, you update details of an AMI version using the StartChangeSet API, but with the change type UpdateDeliveryOptions.

In section D. Describing AMI details, you retrieved a delivery option ID. As a reminder, a delivery option is created each time you add a new AMI version.

To update AMI version details, do the following steps in AWS CloudShell, replacing the values in italics with values specific to your product.

  1. In AWS CloudShell, set a variable to the delivery option ID from section D. Describing AMI details.
    DELIVERY_OPTION_ID="example4-2222-cccc-2222-cccccccccccc";
  2. Set a variable to the product ID of your product.
    PRODUCT_ID="example1-abcd-1234-5ef6-7890abcdef12";

    In this section, you are only updating the usage instructions for this AMI version. You can update other details as well. Refer to the Catalog API documentation for a full list of available product details that can be changed. Any details omitted in your request will use the values in the latest version.

  3. Set a variable to a JSON object with the new usage instructions included.
    DETAILS_JSON='{
      "DeliveryOptions": [
        {
          "Id": "'"${DELIVERY_OPTION_ID}"'",
          "Details": {
            "AmiDeliveryOptionDetails": {
              "UsageInstructions": "Updated usage instructions"
            }
          }
        }
      ]
    }';
  4. Similar to step A.3, you must convert the JSON object into a JSON string so you can nest it into another JSON object as a string. Run the following command. Use jq again to do the conversion and set the output to another variable called DETAILS_JSON_STRING.
    DETAILS_JSON_STRING="$(echo "${DETAILS_JSON}" | jq 'tostring';)";
  5. Run the following AWS CLI command for StartChangeSet API with the variables PRODUCT_ID and DETAILS_JSON_STRING from steps E.2 and 4. Use UpdateDeliveryOptions for the change type. This starts a change set to update the details of the delivery option of the AMI version.
    aws marketplace-catalog start-change-set \
    --catalog "AWSMarketplace" \
    --change-set '[{
      "ChangeType": "UpdateDeliveryOptions",
      "Entity": {
        "Identifier": "'"${PRODUCT_ID}"'",
        "Type": "AmiProduct@1.0"
      },
      "Details": '"${DETAILS_JSON_STRING}"'
    }]';

    After running the command, your output should include the change set ID and the change set ARN.

    {
      "ChangeSetId": "example123456789012abcdef",
      "ChangeSetArn": "arn:aws:aws-marketplace:us-east-1:123456789012:AWSMarketplace/ChangeSet/example123456789012abcdef"
    }

    To get the status of your change set, repeat the steps in section B. Describing update status.

F. Restricting an AMI version

In this final section, you restrict an AMI version from your product. To do this, you use the StartChangeSet API again, but with the change type RestrictDeliveryOptions.

Restricting an AMI version prevents new buyers from accessing that specific version of your public product. For more information on how it affects existing user, see the Seller guide on restricting a version.

You can only restrict a version if the product is live in AWS Marketplace. This change type will not work for products still in the limited state.

In section D. Describing AMI details, you retrieved a delivery option ID. As a reminder, a delivery option is created each time you add a new AMI version.

To restrict an AMI version, do the following steps in AWS CloudShell, replacing the values in italics with values specific to your product.

  1. Set a variable to the product ID of your product.
    PRODUCT_ID="example1-abcd-1234-5ef6-7890abcdef12";
  2. Set a variable to the delivery option ID from section D. Describing AMI details.
    DETAILS_JSON='{
      "DeliveryOptionIds": [
        "example4-2222-cccc-2222-cccccccccccc"
      ]
    }';
  3. Similar to step A.3, you must convert the JSON object into a JSON string so that you can nest it into another JSON object as a string. Run the following command and use jq again to do the conversion and set the output to another variable called DETAILS_JSON_STRING.
    DETAILS_JSON_STRING="$(echo "${DETAILS_JSON}" | jq 'tostring';)";
  4. Run the following AWS CLI command for StartChangeSet API with the variables PRODUCT_ID and DETAILS_JSON_STRING from steps F.1 and 3. Use RestrictDeliveryOptions for the change type. This starts a change set to restrict the delivery option of the AMI version.
    aws marketplace-catalog start-change-set \
    --catalog "AWSMarketplace" \
    --change-set '[
      {
        "ChangeType": "RestrictDeliveryOptions",
        "Entity": {
          "Identifier": "'"${PRODUCT_ID}"'",
          "Type": "AmiProduct@1.0"
        },
        "Details": '"${DETAILS_JSON_STRING}"'
      }
    ]';

    After running the command, your output should include the change set ID and the change set ARN. My output looks like this:

    {
      "ChangeSetId": "example123456789012abcdef",
      "ChangeSetArn": "arn:aws:aws-marketplace:us-east-1:123456789012:AWSMarketplace/ChangeSet/example123456789012abcdef"
    }

    To get the status of your change set, repeat the steps in section B.

Conclusion and next steps

In this post, I showed how to use Catalog API to update your AMI listings. I showed how to update product details, describe the update status, add a new AMI version, and describe AMI details. I also showed how to update AMI version details and restrict an AMI version.

Catalog API can help you automate how you manage your single-AMI and Container products in AWS Marketplace.

For more information, see the Catalog API documentation. As you integrate this with your release process or CI/CD pipelines, keep in mind the Catalog API service limits.

To get started, visit the documentation page here: https://docs.aws.amazon.com/marketplace-catalog/latest/api-reference/ami-products.html

About the author

Profile picture of Joseph Shih, Senior Partner Solutions Architect, AWS Marketplace

Joseph Shih is a Senior Partner Solutions Architect focusing on AWS Marketplace and is passionate about application development, serverless technology, and DevOps. He believes code increases productivity in every workplace, industry, and home, and his dream is to write software that changes the world and transforms lives.